home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / tests / udpsrv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.2 KB  |  534 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*******************************************************************
  20. ** udpsrc.c -- Test basic function of UDP server
  21. **
  22. ** udpsrv operates on the same machine with program udpclt.
  23. ** udpsrv is the server side of a udp sockets application.
  24. ** udpclt is the client side of a udp sockets application.
  25. **
  26. ** The test is designed to assist developers in porting/debugging
  27. ** the UDP socket functions of NSPR.
  28. **
  29. ** This test is not a stress test.
  30. **
  31. ** main() starts two threads: UDP_Server() and UDP_Client();
  32. ** main() uses PR_JoinThread() to wait for the threads to complete.
  33. **
  34. ** UDP_Server() does repeated recvfrom()s from a socket.
  35. ** He detects an EOF condition set by UDP_Client(). For each
  36. ** packet received by UDP_Server(), he checks its content for
  37. ** expected content, then sends the packet back to UDP_Client().
  38. ** 
  39. ** UDP_Client() sends packets to UDP_Server() using sendto()
  40. ** he recieves packets back from the server via recvfrom().
  41. ** After he sends enough packets containing UDP_AMOUNT_TO_WRITE
  42. ** bytes of data, he sends an EOF message.
  43. ** 
  44. ** The test issues a pass/fail message at end.
  45. ** 
  46. ** Notes:
  47. ** The variable "_debug_on" can be set to 1 to cause diagnostic
  48. ** messages related to client/server synchronization. Useful when
  49. ** the test hangs.
  50. ** 
  51. ** Error messages are written to stdout.
  52. ** 
  53. ********************************************************************
  54. */
  55. /* --- include files --- */
  56. #include "nspr.h"
  57. #include "prpriv.h"
  58.  
  59. #include "plgetopt.h"
  60. #include "prttools.h"
  61.  
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <errno.h>
  66.  
  67. /* --- manifest constants --- */
  68. #ifdef XP_MAC
  69. #define fprintf(a,b) printf(b)
  70. #include "prlog.h"
  71. #define printf PR_LogPrint
  72. #endif
  73.  
  74. #ifdef XP_PC
  75. #define mode_t int
  76. #endif
  77.  
  78. #define UDP_BUF_SIZE            4096
  79. #define UDP_DGRAM_SIZE          128
  80. #define UDP_AMOUNT_TO_WRITE     (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1)
  81. #define NUM_UDP_CLIENTS         1
  82. #define NUM_UDP_DATAGRAMS_PER_CLIENT    5
  83. #define UDP_SERVER_PORT         9050
  84. #define UDP_CLIENT_PORT         9053
  85. /* #define MY_INADDR               INADDR_ANY */
  86. #define MY_INADDR               INADDR_LOOPBACK
  87.  
  88. #define UDP_TIMEOUT             400000
  89. /* #define UDP_TIMEOUT             PR_INTERVAL_NO_TIMEOUT */
  90.  
  91. /* --- static data --- */
  92. static PRIntn _debug_on      = 0;
  93. static PRBool passed         = PR_TRUE;
  94. static PRUint32 cltBytesRead = 0;
  95. static PRUint32 srvBytesRead = 0;
  96.  
  97. /* --- static function declarations --- */
  98. #define DPRINTF(arg) if (_debug_on) printf(arg)
  99.  
  100.  
  101.  
  102. /*******************************************************************
  103. ** ListNetAddr() -- Display the Net Address on stdout
  104. **
  105. ** Description: displays the component parts of a PRNetAddr struct
  106. **
  107. ** Arguments:   address of PRNetAddr structure to display
  108. **
  109. ** Returns: void
  110. **
  111. ** Notes:
  112. **
  113. ********************************************************************
  114. */
  115. void ListNetAddr( char *msg, PRNetAddr *na )
  116. {
  117.     char    mbuf[256];
  118.     
  119.     sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n",
  120.             msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) );
  121. #if 0            
  122.     DPRINTF( mbuf );            
  123. #endif
  124. } /* --- end ListNetAddr() --- */
  125.  
  126. /********************************************************************
  127. ** UDP_Server() -- Test a UDP server application
  128. **
  129. ** Description: The Server side of a UDP Client/Server application.
  130. **
  131. ** Arguments: none
  132. **
  133. ** Returns: void
  134. **
  135. ** Notes:
  136. **
  137. **
  138. ********************************************************************
  139. */
  140. static void PR_CALLBACK UDP_Server( void *arg )
  141. {
  142.     static char     svrBuf[UDP_BUF_SIZE];
  143.     PRFileDesc      *svrSock;
  144.     PRInt32         rv;
  145.     PRNetAddr       netaddr;
  146.     PRBool          bound = PR_FALSE;
  147.     PRBool          endOfInput = PR_FALSE;
  148.     PRInt32         numBytes = UDP_DGRAM_SIZE;
  149.     
  150.     DPRINTF("udpsrv: UDP_Server(): starting\n" );
  151.  
  152.     /* --- Create the socket --- */
  153.     DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" );
  154.     svrSock = PR_NewUDPSocket();
  155.     if ( svrSock == NULL )
  156.     {
  157.         passed = PR_FALSE;
  158.         if (debug_mode) printf("udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
  159.         return;
  160.     }
  161.     
  162.     /* --- Initialize the sockaddr_in structure --- */
  163.     memset( &netaddr, 0, sizeof( netaddr )); 
  164.     netaddr.inet.family = AF_INET;
  165.     netaddr.inet.port   = PR_htons( UDP_SERVER_PORT );
  166.     netaddr.inet.ip     = PR_htonl( MY_INADDR );
  167.     
  168.     /* --- Bind the socket --- */
  169.     while ( !bound )
  170.     {
  171.         DPRINTF("udpsrv: UDP_Server(): Binding socket\n" );
  172.         rv = PR_Bind( svrSock, &netaddr );
  173.         if ( rv < 0 )
  174.         {
  175.             if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
  176.             {
  177.                 if (debug_mode) printf("udpsrv: UDP_Server(): \
  178.                         PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
  179.                 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
  180.                 continue;
  181.             }
  182.             else
  183.             {
  184.                 passed = PR_FALSE;
  185.                 if (debug_mode) printf( "udpsrv: UDP_Server(): \
  186.                         PR_Bind(): failed: %ld with error: %ld\n",
  187.                         rv, PR_GetError() );
  188.                 PR_Close( svrSock );
  189.                 return;
  190.             }
  191.         }
  192.         else
  193.             bound = PR_TRUE;
  194.     }
  195.     ListNetAddr( "UDP_Server: after bind", &netaddr );
  196.     
  197.     /* --- Recv the socket --- */
  198.     while( !endOfInput )
  199.     {
  200.         DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" );
  201.         rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
  202.         if ( rv == -1 )
  203.         {
  204.             passed = PR_FALSE;
  205.             if (debug_mode) printf( "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
  206.                         PR_GetError() );
  207.             PR_Close( svrSock );
  208.             return;
  209.         }
  210.         ListNetAddr( "UDP_Server after RecvFrom", &netaddr );
  211.         
  212.         srvBytesRead += rv;
  213.         
  214.         if ( svrBuf[0] == 'E' )
  215.         {
  216.             DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" );
  217.             endOfInput = PR_TRUE;
  218.         }
  219.             
  220.         /* --- Send the socket --- */
  221.         DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" );
  222.         rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT );
  223.         if ( rv == -1 )
  224.         {
  225.             passed = PR_FALSE;
  226.             if (debug_mode) printf( "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
  227.                         PR_GetError() );
  228.             PR_Close( svrSock );
  229.             return;
  230.         }
  231.         ListNetAddr( "UDP_Server after SendTo", &netaddr );
  232.     }
  233.     
  234.     /* --- Close the socket --- */
  235.     DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
  236.     rv = PR_Close( svrSock );
  237.     if ( rv != PR_SUCCESS )
  238.     {
  239.         passed = PR_FALSE;
  240.         if (debug_mode) printf("udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
  241.         return;
  242.     }
  243.     
  244.     DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
  245. } /* --- end UDP_Server() --- */
  246.  
  247.  
  248. static char         cltBuf[UDP_BUF_SIZE];
  249. static char         cltBufin[UDP_BUF_SIZE];
  250. /********************************************************************
  251. ** UDP_Client() -- Test a UDP client application
  252. **
  253. ** Description:
  254. **
  255. ** Arguments:
  256. **
  257. **
  258. ** Returns:
  259. ** 0 -- Successful execution
  260. ** 1 -- Test failed.
  261. **
  262. ** Notes:
  263. **
  264. **
  265. ********************************************************************
  266. */
  267. static void PR_CALLBACK UDP_Client( void *arg )
  268. {
  269.     PRFileDesc   *cltSock;
  270.     PRInt32      rv;
  271.     PRBool       bound = PR_FALSE;
  272.     PRNetAddr    netaddr;
  273.     PRNetAddr    netaddrx;
  274.     PRBool       endOfInput = PR_FALSE;
  275.     PRInt32      numBytes = UDP_DGRAM_SIZE;
  276.     PRInt32      writeThisMany = UDP_AMOUNT_TO_WRITE;
  277.     int          i;
  278.     
  279.     
  280.     DPRINTF("udpsrv: UDP_Client(): starting\n" );
  281.     
  282.     /* --- Create the socket --- */
  283.     cltSock = PR_NewUDPSocket();
  284.     if ( cltSock == NULL )
  285.     {
  286.         passed = PR_FALSE;
  287.         if (debug_mode) printf("udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
  288.         return;
  289.     }
  290.     
  291.     /* --- Initialize the sockaddr_in structure --- */
  292.     memset( &netaddr, 0, sizeof( netaddr )); 
  293.     netaddr.inet.family = AF_INET;
  294.     netaddr.inet.ip     = PR_htonl( MY_INADDR );
  295.     netaddr.inet.port   = PR_htons( UDP_CLIENT_PORT );
  296.     
  297.     /* --- Initialize the write buffer --- */    
  298.     for ( i = 0; i < UDP_BUF_SIZE ; i++ )
  299.         cltBuf[i] = i;
  300.     
  301.     /* --- Bind the socket --- */
  302.     while ( !bound )
  303.     {
  304.         DPRINTF("udpsrv: UDP_Client(): Binding socket\n" );
  305.         rv = PR_Bind( cltSock, &netaddr );
  306.         if ( rv < 0 )
  307.         {
  308.             if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
  309.             {
  310.                 if (debug_mode) printf("udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
  311.                 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
  312.                 continue;
  313.             }
  314.             else
  315.             {
  316.                 passed = PR_FALSE;
  317.                 if (debug_mode) printf( "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
  318.                         rv, PR_GetError() );
  319.                 PR_Close( cltSock );
  320.                 return;
  321.             }
  322.         }
  323.         else
  324.             bound = PR_TRUE;
  325.     }
  326.     ListNetAddr( "UDP_Client after Bind", &netaddr );
  327.     
  328.     /* --- Initialize the sockaddr_in structure --- */
  329.     memset( &netaddr, 0, sizeof( netaddr )); 
  330.     netaddr.inet.family = AF_INET;
  331.     netaddr.inet.ip     = PR_htonl( MY_INADDR );
  332.     netaddr.inet.port   = PR_htons( UDP_SERVER_PORT );
  333.     
  334.     /* --- send and receive packets until no more data left */    
  335.     while( !endOfInput )
  336.     {
  337.         /*
  338.         ** Signal EOF in the data stream on the last packet
  339.         */        
  340.         if ( writeThisMany <= UDP_DGRAM_SIZE )
  341.         {
  342.             DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" );
  343.             cltBuf[0] = 'E';
  344.             endOfInput = PR_TRUE;
  345.         }
  346.         
  347.         /* --- SendTo the socket --- */
  348.         if ( writeThisMany > UDP_DGRAM_SIZE )
  349.             numBytes = UDP_DGRAM_SIZE;
  350.         else
  351.             numBytes = writeThisMany;
  352.         writeThisMany -= numBytes;
  353.         {
  354.             char   mbuf[256];
  355.             sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %ld, numbytes: %ld\n", 
  356.                 writeThisMany, numBytes );
  357.             DPRINTF( mbuf );
  358.         }
  359.         
  360.         DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" );
  361.         rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
  362.         if ( rv == -1 )
  363.         {
  364.             passed = PR_FALSE;
  365.             if (debug_mode) printf( "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
  366.                         PR_GetError() );
  367.             PR_Close( cltSock );
  368.             return;
  369.         }
  370.         ListNetAddr( "UDP_Client after SendTo", &netaddr );
  371.  
  372.         /* --- RecvFrom the socket --- */
  373.         memset( cltBufin, 0, UDP_BUF_SIZE );
  374.         DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" );
  375.         rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT );
  376.         if ( rv == -1 )
  377.         {
  378.             passed = PR_FALSE;
  379.             if (debug_mode) printf( "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
  380.                    PR_GetError() );
  381.             PR_Close( cltSock );
  382.             return;
  383.         }
  384.         ListNetAddr( "UDP_Client after RecvFrom()", &netaddr );
  385.         cltBytesRead += rv;
  386.         
  387.         /* --- verify buffer --- */
  388.         for ( i = 0; i < rv ; i++ )
  389.         {
  390.             if ( cltBufin[i] != i )
  391.             {
  392.                 /* --- special case, end of input --- */
  393.                 if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
  394.                     continue;
  395.                 passed = PR_FALSE;
  396.                 if (debug_mode) printf("udpsrv: UDP_Client(): return data mismatch\n" );
  397.                 PR_Close( cltSock );
  398.                 return;
  399.             }
  400.         }
  401.         if (debug_mode) printf(".");
  402.     }
  403.     
  404.     /* --- Close the socket --- */
  405.     DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
  406.     rv = PR_Close( cltSock );
  407.     if ( rv != PR_SUCCESS )
  408.     {
  409.         passed = PR_FALSE;
  410.         if (debug_mode) printf("udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
  411.         return;
  412.     }
  413.     DPRINTF("udpsrv: UDP_Client(): ending\n" );
  414. } /* --- end UDP_Client() --- */
  415.  
  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. */
  433.  
  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);
  461.         
  462.     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  463.     PR_STDIO_INIT();
  464.  
  465. #ifdef XP_MAC
  466.     SetupMacPrintfLog("udpsrv.log");
  467. #endif
  468.  
  469.     PR_SetConcurrency(4);
  470.     
  471.     /*
  472.     ** Create the Server thread
  473.     */    
  474.     DPRINTF( "udpsrv: Creating Server Thread\n" );
  475.     srv =  PR_CreateThread( PR_USER_THREAD,
  476.             UDP_Server,
  477.             (void *) 0,
  478.             PR_PRIORITY_LOW,
  479.             PR_LOCAL_THREAD,
  480.             PR_JOINABLE_THREAD,
  481.             0 );
  482.     if ( srv == NULL )
  483.     {
  484.         if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
  485.         passed = PR_FALSE;
  486.     }
  487.     
  488.     /*
  489.     ** Give the Server time to Start
  490.     */    
  491.     DPRINTF( "udpsrv: Pausing to allow Server to start\n" );
  492.     PR_Sleep( PR_MillisecondsToInterval(200) );
  493.     
  494.     /*
  495.     ** Create the Client thread
  496.     */    
  497.     DPRINTF( "udpsrv: Creating Client Thread\n" );
  498.     clt = PR_CreateThread( PR_USER_THREAD,
  499.             UDP_Client,
  500.             (void *) 0,
  501.             PR_PRIORITY_LOW,
  502.             PR_LOCAL_THREAD,
  503.             PR_JOINABLE_THREAD,
  504.             0 );
  505.     if ( clt == NULL )
  506.     {
  507.         if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
  508.         passed = PR_FALSE;
  509.     }
  510.     
  511.     /*
  512.     **
  513.     */
  514.     DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" );
  515.     PR_JoinThread( srv );
  516.     PR_JoinThread( clt );    
  517.     
  518.     /*
  519.     ** Evaluate test results
  520.     */
  521.     if (debug_mode) printf( "\n\nudpsrv: main(): cltBytesRead(%ld), \
  522.         srvBytesRead(%ld), expected(%ld)\n",
  523.          cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
  524.     if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
  525.     {
  526.         passed = PR_FALSE;
  527.     }
  528.     PR_Cleanup();
  529.     if ( passed )
  530.         return 0;
  531.     else
  532.         return 1;
  533. } /* --- end main() --- */
  534.