nsprpub/pr/tests/udpsrv.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*******************************************************************
     7 ** udpsrc.c -- Test basic function of UDP server
     8 **
     9 ** udpsrv operates on the same machine with program udpclt.
    10 ** udpsrv is the server side of a udp sockets application.
    11 ** udpclt is the client side of a udp sockets application.
    12 **
    13 ** The test is designed to assist developers in porting/debugging
    14 ** the UDP socket functions of NSPR.
    15 **
    16 ** This test is not a stress test.
    17 **
    18 ** main() starts two threads: UDP_Server() and UDP_Client();
    19 ** main() uses PR_JoinThread() to wait for the threads to complete.
    20 **
    21 ** UDP_Server() does repeated recvfrom()s from a socket.
    22 ** He detects an EOF condition set by UDP_Client(). For each
    23 ** packet received by UDP_Server(), he checks its content for
    24 ** expected content, then sends the packet back to UDP_Client().
    25 ** 
    26 ** UDP_Client() sends packets to UDP_Server() using sendto()
    27 ** he recieves packets back from the server via recvfrom().
    28 ** After he sends enough packets containing UDP_AMOUNT_TO_WRITE
    29 ** bytes of data, he sends an EOF message.
    30 ** 
    31 ** The test issues a pass/fail message at end.
    32 ** 
    33 ** Notes:
    34 ** The variable "_debug_on" can be set to 1 to cause diagnostic
    35 ** messages related to client/server synchronization. Useful when
    36 ** the test hangs.
    37 ** 
    38 ** Error messages are written to stdout.
    39 ** 
    40 ********************************************************************
    41 */
    42 /* --- include files --- */
    43 #include "nspr.h"
    44 #include "prpriv.h"
    46 #include "plgetopt.h"
    47 #include "prttools.h"
    49 #include <stdio.h>
    50 #include <stdlib.h>
    51 #include <string.h>
    52 #include <errno.h>
    54 #ifdef XP_PC
    55 #define mode_t int
    56 #endif
    58 #define UDP_BUF_SIZE            4096
    59 #define UDP_DGRAM_SIZE          128
    60 #define UDP_AMOUNT_TO_WRITE     (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1)
    61 #define NUM_UDP_CLIENTS         1
    62 #define NUM_UDP_DATAGRAMS_PER_CLIENT    5
    63 #define UDP_SERVER_PORT         9050
    64 #define UDP_CLIENT_PORT         9053
    65 #define MY_INADDR               PR_INADDR_ANY
    66 #define PEER_INADDR             PR_INADDR_LOOPBACK
    68 #define UDP_TIMEOUT             400000
    69 /* #define UDP_TIMEOUT             PR_INTERVAL_NO_TIMEOUT */
    71 /* --- static data --- */
    72 static PRIntn _debug_on      = 0;
    73 static PRBool passed         = PR_TRUE;
    74 static PRUint32 cltBytesRead = 0;
    75 static PRUint32 srvBytesRead = 0;
    76 static PRFileDesc *output    = NULL;
    78 /* --- static function declarations --- */
    79 #define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
    83 /*******************************************************************
    84 ** ListNetAddr() -- Display the Net Address on stdout
    85 **
    86 ** Description: displays the component parts of a PRNetAddr struct
    87 **
    88 ** Arguments:   address of PRNetAddr structure to display
    89 **
    90 ** Returns: void
    91 **
    92 ** Notes:
    93 **
    94 ********************************************************************
    95 */
    96 void ListNetAddr( char *msg, PRNetAddr *na )
    97 {
    98     char    mbuf[256];
   100     sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n",
   101             msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) );
   102 #if 0            
   103     DPRINTF( mbuf );            
   104 #endif
   105 } /* --- end ListNetAddr() --- */
   107 /********************************************************************
   108 ** UDP_Server() -- Test a UDP server application
   109 **
   110 ** Description: The Server side of a UDP Client/Server application.
   111 **
   112 ** Arguments: none
   113 **
   114 ** Returns: void
   115 **
   116 ** Notes:
   117 **
   118 **
   119 ********************************************************************
   120 */
   121 static void PR_CALLBACK UDP_Server( void *arg )
   122 {
   123     static char     svrBuf[UDP_BUF_SIZE];
   124     PRFileDesc      *svrSock;
   125     PRInt32         rv;
   126     PRNetAddr       netaddr;
   127     PRBool          bound = PR_FALSE;
   128     PRBool          endOfInput = PR_FALSE;
   129     PRInt32         numBytes = UDP_DGRAM_SIZE;
   131     DPRINTF("udpsrv: UDP_Server(): starting\n" );
   133     /* --- Create the socket --- */
   134     DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" );
   135     svrSock = PR_NewUDPSocket();
   136     if ( svrSock == NULL )
   137     {
   138         passed = PR_FALSE;
   139         if (debug_mode)
   140             PR_fprintf(output,
   141                 "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
   142         return;
   143     }
   145     /* --- Initialize the sockaddr_in structure --- */
   146     memset( &netaddr, 0, sizeof( netaddr )); 
   147     netaddr.inet.family = PR_AF_INET;
   148     netaddr.inet.port   = PR_htons( UDP_SERVER_PORT );
   149     netaddr.inet.ip     = PR_htonl( MY_INADDR );
   151     /* --- Bind the socket --- */
   152     while ( !bound )
   153     {
   154         DPRINTF("udpsrv: UDP_Server(): Binding socket\n" );
   155         rv = PR_Bind( svrSock, &netaddr );
   156         if ( rv < 0 )
   157         {
   158             if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
   159             {
   160                 if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
   161 						PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
   162                 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
   163                 continue;
   164             }
   165             else
   166             {
   167                 passed = PR_FALSE;
   168                 if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
   169 						PR_Bind(): failed: %ld with error: %ld\n",
   170                         rv, PR_GetError() );
   171                 PR_Close( svrSock );
   172                 return;
   173             }
   174         }
   175         else
   176             bound = PR_TRUE;
   177     }
   178     ListNetAddr( "UDP_Server: after bind", &netaddr );
   180     /* --- Recv the socket --- */
   181     while( !endOfInput )
   182     {
   183         DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" );
   184         rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
   185         if ( rv == -1 )
   186         {
   187             passed = PR_FALSE;
   188             if (debug_mode)
   189                 PR_fprintf(output,
   190                     "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
   191                     PR_GetError() );
   192             PR_Close( svrSock );
   193             return;
   194         }
   195         ListNetAddr( "UDP_Server after RecvFrom", &netaddr );
   197         srvBytesRead += rv;
   199         if ( svrBuf[0] == 'E' )
   200         {
   201             DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" );
   202             endOfInput = PR_TRUE;
   203         }
   205         /* --- Send the socket --- */
   206         DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" );
   207         rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT );
   208         if ( rv == -1 )
   209         {
   210             passed = PR_FALSE;
   211             if (debug_mode)
   212                 PR_fprintf(output,
   213                     "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
   214                     PR_GetError() );
   215             PR_Close( svrSock );
   216             return;
   217         }
   218         ListNetAddr( "UDP_Server after SendTo", &netaddr );
   219     }
   221     /* --- Close the socket --- */
   222     DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
   223     rv = PR_Close( svrSock );
   224     if ( rv != PR_SUCCESS )
   225     {
   226         passed = PR_FALSE;
   227         if (debug_mode)
   228             PR_fprintf(output,
   229                 "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
   230         return;
   231     }
   233     DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
   234 } /* --- end UDP_Server() --- */
   237 static char         cltBuf[UDP_BUF_SIZE];
   238 static char         cltBufin[UDP_BUF_SIZE];
   239 /********************************************************************
   240 ** UDP_Client() -- Test a UDP client application
   241 **
   242 ** Description:
   243 **
   244 ** Arguments:
   245 **
   246 **
   247 ** Returns:
   248 ** 0 -- Successful execution
   249 ** 1 -- Test failed.
   250 **
   251 ** Notes:
   252 **
   253 **
   254 ********************************************************************
   255 */
   256 static void PR_CALLBACK UDP_Client( void *arg )
   257 {
   258     PRFileDesc   *cltSock;
   259     PRInt32      rv;
   260     PRBool       bound = PR_FALSE;
   261     PRNetAddr    netaddr;
   262     PRNetAddr    netaddrx;
   263     PRBool       endOfInput = PR_FALSE;
   264     PRInt32      numBytes = UDP_DGRAM_SIZE;
   265     PRInt32      writeThisMany = UDP_AMOUNT_TO_WRITE;
   266     int          i;
   269     DPRINTF("udpsrv: UDP_Client(): starting\n" );
   271     /* --- Create the socket --- */
   272     cltSock = PR_NewUDPSocket();
   273     if ( cltSock == NULL )
   274     {
   275         passed = PR_FALSE;
   276         if (debug_mode)
   277             PR_fprintf(output,
   278                 "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
   279         return;
   280     }
   282     /* --- Initialize the sockaddr_in structure --- */
   283     memset( &netaddr, 0, sizeof( netaddr )); 
   284     netaddr.inet.family = PR_AF_INET;
   285     netaddr.inet.ip     = PR_htonl( MY_INADDR );
   286     netaddr.inet.port   = PR_htons( UDP_CLIENT_PORT );
   288     /* --- Initialize the write buffer --- */    
   289     for ( i = 0; i < UDP_BUF_SIZE ; i++ )
   290         cltBuf[i] = i;
   292     /* --- Bind the socket --- */
   293     while ( !bound )
   294     {
   295         DPRINTF("udpsrv: UDP_Client(): Binding socket\n" );
   296         rv = PR_Bind( cltSock, &netaddr );
   297         if ( rv < 0 )
   298         {
   299             if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
   300             {
   301                 if (debug_mode)
   302                     PR_fprintf(output,
   303                         "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
   304                 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
   305                 continue;
   306             }
   307             else
   308             {
   309                 passed = PR_FALSE;
   310                 if (debug_mode)
   311                     PR_fprintf(output,
   312                         "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
   313                         rv, PR_GetError() );
   314                 PR_Close( cltSock );
   315                 return;
   316             }
   317         }
   318         else
   319             bound = PR_TRUE;
   320     }
   321     ListNetAddr( "UDP_Client after Bind", &netaddr );
   323     /* --- Initialize the sockaddr_in structure --- */
   324     memset( &netaddr, 0, sizeof( netaddr )); 
   325     netaddr.inet.family = PR_AF_INET;
   326     netaddr.inet.ip     = PR_htonl( PEER_INADDR );
   327     netaddr.inet.port   = PR_htons( UDP_SERVER_PORT );
   329     /* --- send and receive packets until no more data left */    
   330     while( !endOfInput )
   331     {
   332         /*
   333         ** Signal EOF in the data stream on the last packet
   334         */        
   335         if ( writeThisMany <= UDP_DGRAM_SIZE )
   336         {
   337             DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" );
   338             cltBuf[0] = 'E';
   339             endOfInput = PR_TRUE;
   340         }
   342         /* --- SendTo the socket --- */
   343         if ( writeThisMany > UDP_DGRAM_SIZE )
   344             numBytes = UDP_DGRAM_SIZE;
   345         else
   346             numBytes = writeThisMany;
   347         writeThisMany -= numBytes;
   348         {
   349             char   mbuf[256];
   350             sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n", 
   351                 writeThisMany, numBytes );
   352             DPRINTF( mbuf );
   353         }
   355         DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" );
   356         rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
   357         if ( rv == -1 )
   358         {
   359             passed = PR_FALSE;
   360             if (debug_mode)
   361                 PR_fprintf(output,
   362                     "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
   363                         PR_GetError() );
   364             PR_Close( cltSock );
   365             return;
   366         }
   367         ListNetAddr( "UDP_Client after SendTo", &netaddr );
   369         /* --- RecvFrom the socket --- */
   370         memset( cltBufin, 0, UDP_BUF_SIZE );
   371         DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" );
   372         rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT );
   373         if ( rv == -1 )
   374         {
   375             passed = PR_FALSE;
   376             if (debug_mode) PR_fprintf(output,
   377                 "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
   378                    PR_GetError() );
   379             PR_Close( cltSock );
   380             return;
   381         }
   382         ListNetAddr( "UDP_Client after RecvFrom()", &netaddr );
   383         cltBytesRead += rv;
   385         /* --- verify buffer --- */
   386         for ( i = 0; i < rv ; i++ )
   387         {
   388             if ( cltBufin[i] != i )
   389             {
   390                 /* --- special case, end of input --- */
   391                 if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
   392                     continue;
   393                 passed = PR_FALSE;
   394                 if (debug_mode) PR_fprintf(output,
   395                     "udpsrv: UDP_Client(): return data mismatch\n" );
   396                 PR_Close( cltSock );
   397                 return;
   398             }
   399         }
   400         if (debug_mode) PR_fprintf(output, ".");
   401     }
   403     /* --- Close the socket --- */
   404     DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
   405     rv = PR_Close( cltSock );
   406     if ( rv != PR_SUCCESS )
   407     {
   408         passed = PR_FALSE;
   409         if (debug_mode) PR_fprintf(output,
   410             "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
   411         return;
   412     }
   413     DPRINTF("udpsrv: UDP_Client(): ending\n" );
   414 } /* --- end UDP_Client() --- */
   416 /********************************************************************
   417 ** main() -- udpsrv
   418 **
   419 ** arguments:
   420 **
   421 ** Returns:
   422 ** 0 -- Successful execution
   423 ** 1 -- Test failed.
   424 **
   425 ** Description:
   426 **
   427 ** Standard test case setup.
   428 **
   429 ** Calls the function UDP_Server()
   430 **
   431 ********************************************************************
   432 */
   434 int main(int argc, char **argv)
   435 {
   436     PRThread    *srv, *clt;
   437 /* The command line argument: -d is used to determine if the test is being run
   438 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   439 	All of the printfs associated with this test has been handled with a if (debug_mode)
   440 	test.
   441 	Usage: test_name -d -v
   442 	*/
   443 	PLOptStatus os;
   444 	PLOptState *opt = PL_CreateOptState(argc, argv, "dv");
   445 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   446     {
   447 		if (PL_OPT_BAD == os) continue;
   448         switch (opt->option)
   449         {
   450         case 'd':  /* debug mode */
   451 			debug_mode = 1;
   452             break;
   453         case 'v':  /* verbose mode */
   454 			_debug_on = 1;
   455             break;
   456          default:
   457             break;
   458         }
   459     }
   460 	PL_DestroyOptState(opt);
   462     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   463     PR_STDIO_INIT();
   464     output = PR_STDERR;
   466     PR_SetConcurrency(4);
   468     /*
   469     ** Create the Server thread
   470     */    
   471     DPRINTF( "udpsrv: Creating Server Thread\n" );
   472     srv =  PR_CreateThread( PR_USER_THREAD,
   473             UDP_Server,
   474             (void *) 0,
   475             PR_PRIORITY_LOW,
   476             PR_LOCAL_THREAD,
   477             PR_JOINABLE_THREAD,
   478             0 );
   479     if ( srv == NULL )
   480     {
   481         if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
   482         passed = PR_FALSE;
   483     }
   485     /*
   486     ** Give the Server time to Start
   487     */    
   488     DPRINTF( "udpsrv: Pausing to allow Server to start\n" );
   489     PR_Sleep( PR_MillisecondsToInterval(200) );
   491     /*
   492     ** Create the Client thread
   493     */    
   494     DPRINTF( "udpsrv: Creating Client Thread\n" );
   495     clt = PR_CreateThread( PR_USER_THREAD,
   496             UDP_Client,
   497             (void *) 0,
   498             PR_PRIORITY_LOW,
   499             PR_LOCAL_THREAD,
   500             PR_JOINABLE_THREAD,
   501             0 );
   502     if ( clt == NULL )
   503     {
   504         if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
   505         passed = PR_FALSE;
   506     }
   508     /*
   509     **
   510     */
   511     DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" );
   512     PR_JoinThread( srv );
   513     PR_JoinThread( clt );    
   515     /*
   516     ** Evaluate test results
   517     */
   518     if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
   519 		srvBytesRead(%ld), expected(%ld)\n",
   520          cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
   521     if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
   522     {
   523         passed = PR_FALSE;
   524     }
   525     PR_Cleanup();
   526     if ( passed )
   527         return 0;
   528     else
   529 		return 1;
   530 } /* --- end main() --- */

mercurial