PRFileDesc* Resolver :: ar_open() { if (NULL == afd && _res.nscount > 0) { if (_res.options & RES_USEVC) { struct sockaddr_in *sip; int i = 0; sip = _res.nsaddr_list; ar_vc = 1; afd = PR_NewTCPSocket(); /* * Try each name server listed in sequence until we * succeed or run out. */ while (PR_Connect(afd, (PRNetAddr *)sip++, PR_INTERVAL_NO_TIMEOUT)) { PR_Close(afd); afd = NULL; if (i++ >= _res.nscount) break; afd = PR_NewTCPSocket(); } } else { afd = PR_NewUDPSocket(); } } return afd; }
/**doc $TOC_MEMBER $INAME $INAME( [type = Socket.TCP] ) Type can be Socket.TCP or Socket.UDP. **/ DEFINE_CONSTRUCTOR() { PRFileDesc *fd = NULL; JL_DEFINE_ARGS; JL_ASSERT_CONSTRUCTING(); { JL_DEFINE_CONSTRUCTOR_OBJ; int descType; if ( JL_ARG_ISDEF(1) ) JL_CHK( jl::getValue(cx, JL_ARG(1), &descType) ); else descType = PR_DESC_SOCKET_TCP; // default if ( descType == PR_DESC_SOCKET_TCP ) fd = PR_NewTCPSocket(); else if ( descType == PR_DESC_SOCKET_UDP ) fd = PR_NewUDPSocket(); else JL_ERR( E_ARG, E_NUM(1), E_INVALID ); if ( fd == NULL ) return ThrowIoError(cx); JL_CHK( jl::reserveStreamReadInterface(cx, JL_OBJ) ); JL_SetPrivate(JL_OBJ, fd); } return true; bad: if ( fd ) PR_Close(fd); return false; }
int main(int argc, char **argv) #endif { PRUintn pdkey; PRStatus status; char *path = NULL; PRDir *dir = NULL; PRLock *ml = NULL; PRCondVar *cv = NULL; PRThread *thread = NULL; PRIntervalTime interval = 0; PRFileDesc *file, *udp, *tcp, *pair[2]; PRIntn test; if ( argc < 2) { test = 0; } else test = atoi(argv[1]); switch (test) { case 0: ml = PR_NewLock(); break; case 1: interval = PR_SecondsToInterval(1); break; case 2: thread = PR_CreateThread( PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); break; case 3: file = PR_Open("/usr/tmp/", PR_RDONLY, 0); break; case 4: udp = PR_NewUDPSocket(); break; case 5: tcp = PR_NewTCPSocket(); break; case 6: dir = PR_OpenDir("/usr/tmp/"); break; case 7: (void)PR_NewThreadPrivateIndex(&pdkey, NULL); break; case 8: path = PR_GetEnv("PATH"); break; case 9: status = PR_NewTCPSocketPair(pair); break; case 10: PR_SetConcurrency(2); break; default: printf( "lazyinit: unrecognized command line argument: %s\n", argv[1] ); printf( "FAIL\n" ); exit( 1 ); break; } /* switch() */ return 0; } /* Lazy */
// 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); switch (addr->protocol) { case IPPROTO_UDP: if (!(fd_ = PR_NewUDPSocket())) { r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket"); ABORT(R_INTERNAL); } break; case IPPROTO_TCP: if (!(fd_ = PR_NewTCPSocket())) { r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket"); ABORT(R_INTERNAL); } break; default: 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_,addr->protocol,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); }
int main(int argc, char **argv) { PRStatus rv; PRFileDesc *udp = PR_NewUDPSocket(); PRFileDesc *tcp = PR_NewTCPSocket(); const char *tag[] = { "PR_SockOpt_Nonblocking", /* nonblocking io */ "PR_SockOpt_Linger", /* linger on close if data present */ "PR_SockOpt_Reuseaddr", /* allow local address reuse */ "PR_SockOpt_Keepalive", /* keep connections alive */ "PR_SockOpt_RecvBufferSize", /* send buffer size */ "PR_SockOpt_SendBufferSize", /* receive buffer size */ "PR_SockOpt_IpTimeToLive", /* time to live */ "PR_SockOpt_IpTypeOfService", /* type of service and precedence */ "PR_SockOpt_AddMember", /* add an IP group membership */ "PR_SockOpt_DropMember", /* drop an IP group membership */ "PR_SockOpt_McastInterface", /* multicast interface address */ "PR_SockOpt_McastTimeToLive", /* multicast timetolive */ "PR_SockOpt_McastLoopback", /* multicast loopback */ "PR_SockOpt_NoDelay", /* don't delay send to coalesce packets */ "PR_SockOpt_MaxSegment", /* maximum segment size */ "PR_SockOpt_Broadcast", /* Enable broadcast */ "PR_SockOpt_Last" }; err = PR_GetSpecialFD(PR_StandardError); PR_STDIO_INIT(); if (NULL == udp) Failed("PR_NewUDPSocket()", NULL); else if (NULL == tcp) Failed("PR_NewTCPSocket()", NULL); else { PRSockOption option; PRUint32 segment = 1024; PRNetAddr addr; rv = PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr); if (PR_FAILURE == rv) Failed("PR_InitializeNetAddr()", NULL); rv = PR_Bind(udp, &addr); if (PR_FAILURE == rv) Failed("PR_Bind()", NULL); for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option)) { PRSocketOptionData data; PRFileDesc *fd = tcp; data.option = option; switch (option) { case PR_SockOpt_Nonblocking: data.value.non_blocking = PR_TRUE; break; #ifndef SYMBIAN case PR_SockOpt_Linger: data.value.linger.polarity = PR_TRUE; data.value.linger.linger = PR_SecondsToInterval(2); break; #endif case PR_SockOpt_Reuseaddr: data.value.reuse_addr = PR_TRUE; break; case PR_SockOpt_Keepalive: data.value.keep_alive = PR_TRUE; break; case PR_SockOpt_RecvBufferSize: data.value.recv_buffer_size = segment; break; case PR_SockOpt_SendBufferSize: data.value.send_buffer_size = segment; break; #ifndef SYMBIAN case PR_SockOpt_IpTimeToLive: data.value.ip_ttl = 64; break; case PR_SockOpt_IpTypeOfService: data.value.tos = 0; break; case PR_SockOpt_McastTimeToLive: fd = udp; data.value.mcast_ttl = 4; break; case PR_SockOpt_McastLoopback: fd = udp; data.value.mcast_loopback = PR_TRUE; break; #endif case PR_SockOpt_NoDelay: data.value.no_delay = PR_TRUE; break; #ifndef WIN32 case PR_SockOpt_MaxSegment: data.value.max_segment = segment; break; #endif #ifndef SYMBIAN case PR_SockOpt_Broadcast: fd = udp; data.value.broadcast = PR_TRUE; break; #endif default: continue; } /* * TCP_MAXSEG can only be read, not set */ if (option != PR_SockOpt_MaxSegment) { #ifdef WIN32 if (option != PR_SockOpt_McastLoopback) #endif { rv = PR_SetSocketOption(fd, &data); if (PR_FAILURE == rv) Failed("PR_SetSocketOption()", tag[option]); } } rv = PR_GetSocketOption(fd, &data); if (PR_FAILURE == rv) Failed("PR_GetSocketOption()", tag[option]); } PR_Close(udp); PR_Close(tcp); } PR_fprintf(err, "%s\n", (failed) ? "FAILED" : "PASSED"); return (failed) ? 1 : 0; } /* main */
/* * 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) { Client_Param *cp = (Client_Param *) arg; PRFileDesc *sockfd; buffer *in_buf, *out_buf; union PRNetAddr netaddr; PRInt32 bytes, i, rv; bytes = cp->datalen; out_buf = PR_NEW(buffer); if (out_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } if ((sockfd = PR_NewUDPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); failed_already=1; return; } /* * bind an address for the client, let the system chose the port * number */ memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = AF_INET; netaddr.inet.ip = PR_htonl(INADDR_ANY); netaddr.inet.port = PR_htons(0); if (PR_Bind(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; return; } DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); netaddr.inet.family = cp->server_addr.inet.family; netaddr.inet.port = cp->server_addr.inet.port; netaddr.inet.ip = cp->server_addr.inet.ip; if (cp->udp_connect) { if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr,"prsocket_test: PR_Connect failed\n"); failed_already=1; 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", PR_GetCurrentThread(), out_buf->data, bytes)); memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes); /* * write to server */ if (cp->udp_connect) rv = PR_Send(sockfd, out_buf->data, bytes, 0, PR_INTERVAL_NO_TIMEOUT); else rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); if (cp->udp_connect) rv = PR_Recv(sockfd, in_buf->data, bytes, 0, PR_INTERVAL_NO_TIMEOUT); else rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n", PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data)))); /* * verify the data read */ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n"); failed_already=1; return; } } PR_Close(sockfd); PR_DELETE(in_buf); PR_DELETE(out_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(cp->exit_mon); --(*cp->exit_counter); PR_Notify(cp->exit_mon); PR_ExitMonitor(cp->exit_mon); PR_DELETE(cp); DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread())); }
/* * 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) { Server_Param *sp = (Server_Param *) arg; PRFileDesc *sockfd; buffer *in_buf; PRNetAddr netaddr; PRInt32 bytes, i, rv; bytes = sp->datalen; /* * Create a udp socket */ if ((sockfd = PR_NewUDPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); failed_already=1; return; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = AF_INET; netaddr.inet.port = PR_htons(UDP_SERVER_PORT); netaddr.inet.ip = PR_htonl(INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); failed_already=1; return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; return; } if (netaddr.inet.port != PR_htons(UDP_SERVER_PORT)) { fprintf(stderr,"prsocket_test: ERROR - tried to bind to UDP " "port %hu, but was bound to port %hu\n", UDP_SERVER_PORT, PR_ntohs(netaddr.inet.port)); failed_already=1; return; } DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); udp_server_addr = netaddr; /* * We can't use the IP address returned by PR_GetSockName in * netaddr.inet.ip because netaddr.inet.ip is returned * as 0 (= INADDR_ANY). */ udp_server_addr.inet.ip = PR_htonl(INADDR_LOOPBACK); /* * Wake up parent thread because server address is bound and made * available in the global variable 'udp_server_addr' */ PR_PostSem(sp->addr_sem); bytes = sp->datalen; in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } /* * Receive datagrams from clients and send them back, unmodified, to the * clients */ memset(&netaddr, 0 , sizeof(netaddr)); 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", netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, in_buf->data[0])); rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, in_buf->data[0])); if (rv != bytes) { return; } rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } } PR_DELETE(in_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread())); }