Bugzilla bug #17223: added the PR_MSG_PEEK (with same value as MSG_PEEK)

for PR_Recv().  Define _PR_EMULATE_MSG_PEEK on platforms that don't
natively support MSG_PEEK.  Implemented PR_MSG_PEEK for pthreads.
Added the peek.c test case.
Modified files: prio.h, _macos.h, _winnt.h, primpl.h, ptio.c,
pr/tests/Makefile, pr/tests/Makefile.in
Added file: pr/tests/peek.c
This commit is contained in:
wtc%netscape.com 2000-05-03 01:22:54 +00:00
Родитель ed35421751
Коммит fcd37d3a17
8 изменённых файлов: 397 добавлений и 7 удалений

Просмотреть файл

@ -46,6 +46,8 @@
#include <setjmp.h>
#include <Errors.h>
#define _PR_EMULATE_MSG_PEEK
struct _MDProcess {
PRInt8 notused;
};

Просмотреть файл

@ -50,6 +50,7 @@
#define _PR_HAVE_ATOMIC_OPS
#define _PR_HAVE_ATOMIC_CAS
#define PR_HAVE_WIN32_NAMED_SHARED_MEMORY
#define _PR_EMULATE_MSG_PEEK
/* --- Common User-Thread/Native-Thread Definitions --------------------- */

Просмотреть файл

@ -1343,7 +1343,7 @@ NSPR_API(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how);
* PRInt32 amount
* the size of 'buf' (in bytes)
* PRIntn flags
* (OBSOLETE - must always be zero)
* must be zero or PR_MSG_PEEK.
* PRIntervalTime timeout
* Time limit for completion of the receive operation.
* OUTPUTS:
@ -1356,6 +1356,8 @@ NSPR_API(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how);
**************************************************************************
*/
#define PR_MSG_PEEK 0x2
NSPR_API(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
PRIntn flags, PRIntervalTime timeout);

Просмотреть файл

@ -1577,6 +1577,11 @@ struct PRFilePrivate {
PRBool inheritable;
PRFileDesc *next;
PRIntn lockCount;
#ifdef _PR_EMULATE_MSG_PEEK
char *peekBuf;
PRInt32 peekBufSize;
PRInt32 peekBytes;
#endif
_MDFileDesc md;
};

Просмотреть файл

