socket.c revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape Portable Runtime (NSPR).
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/***********************************************************************
**
** Name: socket.c
**
** Description: Test socket functionality.
**
** Modification History:
*/
#include "primpl.h"
#include "plgetopt.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef XP_UNIX
#endif
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#include <pthread.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
static int _debug_on = 0;
static int test_cancelio = 0;
#ifdef XP_MAC
#include "prlog.h"
#include "prsem.h"
{
return 0;
}
#define printf PR_LogPrint
extern void SetupMacPrintfLog(char *logFile);
#else
#endif
#ifdef XP_PC
#define mode_t int
#endif
#ifdef XP_PC
char *TEST_DIR = "prdir";
char *SMALL_FILE_NAME = "prsmallf";
char *LARGE_FILE_NAME = "prlargef";
#else
char *TEST_DIR = "/tmp/prsocket_test_dir";
char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";
char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";
#endif
#define SMALL_FILE_OFFSET_1 (512)
#define SMALL_FILE_OFFSET_2 (75)
#define SMALL_FILE_LEN_2 (758)
#define SMALL_FILE_OFFSET_3 (1024)
#define LARGE_FILE_OFFSET_1 (0)
#define LARGE_FILE_OFFSET_2 (64)
#define LARGE_FILE_OFFSET_4 PR_GetPageSize()
#define LARGE_FILE_LEN_4 769
#define LARGE_FILE_HEADER_SIZE (512)
#define LARGE_FILE_TRAILER_SIZE (64)
#define TCP_MESG_SIZE 1024
/*
* set UDP datagram size small enough that datagrams sent to a port on the
* local host will not be lost
*/
#define UDP_DGRAM_SIZE 128
#define NUM_UDP_CLIENTS 10
#ifndef XP_MAC
#define NUM_TRANSMITFILE_CLIENTS 4
#else
/* Mac can't handle more than 2* (3Mb) allocations for large file size buffers */
#define NUM_TRANSMITFILE_CLIENTS 2
#endif
#define NUM_TCP_CONNECTIONS_PER_CLIENT 5
#define NUM_TCP_MESGS_PER_CONNECTION 10
#define NUM_UDP_DATAGRAMS_PER_CLIENT 5
#define TCP_SERVER_PORT 10000
#define UDP_SERVER_PORT TCP_SERVER_PORT
#define SERVER_MAX_BIND_COUNT 100
static PRInt32 thread_count;
/* an I/O layer that uses the emulated senfile method */
static PRDescIdentity emuSendFileIdentity;
static PRIOMethods emuSendFileMethods;
int failed_already=0;
typedef struct buffer {
char data[BUF_DATA_SIZE];
} buffer;
typedef struct Serve_Client_Param {
typedef struct Server_Param {
} Server_Param;
typedef struct Client_Param {
} Client_Param;
/* the sendfile method in emuSendFileMethods */
static PRInt32 PR_CALLBACK
{
}
/* the transmitfile method in emuSendFileMethods */
static PRInt32 PR_CALLBACK
{
sfd.file_offset = 0;
sfd.file_nbytes = 0;
}
/*
* readn
* read data from sockfd into buf
*/
static PRInt32
{
int rem;
int bytes;
int offset = 0;
int err;
if (test_cancelio)
DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
PR_GetCurrentThread(), rem));
timeout);
DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
PR_GetCurrentThread(), bytes));
if (bytes < 0) {
#ifdef WINNT
PR_GetOSError());
goto retry;
}
#endif
return -1;
}
}
return len;
}
/*
* writen
* write data from buf to sockfd
*/
static PRInt32
{
int rem;
int bytes;
int offset = 0;
DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
PR_GetCurrentThread(), rem));
DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
PR_GetCurrentThread(), bytes));
if (bytes <= 0)
return -1;
}
return len;
}
/*
* Serve_Client
* Thread, started by the server, for serving a client connection.
* Reads data from socket and writes it back, unmodified, and
* closes the socket
*/
static void PR_CALLBACK
Serve_Client(void *arg)
{
goto exit;
}
for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
/*
* Read data from client and send it back to the client unmodified
*/
goto exit;
}
/*
* shutdown reads, after the last read
*/
if (j == num_tcp_mesgs_per_connection - 1)
}
goto exit;
}
}
/*
* shutdown reads and writes
*/
}
exit:
if (in_buf) {
}
}
void *arg,
{
PRInt32 native_thread = 0;
switch(index % 4) {
case 0:
scope = (PR_LOCAL_THREAD);
break;
case 1:
scope = (PR_GLOBAL_THREAD);
break;
case 2:
break;
case 3:
native_thread = 1;
break;
default:
PR_ASSERT(!"Invalid scope");
break;
}
if (native_thread) {
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
else
return (NULL);
#else
unsigned tid;
NULL,
arg,
0,
&tid);
#endif
} else {
}
#else
#endif
}
/*
* TCP Server
* Server Thread
* Bind an address to a socket and listen for incoming connections
* Start a Serve_Client thread for each incoming connection.
*/
static void PR_CALLBACK
TCP_Server(void *arg)
{
PRThread *t;
PRInt32 i;
/*
* Create a tcp socket
*/
goto exit;
}
&netaddr) == PR_FAILURE) {
goto exit;
}
/*
* try a few times to bind server's address, if addresses are in
* use
*/
i = 0;
if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
if (i++ < SERVER_MAX_BIND_COUNT)
continue;
}
perror("PR_Bind");
goto exit;
}
goto exit;
}
goto exit;
}
DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
&tcp_server_addr) == PR_FAILURE) {
goto exit;
}
/*
* Wake up parent thread because server address is bound and made
* available in the global variable 'tcp_server_addr'
*/
for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) {
/* test both null and non-null 'addr' argument to PR_Accept */
DPRINTF(("TCP_Server: Accepting connection\n"));
PR_INTERVAL_NO_TIMEOUT)) == NULL) {
goto exit;
}
DPRINTF(("TCP_Server: Accepted connection\n"));
goto exit;
}
/*
* Start a Serve_Client thread for each incoming connection
*/
Serve_Client, (void *)scp,
0, i);
if (t == NULL) {
goto exit;
}
DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
}
exit:
if (sockfd) {
}
/*
* Decrement exit_counter and notify parent thread
*/
--(*sp->exit_counter);
}
/*
* UDP Server
* Server Thread
* Bind an address to a socket, read data from clients and send data
* back to clients
*/
static void PR_CALLBACK
UDP_Server(void *arg)
{
/*
* Create a udp socket
*/
return;
}
&netaddr) == PR_FAILURE) {
return;
}
/*
* try a few times to bind server's address, if addresses are in
* use
*/
i = 0;
if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
if (i++ < SERVER_MAX_BIND_COUNT)
continue;
}
perror("PR_Bind");
return;
}
return;
}
DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
/*
* We can't use the IP address returned by PR_GetSockName in
* netaddr.inet.ip because netaddr.inet.ip is returned
* as 0 (= PR_INADDR_ANY).
*/
&udp_server_addr) == PR_FAILURE) {
return;
}
/*
* Wake up parent thread because server address is bound and made
* available in the global variable 'udp_server_addr'
*/
return;
}
/*
* Receive datagrams from clients and send them back, unmodified, to the
* clients
*/
for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) {
DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
return;
}
return;
}
}
/*
* Decrement exit_counter and notify parent thread
*/
--(*sp->exit_counter);
}
/*
* TCP_Client
* Client Thread
* Connect to the server at the address specified in the argument.
* Fill in a buffer, write data to server, read it back and check
* for data corruption.
* Close the socket for server connection
*/
static void PR_CALLBACK
TCP_Client(void *arg)
{
return;
}
return;
}
for (i = 0; i < num_tcp_connections_per_client; i++) {
return;
}
PR_GetError(), PR_GetOSError());
return;
}
for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
/*
* fill in random data
*/
/*
* write to server
*/
#ifdef WINNT
if (test_cancelio && (j == 0))
#endif
return;
}
DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
return;
}
/*
* verify the data read
*/
return;
}
}
/*
* shutdown reads and writes
*/
}
}
/*
* Decrement exit_counter and notify parent thread
*/
--(*cp->exit_counter);
}
/*
* UDP_Client
* Client Thread
* Create a socket and bind an address
* Communicate with the server at the address specified in the argument.
* Fill in a buffer, write data to server, read it back and check
* for data corruption.
* Close the socket
*/
static void PR_CALLBACK
UDP_Client(void *arg)
{
return;
}
return;
}
return;
}
/*
* bind an address for the client, let the system chose the port
* number
*/
&netaddr) == PR_FAILURE) {
return;
}
perror("PR_Bind");
return;
}
return;
}
DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
if (cp->udp_connect) {
return;
}
}
for (i = 0; i < num_udp_datagrams_per_client; i++) {
/*
* fill in random data
*/
DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
/*
* write to server
*/
if (cp->udp_connect)
else
return;
}
DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
if (cp->udp_connect)
else
return;
}
DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
/*
* verify the data read
*/
return;
}
}
/*
* Decrement exit_counter and notify parent thread
*/
--(*cp->exit_counter);
}
/*
* TCP_Socket_Client_Server_Test - concurrent server test
*
* One server and several clients are started
* Each client connects to the server and sends a chunk of data
* For each connection, server starts another thread to read the data
* from the client and send it back to the client, unmodified.
* Each client checks that data received from server is same as the
* data it sent to the server.
*
*/
static PRInt32
{
int i;
PRThread *t;
thread_count = 0;
/*
* start the server thread
*/
return -1;
}
server_sem = PR_NewSem(0);
if (server_sem == NULL) {
return -1;
}
mon2 = PR_NewMonitor();
return -1;
}
TCP_Server, (void *)sparamp,
0);
if (t == NULL) {
return -1;
}
DPRINTF(("Created TCP server = 0x%lx\n", t));
thread_count++;
/*
* wait till the server address is setup
*/
/*
* Now start a bunch of client threads
*/
return -1;
}
for (i = 0; i < num_tcp_clients; i++) {
TCP_Client, (void *) cparamp,
0, i);
if (t == NULL) {
return -1;
}
DPRINTF(("Created TCP client = 0x%lx\n", t));
thread_count++;
}
/* Wait for server and client threads to exit */
while (thread_count) {
}
return 0;
}
/*
* UDP_Socket_Client_Server_Test - iterative server test
*
* One server and several clients are started
* Each client connects to the server and sends a chunk of data
* For each connection, server starts another thread to read the data
* from the client and send it back to the client, unmodified.
* Each client checks that data received from server is same as the
* data it sent to the server.
*
*/
static PRInt32
{
int i;
PRThread *t;
thread_count = 0;
/*
* start the server thread
*/
return -1;
}
server_sem = PR_NewSem(0);
if (server_sem == NULL) {
return -1;
}
mon2 = PR_NewMonitor();
return -1;
}
DPRINTF(("Creating UDP server"));
UDP_Server, (void *)sparamp,
0);
if (t == NULL) {
return -1;
}
thread_count++;
/*
* wait till the server address is setup
*/
/*
* Now start a bunch of client threads
*/
for (i = 0; i < num_udp_clients; i++) {
return -1;
}
/*
* Cause every other client thread to connect udp sockets
*/
#ifndef XP_MAC
#else
/* No support for UDP connects on Mac */
cparamp->udp_connect = 0;
#endif
if (udp_connect)
udp_connect = 0;
else
udp_connect = 1;
DPRINTF(("Creating UDP client %d\n", i));
UDP_Client, (void *) cparamp,
0);
if (t == NULL) {
return -1;
}
thread_count++;
}
/* Wait for server and client threads to exit */
while (thread_count) {
}
return 0;
}
/*
* TransmitFile_Client
* Client Thread
*/
static void
TransmitFile_Client(void *arg)
{
return;
}
return;
}
return;
}
return;
}
/*
* read the small file and verify the data
*/
!= (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) {
"prsocket_test: TransmitFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n");
return;
}
SMALL_FILE_SIZE) != 0) {
"prsocket_test: TransmitFile_Client ERROR - small file data corruption\n");
return;
}
#endif
/*
* read the large file and verify the data
*/
"prsocket_test: TransmitFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
}
#endif
/*
* receive data from PR_SendFile
*/
/*
* case 1: small file with header and trailer
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 1. ERROR - small file header corruption\n");
return;
}
SMALL_FILE_SIZE) != 0) {
"SendFile 1. ERROR - small file data corruption\n");
return;
}
if (memcmp(small_file_trailer,
SMALL_FILE_TRAILER_SIZE) != 0) {
"SendFile 1. ERROR - small file trailer corruption\n");
return;
}
#endif
/*
* case 2: partial large file at zero offset, file with header and trailer
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 2. ERROR - large file header corruption\n");
return;
}
LARGE_FILE_LEN_1) != 0) {
"SendFile 2. ERROR - large file data corruption\n");
return;
}
if (memcmp(large_file_trailer,
LARGE_FILE_TRAILER_SIZE) != 0) {
"SendFile 2. ERROR - large file trailer corruption\n");
return;
}
#endif
/*
* case 3: partial small file at non-zero offset, with header
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 3. ERROR - small file header corruption\n");
return;
}
"SendFile 3. ERROR - small file data corruption\n");
return;
}
#endif
/*
* case 4: partial small file at non-zero offset, with trailer
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
SMALL_FILE_LEN_2) != 0) {
"SendFile 4. ERROR - small file data corruption\n");
return;
}
SMALL_FILE_TRAILER_SIZE) != 0) {
"SendFile 4. ERROR - small file trailer corruption\n");
return;
}
#endif
/*
* case 5: partial large file at non-zero offset, file with header
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 5. ERROR - large file header corruption\n");
return;
}
LARGE_FILE_LEN_2) != 0) {
"SendFile 5. ERROR - large file data corruption\n");
return;
}
#endif
/*
* case 6: partial small file at non-zero offset, with header
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 6. ERROR - small file header corruption\n");
return;
}
#if 0
char *i, *j;
int k;
i = (char *) small_file_addr + SMALL_FILE_OFFSET_3;
j = small_buf + SMALL_FILE_HEADER_SIZE;
k = SMALL_FILE_LEN_3;
while (k-- > 0) {
if (*i++ != *j++)
printf("i = %d j = %d\n",
(int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)),
(int) (j - (small_buf + SMALL_FILE_HEADER_SIZE)));
}
#endif
"SendFile 6. ERROR - small file data corruption\n");
return;
}
#endif
/*
* case 7: partial large file at non-zero offset, with header
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 7. ERROR - large file header corruption\n");
return;
}
LARGE_FILE_LEN_3) != 0) {
"SendFile 7. ERROR - large file data corruption\n");
return;
}
#endif
/*
* case 8: partial large file at non-zero, page-aligned offset, with
* header and trailer
*/
"prsocket_test: SendFile_Client failed to receive file\n");
return;
}
#ifdef XP_UNIX
"SendFile 2. ERROR - large file header corruption\n");
return;
}
LARGE_FILE_LEN_4) != 0) {
"SendFile 2. ERROR - large file data corruption\n");
return;
}
if (memcmp(large_file_trailer,
LARGE_FILE_TRAILER_SIZE) != 0) {
"SendFile 2. ERROR - large file trailer corruption\n");
return;
}
#endif
/*
* Decrement exit_counter and notify parent thread
*/
--(*cp->exit_counter);
}
/*
* Serve_TransmitFile_Client
* Thread, started by the server, for serving a client connection.
* Trasmits a small file, with a header, and a large file, without
* a header
*/
static void
Serve_TransmitFile_Client(void *arg)
{
if (local_small_file_fd == NULL) {
goto done;
}
if (local_large_file_fd == NULL) {
goto done;
}
"prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
if (bytes != LARGE_FILE_SIZE) {
"prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* PR_SendFile test cases
*/
/*
* case 1: small file with header and trailer
*/
sfd.file_offset = 0;
sfd.file_nbytes = 0;
"socket: Error - 1. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 2: partial large file at zero offset, file with header and trailer
*/
sfd.file_offset = 0;
"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 3: partial small file at non-zero offset, with header
*/
"socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 4: partial small file at non-zero offset, with trailer
*/
"socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 5: partial large file at non-zero offset, file with header
*/
"socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 6: partial small file from non-zero offset till end of file, with header
*/
"socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 7: partial large file at non-zero offset till end-of-file, with header
*/
"socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
/*
* case 8: partial large file at non-zero page-aligned offset,
* with header and trailer
*/
"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
"prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
}
done:
if (local_small_file_fd != NULL)
if (local_large_file_fd != NULL)
}
/*
* TransmitFile Server
* Server Thread
* Bind an address to a socket and listen for incoming connections
* Create worker threads to service clients
*/
static void
TransmitFile_Server(void *arg)
{
PRInt32 i;
if (t == NULL) {
goto exit;
}
/*
* Create a tcp socket
*/
goto exit;
}
/*
* try a few times to bind server's address, if addresses are in
* use
*/
i = 0;
if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
if (i++ < SERVER_MAX_BIND_COUNT)
continue;
}
perror("PR_Bind");
goto exit;
}
goto exit;
}
"prsocket_test: ERROR - PR_GetSockName failed\n");
goto exit;
}
DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
/*
* Wake up parent thread because server address is bound and made
* available in the global variable 'tcp_server_addr'
*/
for (i = 0; i < num_transmitfile_clients ; i++) {
/* test both null and non-null 'addr' argument to PR_Accept */
PR_INTERVAL_NO_TIMEOUT)) == NULL) {
"prsocket_test: ERROR - PR_Accept failed\n");
goto exit;
}
/* test both regular and emulated PR_SendFile */
if (i%2) {
"prsocket_test: ERROR - PR_CreateIOLayerStub failed\n");
goto exit;
}
== PR_FAILURE) {
"prsocket_test: ERROR - PR_PushIOLayer failed\n");
goto exit;
}
}
goto exit;
}
/*
* Start a Serve_Client thread for each incoming connection
*/
t[i] = PR_CreateThread(PR_USER_THREAD,
Serve_TransmitFile_Client, (void *)scp,
0);
if (t[i] == NULL) {
"prsocket_test: PR_CreateThread failed\n");
goto exit;
}
DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t));
}
/*
* Wait for all the worker threads to end, so that we know
* they are no longer using the small and large file fd's.
*/
for (i = 0; i < num_transmitfile_clients; i++) {
PR_JoinThread(t[i]);
}
exit:
if (t) {
PR_DELETE(t);
}
if (sockfd) {
}
/*
* Decrement exit_counter and notify parent thread
*/
--(*sp->exit_counter);
}
/*
* Socket_Misc_Test - test miscellaneous functions
*
*/
static PRInt32
Socket_Misc_Test(void)
{
PRThread *t;
/*
* We deliberately pick a buffer size that is not a nice multiple
* of 1024.
*/
typedef struct {
char data[TRANSMITFILE_BUF_SIZE];
} file_buf;
/*
* create file(s) to be transmitted
*/
return -1;
}
if (small_file_fd == NULL) {
rv = -1;
goto done;
}
rv = -1;
goto done;
}
/*
* fill in random data
*/
for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
}
count = 0;
do {
if (bytes <= 0) {
"prsocket_test failed to write to file %s\n",
rv = -1;
goto done;
}
} while (count < SMALL_FILE_SIZE);
#ifdef XP_UNIX
/*
* map the small file; used in checking for data corruption
*/
if (small_file_addr == (void *) -1) {
rv = -1;
goto done;
}
#endif
/*
* header for small file
*/
if (small_file_header == NULL) {
rv = -1;
goto done;
}
/*
* trailer for small file
*/
if (small_file_trailer == NULL) {
rv = -1;
goto done;
}
/*
* setup large file
*/
if (large_file_fd == NULL) {
rv = -1;
goto done;
}
/*
* fill in random data
*/
for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
}
count = 0;
do {
if (bytes <= 0) {
"prsocket_test failed to write to file %s: (%ld, %ld)\n",
PR_GetError(), PR_GetOSError());
rv = -1;
goto done;
}
} while (count < LARGE_FILE_SIZE);
#ifdef XP_UNIX
/*
* map the large file; used in checking for data corruption
*/
if (large_file_addr == (void *) -1) {
rv = -1;
goto done;
}
#endif
/*
* header for large file
*/
if (large_file_header == NULL) {
rv = -1;
goto done;
}
/*
* trailer for large file
*/
if (large_file_trailer == NULL) {
rv = -1;
goto done;
}
thread_count = 0;
/*
* start the server thread
*/
rv = -1;
goto done;
}
server_sem = PR_NewSem(0);
if (server_sem == NULL) {
rv = -1;
goto done;
}
mon2 = PR_NewMonitor();
rv = -1;
goto done;
}
TransmitFile_Server, (void *)sparamp,
0);
if (t == NULL) {
rv = -1;
goto done;
}
DPRINTF(("Created TCP server = 0x%x\n", t));
thread_count++;
/*
* wait till the server address is setup
*/
/*
* Now start a bunch of client threads
*/
rv = -1;
goto done;
}
for (i = 0; i < num_transmitfile_clients; i++) {
TransmitFile_Client, (void *) cparamp,
0, i);
if (t == NULL) {
rv = -1;
goto done;
}
DPRINTF(("Created TransmitFile client = 0x%lx\n", t));
thread_count++;
}
/* Wait for server and client threads to exit */
while (thread_count) {
}
done:
if (buf) {
}
#ifdef XP_UNIX
#endif
}
}
}
return rv;
}
/************************************************************************/
/*
* Test Socket NSPR APIs
*/
int
{
/*
* -d debug mode
*/
{
if (PL_OPT_BAD == os) continue;
{
case 'd': /* debug mode */
_debug_on = 1;
break;
default:
break;
}
}
#ifdef XP_MAC
SetupMacPrintfLog("socket.log");
#endif
/*
* run client-server test with TCP, Ipv4-Ipv4
*/
if (TCP_Socket_Client_Server_Test() < 0) {
printf("TCP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("TCP_Socket_Client_Server_Test Passed\n");
/*
* client-server test, Ipv6-Ipv4
*/
if (TCP_Socket_Client_Server_Test() < 0) {
printf("TCP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("TCP_Socket_Client_Server_Test Passed\n");
/*
* client-server test, Ipv4-Ipv6
*/
if (TCP_Socket_Client_Server_Test() < 0) {
printf("TCP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("TCP_Socket_Client_Server_Test Passed\n");
/*
* client-server test, Ipv6-Ipv6
*/
if (TCP_Socket_Client_Server_Test() < 0) {
printf("TCP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("TCP_Socket_Client_Server_Test Passed\n");
test_cancelio = 0;
/*
*/
if (UDP_Socket_Client_Server_Test() < 0) {
printf("UDP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("UDP_Socket_Client_Server_Test Passed\n");
/*
*/
if (UDP_Socket_Client_Server_Test() < 0) {
printf("UDP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("UDP_Socket_Client_Server_Test Passed\n");
/*
* run client-server test with UDP,IPv4-IPv6
*/
if (UDP_Socket_Client_Server_Test() < 0) {
printf("UDP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("UDP_Socket_Client_Server_Test Passed\n");
/*
* run client-server test with UDP,IPv6-IPv6
*/
if (UDP_Socket_Client_Server_Test() < 0) {
printf("UDP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("UDP_Socket_Client_Server_Test Passed\n");
/*
* Misc socket tests - including transmitfile, etc.
*/
#if !defined(WIN16)
/*
** The 'transmit file' test does not run because
** transmit file is not implemented in NSPR yet.
**
*/
if (Socket_Misc_Test() < 0) {
printf("Socket_Misc_Test failed\n");
goto done;
} else
printf("Socket_Misc_Test passed\n");
/*
* run client-server test with TCP again to test
* recycling used sockets from PR_TransmitFile().
*/
if (TCP_Socket_Client_Server_Test() < 0) {
printf("TCP_Socket_Client_Server_Test failed\n");
goto done;
} else
printf("TCP_Socket_Client_Server_Test Passed\n");
#endif
done:
PR_Cleanup();
if (failed_already) return 1;
else return 0;
}