123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*******************************************************************
- ** udpsrc.c -- Test basic function of UDP server
- **
- ** udpsrv operates on the same machine with program udpclt.
- ** udpsrv is the server side of a udp sockets application.
- ** udpclt is the client side of a udp sockets application.
- **
- ** The test is designed to assist developers in porting/debugging
- ** the UDP socket functions of NSPR.
- **
- ** This test is not a stress test.
- **
- ** main() starts two threads: UDP_Server() and UDP_Client();
- ** main() uses PR_JoinThread() to wait for the threads to complete.
- **
- ** UDP_Server() does repeated recvfrom()s from a socket.
- ** He detects an EOF condition set by UDP_Client(). For each
- ** packet received by UDP_Server(), he checks its content for
- ** expected content, then sends the packet back to UDP_Client().
- **
- ** UDP_Client() sends packets to UDP_Server() using sendto()
- ** he recieves packets back from the server via recvfrom().
- ** After he sends enough packets containing UDP_AMOUNT_TO_WRITE
- ** bytes of data, he sends an EOF message.
- **
- ** The test issues a pass/fail message at end.
- **
- ** Notes:
- ** The variable "_debug_on" can be set to 1 to cause diagnostic
- ** messages related to client/server synchronization. Useful when
- ** the test hangs.
- **
- ** Error messages are written to stdout.
- **
- ********************************************************************
- */
- /* --- include files --- */
- #include "nspr.h"
- #include "prpriv.h"
- #include "plgetopt.h"
- #include "prttools.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #ifdef XP_PC
- #define mode_t int
- #endif
- #define UDP_BUF_SIZE 4096
- #define UDP_DGRAM_SIZE 128
- #define UDP_AMOUNT_TO_WRITE (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1)
- #define NUM_UDP_CLIENTS 1
- #define NUM_UDP_DATAGRAMS_PER_CLIENT 5
- #define UDP_SERVER_PORT 9050
- #define UDP_CLIENT_PORT 9053
- #define MY_INADDR PR_INADDR_ANY
- #define PEER_INADDR PR_INADDR_LOOPBACK
- #define UDP_TIMEOUT 400000
- /* #define UDP_TIMEOUT PR_INTERVAL_NO_TIMEOUT */
- /* --- static data --- */
- static PRIntn _debug_on = 0;
- static PRBool passed = PR_TRUE;
- static PRUint32 cltBytesRead = 0;
- static PRUint32 srvBytesRead = 0;
- static PRFileDesc *output = NULL;
- /* --- static function declarations --- */
- #define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
- /*******************************************************************
- ** ListNetAddr() -- Display the Net Address on stdout
- **
- ** Description: displays the component parts of a PRNetAddr struct
- **
- ** Arguments: address of PRNetAddr structure to display
- **
- ** Returns: void
- **
- ** Notes:
- **
- ********************************************************************
- */
- void ListNetAddr( char *msg, PRNetAddr *na )
- {
- char mbuf[256];
- sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n",
- msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) );
- #if 0
- DPRINTF( mbuf );
- #endif
- } /* --- end ListNetAddr() --- */
- /********************************************************************
- ** UDP_Server() -- Test a UDP server application
- **
- ** Description: The Server side of a UDP Client/Server application.
- **
- ** Arguments: none
- **
- ** Returns: void
- **
- ** Notes:
- **
- **
- ********************************************************************
- */
- static void PR_CALLBACK UDP_Server( void *arg )
- {
- static char svrBuf[UDP_BUF_SIZE];
- PRFileDesc *svrSock;
- PRInt32 rv;
- PRNetAddr netaddr;
- PRBool bound = PR_FALSE;
- PRBool endOfInput = PR_FALSE;
- PRInt32 numBytes = UDP_DGRAM_SIZE;
- DPRINTF("udpsrv: UDP_Server(): starting\n" );
- /* --- Create the socket --- */
- DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" );
- svrSock = PR_NewUDPSocket();
- if ( svrSock == NULL )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
- return;
- }
- /* --- Initialize the sockaddr_in structure --- */
- memset( &netaddr, 0, sizeof( netaddr ));
- netaddr.inet.family = PR_AF_INET;
- netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
- netaddr.inet.ip = PR_htonl( MY_INADDR );
- /* --- Bind the socket --- */
- while ( !bound )
- {
- DPRINTF("udpsrv: UDP_Server(): Binding socket\n" );
- rv = PR_Bind( svrSock, &netaddr );
- if ( rv < 0 )
- {
- if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
- {
- if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
- PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
- PR_Sleep( PR_MillisecondsToInterval( 2000 ));
- continue;
- }
- else
- {
- passed = PR_FALSE;
- if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
- PR_Bind(): failed: %ld with error: %ld\n",
- rv, PR_GetError() );
- PR_Close( svrSock );
- return;
- }
- }
- else {
- bound = PR_TRUE;
- }
- }
- ListNetAddr( "UDP_Server: after bind", &netaddr );
- /* --- Recv the socket --- */
- while( !endOfInput )
- {
- DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" );
- rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
- if ( rv == -1 )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
- PR_GetError() );
- PR_Close( svrSock );
- return;
- }
- ListNetAddr( "UDP_Server after RecvFrom", &netaddr );
- srvBytesRead += rv;
- if ( svrBuf[0] == 'E' )
- {
- DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" );
- endOfInput = PR_TRUE;
- }
- /* --- Send the socket --- */
- DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" );
- rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT );
- if ( rv == -1 )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
- PR_GetError() );
- PR_Close( svrSock );
- return;
- }
- ListNetAddr( "UDP_Server after SendTo", &netaddr );
- }
- /* --- Close the socket --- */
- DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
- rv = PR_Close( svrSock );
- if ( rv != PR_SUCCESS )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
- return;
- }
- DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
- } /* --- end UDP_Server() --- */
- static char cltBuf[UDP_BUF_SIZE];
- static char cltBufin[UDP_BUF_SIZE];
- /********************************************************************
- ** UDP_Client() -- Test a UDP client application
- **
- ** Description:
- **
- ** Arguments:
- **
- **
- ** Returns:
- ** 0 -- Successful execution
- ** 1 -- Test failed.
- **
- ** Notes:
- **
- **
- ********************************************************************
- */
- static void PR_CALLBACK UDP_Client( void *arg )
- {
- PRFileDesc *cltSock;
- PRInt32 rv;
- PRBool bound = PR_FALSE;
- PRNetAddr netaddr;
- PRNetAddr netaddrx;
- PRBool endOfInput = PR_FALSE;
- PRInt32 numBytes = UDP_DGRAM_SIZE;
- PRInt32 writeThisMany = UDP_AMOUNT_TO_WRITE;
- int i;
- DPRINTF("udpsrv: UDP_Client(): starting\n" );
- /* --- Create the socket --- */
- cltSock = PR_NewUDPSocket();
- if ( cltSock == NULL )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
- return;
- }
- /* --- Initialize the sockaddr_in structure --- */
- memset( &netaddr, 0, sizeof( netaddr ));
- netaddr.inet.family = PR_AF_INET;
- netaddr.inet.ip = PR_htonl( MY_INADDR );
- netaddr.inet.port = PR_htons( UDP_CLIENT_PORT );
- /* --- Initialize the write buffer --- */
- for ( i = 0; i < UDP_BUF_SIZE ; i++ ) {
- cltBuf[i] = i;
- }
- /* --- Bind the socket --- */
- while ( !bound )
- {
- DPRINTF("udpsrv: UDP_Client(): Binding socket\n" );
- rv = PR_Bind( cltSock, &netaddr );
- if ( rv < 0 )
- {
- if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
- {
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
- PR_Sleep( PR_MillisecondsToInterval( 2000 ));
- continue;
- }
- else
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
- rv, PR_GetError() );
- PR_Close( cltSock );
- return;
- }
- }
- else {
- bound = PR_TRUE;
- }
- }
- ListNetAddr( "UDP_Client after Bind", &netaddr );
- /* --- Initialize the sockaddr_in structure --- */
- memset( &netaddr, 0, sizeof( netaddr ));
- netaddr.inet.family = PR_AF_INET;
- netaddr.inet.ip = PR_htonl( PEER_INADDR );
- netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
- /* --- send and receive packets until no more data left */
- while( !endOfInput )
- {
- /*
- ** Signal EOF in the data stream on the last packet
- */
- if ( writeThisMany <= UDP_DGRAM_SIZE )
- {
- DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" );
- cltBuf[0] = 'E';
- endOfInput = PR_TRUE;
- }
- /* --- SendTo the socket --- */
- if ( writeThisMany > UDP_DGRAM_SIZE ) {
- numBytes = UDP_DGRAM_SIZE;
- }
- else {
- numBytes = writeThisMany;
- }
- writeThisMany -= numBytes;
- {
- char mbuf[256];
- sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n",
- writeThisMany, numBytes );
- DPRINTF( mbuf );
- }
- DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" );
- rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
- if ( rv == -1 )
- {
- passed = PR_FALSE;
- if (debug_mode)
- PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
- PR_GetError() );
- PR_Close( cltSock );
- return;
- }
- ListNetAddr( "UDP_Client after SendTo", &netaddr );
- /* --- RecvFrom the socket --- */
- memset( cltBufin, 0, UDP_BUF_SIZE );
- DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" );
- rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT );
- if ( rv == -1 )
- {
- passed = PR_FALSE;
- if (debug_mode) PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
- PR_GetError() );
- PR_Close( cltSock );
- return;
- }
- ListNetAddr( "UDP_Client after RecvFrom()", &netaddr );
- cltBytesRead += rv;
- /* --- verify buffer --- */
- for ( i = 0; i < rv ; i++ )
- {
- if ( cltBufin[i] != i )
- {
- /* --- special case, end of input --- */
- if ( endOfInput && i == 0 && cltBufin[0] == 'E' ) {
- continue;
- }
- passed = PR_FALSE;
- if (debug_mode) PR_fprintf(output,
- "udpsrv: UDP_Client(): return data mismatch\n" );
- PR_Close( cltSock );
- return;
- }
- }
- if (debug_mode) {
- PR_fprintf(output, ".");
- }
- }
- /* --- Close the socket --- */
- DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
- rv = PR_Close( cltSock );
- if ( rv != PR_SUCCESS )
- {
- passed = PR_FALSE;
- if (debug_mode) PR_fprintf(output,
- "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
- return;
- }
- DPRINTF("udpsrv: UDP_Client(): ending\n" );
- } /* --- end UDP_Client() --- */
- /********************************************************************
- ** main() -- udpsrv
- **
- ** arguments:
- **
- ** Returns:
- ** 0 -- Successful execution
- ** 1 -- Test failed.
- **
- ** Description:
- **
- ** Standard test case setup.
- **
- ** Calls the function UDP_Server()
- **
- ********************************************************************
- */
- int main(int argc, char **argv)
- {
- PRThread *srv, *clt;
- /* The command line argument: -d is used to determine if the test is being run
- in debug mode. The regress tool requires only one line output:PASS or FAIL.
- All of the printfs associated with this test has been handled with a if (debug_mode)
- test.
- Usage: test_name -d -v
- */
- PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "dv");
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) {
- continue;
- }
- switch (opt->option)
- {
- case 'd': /* debug mode */
- debug_mode = 1;
- break;
- case 'v': /* verbose mode */
- _debug_on = 1;
- break;
- default:
- break;
- }
- }
- PL_DestroyOptState(opt);
- PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
- PR_STDIO_INIT();
- output = PR_STDERR;
- PR_SetConcurrency(4);
- /*
- ** Create the Server thread
- */
- DPRINTF( "udpsrv: Creating Server Thread\n" );
- srv = PR_CreateThread( PR_USER_THREAD,
- UDP_Server,
- (void *) 0,
- PR_PRIORITY_LOW,
- PR_LOCAL_THREAD,
- PR_JOINABLE_THREAD,
- 0 );
- if ( srv == NULL )
- {
- if (debug_mode) {
- PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
- }
- passed = PR_FALSE;
- }
- /*
- ** Give the Server time to Start
- */
- DPRINTF( "udpsrv: Pausing to allow Server to start\n" );
- PR_Sleep( PR_MillisecondsToInterval(200) );
- /*
- ** Create the Client thread
- */
- DPRINTF( "udpsrv: Creating Client Thread\n" );
- clt = PR_CreateThread( PR_USER_THREAD,
- UDP_Client,
- (void *) 0,
- PR_PRIORITY_LOW,
- PR_LOCAL_THREAD,
- PR_JOINABLE_THREAD,
- 0 );
- if ( clt == NULL )
- {
- if (debug_mode) {
- PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
- }
- passed = PR_FALSE;
- }
- /*
- **
- */
- DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" );
- PR_JoinThread( srv );
- PR_JoinThread( clt );
- /*
- ** Evaluate test results
- */
- if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
- srvBytesRead(%ld), expected(%ld)\n",
- cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
- if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
- {
- passed = PR_FALSE;
- }
- PR_Cleanup();
- if ( passed ) {
- return 0;
- }
- else {
- return 1;
- }
- } /* --- end main() --- */
|