@ -658,8 +658,12 @@ static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)
* error we continue is EWOULDBLOCK|EAGAIN.
*/
#if defined(SOLARIS)
op->result.code = read(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
if (0 == op->arg4.flags)
op->result.code = read(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
else
op->result.code = recv(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
#else
op->result.code = recv(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
@ -1524,15 +1528,28 @@ static PRInt32 pt_Recv(
PRIntn flags, PRIntervalTime timeout)
{
PRInt32 syserrno, bytes = -1;
PRIntn osflags;
if (0 == flags)
osflags = 0;
else if (PR_MSG_PEEK == flags)
osflags = MSG_PEEK;
else
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return bytes;
}
if (pt_TestAbort()) return bytes;
/* recv() is a much slower call on pre-2.6 Solaris than read(). */
#if defined(SOLARIS)
PR_ASSERT(0 == flags);
bytes = read(fd->secret->md.osfd, buf, amount);
if (0 == osflags)
bytes = read(fd->secret->md.osfd, buf, amount);
else
bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
#else
bytes = recv(fd->secret->md.osfd, buf, amount, flags);
bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
#endif
syserrno = errno;
@ -1546,7 +1563,7 @@ static PRInt32 pt_Recv(
op.arg1.osfd = fd->secret->md.osfd;
op.arg2.buffer = buf;
op.arg3.amount = amount;
op.arg4.flags = flags;
op.arg4.flags = osflags;
op.timeout = timeout;
op.function = pt_recv_cont;
op.event = POLLIN | POLLPRI;

Просмотреть файл

@ -105,6 +105,7 @@ CSRCS = \
op_nofil.c \
openfile.c \
parent.c \
peek.c \
perf.c \
pipeping.c \
pipepong.c \

Просмотреть файл

@ -109,6 +109,7 @@ CSRCS = \
op_nofil.c \
openfile.c \
parent.c \
peek.c \
perf.c \
pipeping.c \
pipepong.c \

361
nsprpub/pr/tests/peek.c Normal file
Просмотреть файл

@ -0,0 +1,361 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* A test case for the PR_MSG_PEEK flag of PR_Recv().
*
* Test both blocking and non-blocking sockets.
*/
#include "nspr.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1024
static int iterations = 10;
/*
* In iteration i, recv_amount[i] is the number of bytes we
* wish to receive, and send_amount[i] is the number of bytes
* we actually send. Therefore, the number of elements in the
* recv_amount or send_amount array should equal to 'iterations'.
* For this test to pass we need to ensure that
* recv_amount[i] <= BUFFER_SIZE,
* send_amount[i] <= BUFFER_SIZE,
* send_amount[i] <= recv_amount[i].
*/
static PRInt32 recv_amount[10] = {
16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
static PRInt32 send_amount[10] = {
16, 64, 128, 1024, 512, 256, 128, 64, 16, 32};
/* Blocking I/O */
static void ServerB(void *arg)
{
PRFileDesc *listenSock = (PRFileDesc *) arg;
PRFileDesc *sock;
char buf[BUFFER_SIZE];
PRInt32 nbytes;
int i;
int j;
sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
if (NULL == sock) {
fprintf(stderr, "PR_Accept failed\n");
exit(1);
}
for (i = 0; i < iterations; i++) {
memset(buf, 0, sizeof(buf));
nbytes = PR_Recv(sock, buf, recv_amount[i],
PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i, buf[j]);
exit(1);
}
}
fprintf(stderr, "server: peeked expected data\n");
memset(buf, 0, sizeof(buf));
nbytes = PR_Recv(sock, buf, recv_amount[i],
PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i, buf[j]);
exit(1);
}
}
fprintf(stderr, "server: peeked expected data\n");
memset(buf, 0, sizeof(buf));
nbytes = PR_Recv(sock, buf, recv_amount[i],
0, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i, buf[j]);
exit(1);
}
}
fprintf(stderr, "server: received expected data\n");
PR_Sleep(PR_SecondsToInterval(1));
memset(buf, 2*i+1, send_amount[i]);
nbytes = PR_Send(sock, buf, send_amount[i],
0, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Send failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
exit(1);
}
}
if (PR_Close(sock) == PR_FAILURE) {
fprintf(stderr, "PR_Close failed\n");
exit(1);
}
}
/* Non-blocking I/O */
static void ClientNB(void *arg)
{
PRFileDesc *sock;
PRSocketOptionData opt;
PRUint16 port = (PRUint16) arg;
PRNetAddr addr;
char buf[BUFFER_SIZE];
PRPollDesc pd;
PRInt32 npds;
PRInt32 nbytes;
int i;
int j;
sock = PR_OpenTCPSocket(PR_AF_INET6);
if (NULL == sock) {
fprintf(stderr, "PR_OpenTCPSocket failed\n");
exit(1);
}
opt.option = PR_SockOpt_Nonblocking;
opt.value.non_blocking = PR_TRUE;
if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
fprintf(stderr, "PR_SetSocketOption failed\n");
exit(1);
}
memset(&addr, 0, sizeof(addr));
if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
== PR_FAILURE) {
fprintf(stderr, "PR_SetNetAddr failed\n");
exit(1);
}
if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
fprintf(stderr, "PR_Connect failed\n");
exit(1);
}
pd.fd = sock;
pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
if (-1 == npds) {
fprintf(stderr, "PR_Poll failed\n");
exit(1);
}
if (1 != npds) {
fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
exit(1);
}
if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
fprintf(stderr, "PR_GetConnectStatus failed\n");
exit(1);
}
}
for (i = 0; i < iterations; i++) {
PR_Sleep(PR_SecondsToInterval(1));
memset(buf, 2*i, send_amount[i]);
while ((nbytes = PR_Send(sock, buf, send_amount[i],
0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
fprintf(stderr, "PR_Send failed\n");
exit(1);
}
pd.fd = sock;
pd.in_flags = PR_POLL_WRITE;
npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
if (-1 == npds) {
fprintf(stderr, "PR_Poll failed\n");
exit(1);
}
if (1 != npds) {
fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
exit(1);
}
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
exit(1);
}
memset(buf, 0, sizeof(buf));
while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
pd.fd = sock;
pd.in_flags = PR_POLL_READ;
npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
if (-1 == npds) {
fprintf(stderr, "PR_Poll failed\n");
exit(1);
}
if (1 != npds) {
fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
exit(1);
}
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i+1) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i+1, buf[j]);
exit(1);
}
}
fprintf(stderr, "client: peeked expected data\n");
memset(buf, 0, sizeof(buf));
nbytes = PR_Recv(sock, buf, recv_amount[i],
PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i+1) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i+1, buf[j]);
exit(1);
}
}
fprintf(stderr, "client: peeked expected data\n");
memset(buf, 0, sizeof(buf));
nbytes = PR_Recv(sock, buf, recv_amount[i],
0, PR_INTERVAL_NO_TIMEOUT);
if (-1 == nbytes) {
fprintf(stderr, "PR_Recv failed\n");
exit(1);
}
if (send_amount[i] != nbytes) {
fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
exit(1);
}
for (j = 0; j < nbytes; j++) {
if (buf[j] != 2*i+1) {
fprintf(stderr, "byte %d should be %d but is %d\n",
j, 2*i+1, buf[j]);
exit(1);
}
}
fprintf(stderr, "client: received expected data\n");
}
if (PR_Close(sock) == PR_FAILURE) {
fprintf(stderr, "PR_Close failed\n");
exit(1);
}
}
int main(int argc, char **argv)
{
PRThread *server, *client;
PRFileDesc *listenSock;
PRNetAddr addr;
PRThreadScope scope = PR_GLOBAL_THREAD;
listenSock = PR_OpenTCPSocket(PR_AF_INET6);
if (NULL == listenSock) {
fprintf(stderr, "PR_OpenTCPSocket failed\n");
exit(1);
}
memset(&addr, 0, sizeof(addr));
if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
fprintf(stderr, "PR_SetNetAddr failed\n");
exit(1);
}
if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
fprintf(stderr, "PR_Bind failed\n");
exit(1);
}
if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
fprintf(stderr, "PR_GetSockName failed\n");
exit(1);
}
if (PR_Listen(listenSock, 5) == PR_FAILURE) {
fprintf(stderr, "PR_Listen failed\n");
exit(1);
}
server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock,
PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
if (NULL == server) {
fprintf(stderr, "PR_CreateThread failed\n");
exit(1);
}
client = PR_CreateThread(
PR_USER_THREAD, ClientNB, (void *) PR_ntohs(addr.ipv6.port),
PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
if (NULL == client) {
fprintf(stderr, "PR_CreateThread failed\n");
exit(1);
}
if (PR_JoinThread(server) == PR_FAILURE) {
fprintf(stderr, "PR_JoinThread failed\n");
exit(1);
}
if (PR_JoinThread(client) == PR_FAILURE) {
fprintf(stderr, "PR_JoinThread failed\n");
exit(1);
}
if (PR_Close(listenSock) == PR_FAILURE) {
fprintf(stderr, "PR_Close failed\n");
exit(1);
}
printf("PASS\n");
return 0;
}