Back to index

lightning-sunbird  0.9+nobinonly
peek.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * A test case for the PR_MSG_PEEK flag of PR_Recv().
00040  *
00041  * Test both blocking and non-blocking sockets.
00042  */
00043 
00044 #include "nspr.h"
00045 
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 
00050 #define BUFFER_SIZE 1024
00051 
00052 static int iterations = 10;
00053 
00054 /*
00055  * In iteration i, recv_amount[i] is the number of bytes we
00056  * wish to receive, and send_amount[i] is the number of bytes
00057  * we actually send.  Therefore, the number of elements in the
00058  * recv_amount or send_amount array should equal to 'iterations'.
00059  * For this test to pass we need to ensure that
00060  *     recv_amount[i] <= BUFFER_SIZE,
00061  *     send_amount[i] <= BUFFER_SIZE,
00062  *     send_amount[i] <= recv_amount[i].
00063  */
00064 static PRInt32 recv_amount[10] = {
00065     16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
00066 static PRInt32 send_amount[10] = {
00067     16,  64, 128, 1024, 512, 256, 128,  64, 16, 32};
00068 
00069 /* Blocking I/O */
00070 static void ServerB(void *arg)
00071 {
00072     PRFileDesc *listenSock = (PRFileDesc *) arg;
00073     PRFileDesc *sock;
00074     char buf[BUFFER_SIZE];
00075     PRInt32 nbytes;
00076     int i;
00077     int j;
00078 
00079     sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
00080     if (NULL == sock) {
00081         fprintf(stderr, "PR_Accept failed\n");
00082         exit(1);
00083     }
00084 
00085     for (i = 0; i < iterations; i++) {
00086         memset(buf, 0, sizeof(buf));
00087         nbytes = PR_Recv(sock, buf, recv_amount[i],
00088                 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
00089         if (-1 == nbytes) {
00090             fprintf(stderr, "PR_Recv failed\n");
00091             exit(1);
00092         }
00093         if (send_amount[i] != nbytes) {
00094             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00095             exit(1);
00096         }
00097         for (j = 0; j < nbytes; j++) {
00098             if (buf[j] != 2*i) {
00099                 fprintf(stderr, "byte %d should be %d but is %d\n",
00100                         j, 2*i, buf[j]);
00101                 exit(1);
00102             }
00103         }
00104         fprintf(stderr, "server: peeked expected data\n");
00105 
00106         memset(buf, 0, sizeof(buf));
00107         nbytes = PR_Recv(sock, buf, recv_amount[i],
00108                 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
00109         if (-1 == nbytes) {
00110             fprintf(stderr, "PR_Recv failed\n");
00111             exit(1);
00112         }
00113         if (send_amount[i] != nbytes) {
00114             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00115             exit(1);
00116         }
00117         for (j = 0; j < nbytes; j++) {
00118             if (buf[j] != 2*i) {
00119                 fprintf(stderr, "byte %d should be %d but is %d\n",
00120                         j, 2*i, buf[j]);
00121                 exit(1);
00122             }
00123         }
00124         fprintf(stderr, "server: peeked expected data\n");
00125 
00126         memset(buf, 0, sizeof(buf));
00127         nbytes = PR_Recv(sock, buf, recv_amount[i],
00128                 0, PR_INTERVAL_NO_TIMEOUT);
00129         if (-1 == nbytes) {
00130             fprintf(stderr, "PR_Recv failed\n");
00131             exit(1);
00132         }
00133         if (send_amount[i] != nbytes) {
00134             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00135             exit(1);
00136         }
00137         for (j = 0; j < nbytes; j++) {
00138             if (buf[j] != 2*i) {
00139                 fprintf(stderr, "byte %d should be %d but is %d\n",
00140                         j, 2*i, buf[j]);
00141                 exit(1);
00142             }
00143         }
00144         fprintf(stderr, "server: received expected data\n");
00145 
00146         PR_Sleep(PR_SecondsToInterval(1));
00147         memset(buf, 2*i+1, send_amount[i]);
00148         nbytes = PR_Send(sock, buf, send_amount[i],
00149                 0, PR_INTERVAL_NO_TIMEOUT);
00150         if (-1 == nbytes) {
00151             fprintf(stderr, "PR_Send failed\n");
00152             exit(1);
00153         }
00154         if (send_amount[i] != nbytes) {
00155             fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
00156             exit(1);
00157         }
00158     }
00159     if (PR_Close(sock) == PR_FAILURE) {
00160         fprintf(stderr, "PR_Close failed\n");
00161         exit(1);
00162     }
00163 }
00164 
00165 /* Non-blocking I/O */
00166 static void ClientNB(void *arg)
00167 {
00168     PRFileDesc *sock;
00169     PRSocketOptionData opt;
00170     PRUint16 port = (PRUint16) arg;
00171     PRNetAddr addr;
00172     char buf[BUFFER_SIZE];
00173     PRPollDesc pd;
00174     PRInt32 npds;
00175     PRInt32 nbytes;
00176     int i;
00177     int j;
00178 
00179     sock = PR_OpenTCPSocket(PR_AF_INET6);
00180     if (NULL == sock) {
00181         fprintf(stderr, "PR_OpenTCPSocket failed\n");
00182         exit(1);
00183     }
00184     opt.option = PR_SockOpt_Nonblocking;
00185     opt.value.non_blocking = PR_TRUE;
00186     if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
00187         fprintf(stderr, "PR_SetSocketOption failed\n");
00188         exit(1);
00189     }
00190     memset(&addr, 0, sizeof(addr));
00191     if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
00192             == PR_FAILURE) {
00193         fprintf(stderr, "PR_SetNetAddr failed\n");
00194         exit(1);
00195     }
00196     if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
00197         if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
00198             fprintf(stderr, "PR_Connect failed\n");
00199             exit(1);
00200         }
00201         pd.fd = sock;
00202         pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
00203         npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
00204         if (-1 == npds) {
00205             fprintf(stderr, "PR_Poll failed\n");
00206             exit(1);
00207         }
00208         if (1 != npds) {
00209             fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
00210             exit(1);
00211         }
00212         if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
00213             fprintf(stderr, "PR_GetConnectStatus failed\n");
00214             exit(1);
00215         }
00216     }
00217 
00218     for (i = 0; i < iterations; i++) {
00219         PR_Sleep(PR_SecondsToInterval(1));
00220         memset(buf, 2*i, send_amount[i]);
00221         while ((nbytes = PR_Send(sock, buf, send_amount[i],
00222                 0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
00223             if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
00224                 fprintf(stderr, "PR_Send failed\n");
00225                 exit(1);
00226             }
00227             pd.fd = sock;
00228             pd.in_flags = PR_POLL_WRITE;
00229             npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
00230             if (-1 == npds) {
00231                 fprintf(stderr, "PR_Poll failed\n");
00232                 exit(1);
00233             }
00234             if (1 != npds) {
00235                 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
00236                 exit(1);
00237             }
00238         }
00239         if (send_amount[i] != nbytes) {
00240             fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
00241             exit(1);
00242         }
00243 
00244         memset(buf, 0, sizeof(buf));
00245         while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
00246                 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
00247             if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
00248                 fprintf(stderr, "PR_Recv failed\n");
00249                 exit(1);
00250             }
00251             pd.fd = sock;
00252             pd.in_flags = PR_POLL_READ;
00253             npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
00254             if (-1 == npds) {
00255                 fprintf(stderr, "PR_Poll failed\n");
00256                 exit(1);
00257             }
00258             if (1 != npds) {
00259                 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
00260                 exit(1);
00261             }
00262         }
00263         if (send_amount[i] != nbytes) {
00264             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00265             exit(1);
00266         }
00267         for (j = 0; j < nbytes; j++) {
00268             if (buf[j] != 2*i+1) {
00269                 fprintf(stderr, "byte %d should be %d but is %d\n",
00270                         j, 2*i+1, buf[j]);
00271                 exit(1);
00272             }
00273         }
00274         fprintf(stderr, "client: peeked expected data\n");
00275 
00276         memset(buf, 0, sizeof(buf));
00277         nbytes = PR_Recv(sock, buf, recv_amount[i],
00278                 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
00279         if (-1 == nbytes) {
00280             fprintf(stderr, "PR_Recv failed\n");
00281             exit(1);
00282         }
00283         if (send_amount[i] != nbytes) {
00284             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00285             exit(1);
00286         }
00287         for (j = 0; j < nbytes; j++) {
00288             if (buf[j] != 2*i+1) {
00289                 fprintf(stderr, "byte %d should be %d but is %d\n",
00290                         j, 2*i+1, buf[j]);
00291                 exit(1);
00292             }
00293         }
00294         fprintf(stderr, "client: peeked expected data\n");
00295 
00296         memset(buf, 0, sizeof(buf));
00297         nbytes = PR_Recv(sock, buf, recv_amount[i],
00298                 0, PR_INTERVAL_NO_TIMEOUT);
00299         if (-1 == nbytes) {
00300             fprintf(stderr, "PR_Recv failed\n");
00301             exit(1);
00302         }
00303         if (send_amount[i] != nbytes) {
00304             fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
00305             exit(1);
00306         }
00307         for (j = 0; j < nbytes; j++) {
00308             if (buf[j] != 2*i+1) {
00309                 fprintf(stderr, "byte %d should be %d but is %d\n",
00310                         j, 2*i+1, buf[j]);
00311                 exit(1);
00312             }
00313         }
00314         fprintf(stderr, "client: received expected data\n");
00315     }
00316     if (PR_Close(sock) == PR_FAILURE) {
00317         fprintf(stderr, "PR_Close failed\n");
00318         exit(1);
00319     }
00320 }
00321 
00322 static void
00323 RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port)
00324 {
00325     PRThread *server, *client;
00326 
00327     server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock,
00328             PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
00329     if (NULL == server) {
00330         fprintf(stderr, "PR_CreateThread failed\n");
00331         exit(1);
00332     }
00333     client = PR_CreateThread(
00334             PR_USER_THREAD, ClientNB, (void *) port,
00335             PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
00336     if (NULL == client) {
00337         fprintf(stderr, "PR_CreateThread failed\n");
00338         exit(1);
00339     }
00340 
00341     if (PR_JoinThread(server) == PR_FAILURE) {
00342         fprintf(stderr, "PR_JoinThread failed\n");
00343         exit(1);
00344     }
00345     if (PR_JoinThread(client) == PR_FAILURE) {
00346         fprintf(stderr, "PR_JoinThread failed\n");
00347         exit(1);
00348     }
00349 }
00350 
00351 int main(int argc, char **argv)
00352 {
00353     PRFileDesc *listenSock;
00354     PRNetAddr addr;
00355     PRUint16 port;
00356 
00357     listenSock = PR_OpenTCPSocket(PR_AF_INET6);
00358     if (NULL == listenSock) {
00359         fprintf(stderr, "PR_OpenTCPSocket failed\n");
00360         exit(1);
00361     }
00362     memset(&addr, 0, sizeof(addr));
00363     if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
00364         fprintf(stderr, "PR_SetNetAddr failed\n");
00365         exit(1);
00366     }
00367     if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
00368         fprintf(stderr, "PR_Bind failed\n");
00369         exit(1);
00370     }
00371     if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
00372         fprintf(stderr, "PR_GetSockName failed\n");
00373         exit(1);
00374     }
00375     port = PR_ntohs(addr.ipv6.port);
00376     if (PR_Listen(listenSock, 5) == PR_FAILURE) {
00377         fprintf(stderr, "PR_Listen failed\n");
00378         exit(1);
00379     }
00380 
00381     fprintf(stderr, "Running the test with local threads\n");
00382     RunTest(PR_LOCAL_THREAD, listenSock, port);
00383     fprintf(stderr, "Running the test with global threads\n");
00384     RunTest(PR_GLOBAL_THREAD, listenSock, port);
00385 
00386     if (PR_Close(listenSock) == PR_FAILURE) {
00387         fprintf(stderr, "PR_Close failed\n");
00388         exit(1);
00389     }
00390     printf("PASS\n");
00391     return 0;
00392 }