mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	Differential Revision: https://phabricator.services.mozilla.com/D48414 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			546 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			546 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* -*- 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() --- */
 |