JSBool TCP_listen (JSContext* cx, JSObject* object, uintN argc, jsval* argv, jsval* rval) { char* host; int port = -1; int maxconn = 255; jsval jsConnected; JS_BeginRequest(cx); if (argc < 1) { JS_ReportError(cx, "Not enough parameters."); JS_EndRequest(cx); return JS_FALSE; } JS_EnterLocalRootScope(cx); switch (argc) { case 3: JS_ValueToInt32(cx, argv[2], &maxconn); case 2: JS_ValueToInt32(cx, argv[1], &port); case 1: host = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); } TCPInformation* data = (TCPInformation*) JS_GetPrivate(cx, object); PRNetAddr addr; if (JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0])) { PR_InitializeNetAddr(PR_IpAddrAny, port, &addr); } else { __Sockets_initAddr(&addr, host, port); } JS_LeaveLocalRootScope(cx); int on = 1; setsockopt(PR_GET_FD(data->socket), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); jsrefcount req = JS_SuspendRequest(cx); if (PR_Bind(data->socket, &addr) == PR_FAILURE) { JS_ResumeRequest(cx, req); switch (PR_GetError()) { case PR_NO_ACCESS_RIGHTS_ERROR: JS_ReportError(cx, "You can't listen on this port."); break; default: JS_ReportError(cx, "Something went wrong."); break; } JS_EndRequest(cx); return JS_FALSE; } if (PR_Listen(data->socket, maxconn) == PR_FAILURE) { JS_ResumeRequest(cx, req); switch (PR_GetError()) { default: JS_ReportError(cx, "Something went wrong."); break; } JS_EndRequest(cx); return JS_FALSE; } JS_ResumeRequest(cx, req); jsConnected = JSVAL_TRUE; JS_SetProperty(cx, object, "connected", &jsConnected); JS_EndRequest(cx); return JS_TRUE; }
int FileSSL_main(int argc, char * argv[]) { bool isServer = true; SECStatus rv = SECSuccess; char buffer[32] = {0}; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); PK11_SetPasswordFunc(GetModulePassword); rv = NSS_Initialize(GetSystemDBDir(), "", "", "secmod.db", 0); rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); rv = SSL_OptionSetDefault(SSL_SOCKS, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_FDX, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); rv = NSS_SetDomesticPolicy(); rv = NSS_SetExportPolicy(); rv = NSS_SetFrancePolicy(); // rv = SSL_CipherPolicySet(); SSL_ClearSessionCache(); rv = SSL_ConfigServerSessionIDCache(10, 30 , 30, "."); PRFileDesc * socket = PR_NewTCPSocket(); socket = SSL_ImportFD(NULL,socket); if (isServer) { CERTCertDBHandle *certHandle; certHandle = CERT_GetDefaultCertDB(); char * nickname = "itrus Certificate DB:2013-11-15 12:44:10";/*nickname*/ CERTCertificate* cert = NULL; cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickname); SECKEYPrivateKey *prvKey = NULL; prvKey = PK11_FindKeyByAnyCert(cert, NULL); rv = SSL_ConfigSecureServer(socket, cert,prvKey,ssl_kea_rsa); PRNetAddr netAddr; PRNetAddr netAddrLocal; rv = PR_InitializeNetAddr(0, 8888, &netAddr); rv = PR_StringToNetAddr("127.0.0.1", &netAddrLocal); rv = PR_Bind(socket,&netAddr); rv = PR_Listen(socket, 100); while (1) { PRFileDesc * client = PR_Accept(socket, &netAddr, 6000000); PRNetAddr addr; rv = PR_GetSockName(client, &addr); rv = SSL_ForceHandshake(client); rv = PR_Write(client,"123", 4); sleep(1); } } else { rv = SSL_SetURL(socket, "127.0.0.1"); PRNetAddr netAddr; PRNetAddr netAddrLocal; rv = PR_InitializeNetAddr(0, 8888, &netAddr); rv = PR_StringToNetAddr("127.0.0.1", &netAddrLocal); // rv = PR_GetHostByName(); // PR_EnumerateHostEnt rv = PR_Connect(socket,&netAddr, 300000); rv = SSL_AuthCertificateHook(socket, OwnAuthCertHandler, NULL); rv = SSL_ForceHandshake(socket); while (1) { rv = PR_Read(socket,buffer, 32); sleep(1); } } return 0; }
void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else Test_Result(FAIL); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else Test_Result(FAIL); PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else Test_Result(FAIL); PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; }
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRInt32 retVal; /* 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 */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); 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; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Error\n"); printf("reporting operations are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing bad fd */ if (debug_mode) printf("PR_Select should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); failed_already=1; goto exit_now; } PR_FD_SET(badFD, &readFdSet); /* * Make the fd invalid */ #if defined(XP_UNIX) close(PR_FileDesc2NativeHandle(badFD)); #elif defined(XP_OS2) soclose(PR_FileDesc2NativeHandle(badFD)); #elif defined(WIN32) || defined(WIN16) closesocket(PR_FileDesc2NativeHandle(badFD)); #else #error "Unknown architecture" #endif retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Select returns %d\n", retVal); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); failed_already=1; } goto exit_now; } if (debug_mode) printf("PR_Select detected a bad fd. Test passed.\n\n"); PR_FD_CLR(badFD, &readFdSet); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; }
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; /* 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 */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); 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; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("error reporting is tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; npds = 2; /* Testing bad fd */ if (debug_mode) printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); goto exit_now; } pds[2].fd = badFD; pds[2].in_flags = PR_POLL_READ; npds = 3; if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc, badFD, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0) == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[2].out_flags); failed_already=1; goto exit_now; } if (debug_mode) printf("PR_Poll detected the bad fd. Test passed.\n\n"); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; }
static bool NewTCPSocketPair(PRFileDesc *fd[], bool aSetRecvBuff) { // this is a replacement for PR_NewTCPSocketPair that manually // sets the recv buffer to 64K. A windows bug (1248358) // can result in using an incompatible rwin and window // scale option on localhost pipes if not set before connect. SOCKET_LOG(("NewTCPSocketPair %s a recv buffer tuning\n", aSetRecvBuff ? "with" : "without")); PRFileDesc *listener = nullptr; PRFileDesc *writer = nullptr; PRFileDesc *reader = nullptr; PRSocketOptionData recvBufferOpt; recvBufferOpt.option = PR_SockOpt_RecvBufferSize; recvBufferOpt.value.recv_buffer_size = 65535; PRSocketOptionData nodelayOpt; nodelayOpt.option = PR_SockOpt_NoDelay; nodelayOpt.value.no_delay = true; PRSocketOptionData noblockOpt; noblockOpt.option = PR_SockOpt_Nonblocking; noblockOpt.value.non_blocking = true; listener = PR_OpenTCPSocket(PR_AF_INET); if (!listener) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(listener, &recvBufferOpt); } PR_SetSocketOption(listener, &nodelayOpt); PRNetAddr listenAddr; memset(&listenAddr, 0, sizeof(listenAddr)); if ((PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &listenAddr) == PR_FAILURE) || (PR_Bind(listener, &listenAddr) == PR_FAILURE) || (PR_GetSockName(listener, &listenAddr) == PR_FAILURE) || // learn the dynamic port (PR_Listen(listener, 5) == PR_FAILURE)) { goto failed; } writer = PR_OpenTCPSocket(PR_AF_INET); if (!writer) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(writer, &recvBufferOpt); } PR_SetSocketOption(writer, &nodelayOpt); PR_SetSocketOption(writer, &noblockOpt); PRNetAddr writerAddr; if (PR_InitializeNetAddr(PR_IpAddrLoopback, ntohs(listenAddr.inet.port), &writerAddr) == PR_FAILURE) { goto failed; } if (PR_Connect(writer, &writerAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { if ((PR_GetError() != PR_IN_PROGRESS_ERROR) || (PR_ConnectContinue(writer, PR_POLL_WRITE) == PR_FAILURE)) { goto failed; } } reader = PR_Accept(listener, &listenAddr, PR_MillisecondsToInterval(200)); if (!reader) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(reader, &recvBufferOpt); } PR_SetSocketOption(reader, &nodelayOpt); PR_SetSocketOption(reader, &noblockOpt); PR_Close(listener); fd[0] = reader; fd[1] = writer; return true; failed: if (listener) { PR_Close(listener); } if (reader) { PR_Close(reader); } if (writer) { PR_Close(writer); } return false; }
static void AcceptingThread(void *arg) { PRStatus rv; PRInt32 bytes; PRSize buf_size = BUF_SIZE; PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32]; PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg; PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket(); PRSocketOptionData sock_opt; if (NULL == listen_sock) { PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed"); PR_ProcessExit(1); } sock_opt.option = PR_SockOpt_Reuseaddr; sock_opt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(listen_sock, &sock_opt); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_SetSocketOption (server) failed"); PR_ProcessExit(1); } rv = PR_Bind(listen_sock, listen_addr); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Bind (server) failed"); PR_ProcessExit(1); } rv = PR_Listen(listen_sock, 10); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Listen (server) failed"); PR_ProcessExit(1); } bytes = PR_AcceptRead( listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout); if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed"); else { PrintAddress(accept_addr); PR_fprintf( std_out, "(Server) read [0x%p..0x%p) %s\n", buf, &buf[BUF_SIZE], buf); bytes = PR_Write(accept_sock, buf, bytes); rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Shutdown (server) failed"); } if (-1 != bytes) { rv = PR_Close(accept_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } rv = PR_Close(listen_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } /* AcceptingThread */
static void NativeSelectTest(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); return; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address\n"); PR_Close(listenSocket); return; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); PR_Close(listenSocket); return; } if (debug_mode) printf("Listening on port %d\n", PORT); { PRIntn osfd; char buf[11]; fd_set rdset; PRNetAddr rAddr; PRFileDesc *newSock; struct timeval timeout; PRInt32 bytesRead, rv, loops = 0; loops++; if (debug_mode) printf("Going into accept\n"); newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT); if (newSock) { if (debug_mode) printf("Got connection!\n"); } else { if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError()); else Test_Result (FAIL); } osfd = PR_FileDesc2NativeHandle(newSock); FD_ZERO(&rdset); FD_SET(osfd, &rdset); if (debug_mode) printf("Going into select \n"); timeout.tv_sec = 2; timeout.tv_usec = 0; rv = select(osfd + 1, &rdset, NULL, NULL, &timeout); if (debug_mode) printf("return from select is %d\n", rv); if (FD_ISSET(osfd, &rdset)) if (debug_mode) printf("I can't believe it- the socket is ready okay!\n"); else if (debug_mode) printf("Damn; the select test failed...\n"); else Test_Result (FAIL); strcpy(buf, "XXXXXXXXXX"); bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT); buf[10] = '\0'; if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf); PR_Close(newSock); } } /* NativeSelectTest */
int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRThread *clientThread; PRPollDesc pds0[20], pds1[20], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRIntn i, j; PRSocketOptionData optval; /* 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 */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); 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; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; /* Add some unused entries to test if they are ignored by PR_Poll() */ memset(&pds[2], 0, sizeof(pds[2])); memset(&pds[3], 0, sizeof(pds[3])); memset(&pds[4], 0, sizeof(pds[4])); npds = 5; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* two clients, three events per iteration: accept, read, close */ i = 0; while (i < 2 * 3 * NUM_ITERATIONS) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); failed_already=1; goto exit_now; } } for (j = 2; j < npds; j++) { if (NULL == pds[j].fd) { /* * Keep the unused entries in the poll descriptor array * for testing purposes. */ other_pds[nextIndex] = pds[j]; nextIndex++; continue; } PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nAvail; PRInt32 nRead; nEvents++; nAvail = PR_Available(pds[j].fd); nRead = PR_Read(pds[j].fd, buf, sizeof(buf)); PR_ASSERT(nAvail == nRead); if (nRead == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } else if (nRead == 0) { PR_Close(pds[j].fd); continue; } else { /* Just to be safe */ buf[127] = '\0'; if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); failed_already=1; goto exit_now; } other_pds[nextIndex] = pds[j]; nextIndex++; } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } if (debug_mode) printf("Tests passed\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; }
// nr_socket APIs (as member functions) int NrSocket::create(nr_transport_addr *addr) { int r,_status; PRStatus status; PRNetAddr naddr; nsresult rv; nsCOMPtr<nsISocketTransportService> stservice = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (!NS_SUCCEEDED(rv)) { ABORT(R_INTERNAL); } if((r=nr_transport_addr_to_praddr(addr, &naddr))) ABORT(r); if (!(fd_ = PR_NewUDPSocket())) { r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket"); ABORT(R_INTERNAL); } status = PR_Bind(fd_, &naddr); if (status != PR_SUCCESS) { r_log(LOG_GENERIC,LOG_CRIT,"Couldn't bind socket to address %s", addr->as_string); ABORT(R_INTERNAL); } r_log(LOG_GENERIC,LOG_DEBUG,"Creating socket %p with addr %s", fd_, addr->as_string); nr_transport_addr_copy(&my_addr_,addr); /* If we have a wildcard port, patch up the addr */ if(nr_transport_addr_is_wildcard(addr)){ status = PR_GetSockName(fd_, &naddr); if (status != PR_SUCCESS){ r_log(LOG_GENERIC, LOG_CRIT, "Couldn't get sock name for socket"); ABORT(R_INTERNAL); } if((r=nr_praddr_to_transport_addr(&naddr,&my_addr_,1))) ABORT(r); } // Set nonblocking PRSocketOptionData option; option.option = PR_SockOpt_Nonblocking; option.value.non_blocking = PR_TRUE; status = PR_SetSocketOption(fd_, &option); if (status != PR_SUCCESS) { r_log(LOG_GENERIC, LOG_CRIT, "Couldn't make socket nonblocking"); ABORT(R_INTERNAL); } // Remember our thread. ststhread_ = do_QueryInterface(stservice, &rv); if (!NS_SUCCEEDED(rv)) ABORT(R_INTERNAL); // Finally, register with the STS rv = stservice->AttachSocket(fd_, this); if (!NS_SUCCEEDED(rv)) { ABORT(R_INTERNAL); } _status = 0; abort: return(_status); }
static void PollThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) struct _timeb end_time_tb; #endif PRFileDesc *sock; PRNetAddr addr; PRPollDesc pd; PRIntn rv; sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_READ; rv = PR_Poll(&pd, 1, timeout); if (rv != 0) { fprintf(stderr, "PR_Poll did not time out\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (debug_mode) { fprintf(stderr, "Poll thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } }