static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) { PRInt32 result; const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #ifdef XP_UNIX if (addr->raw.family == AF_UNIX) { /* Disallow relative pathnames */ if (addr->local.path[0] != '/') { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } } #endif /* XP_UNIX */ #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr)); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; }
static PRStatus PrintAddress(const PRNetAddr* address) { PRNetAddr translation; char buffer[ADDR_BUFFER]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_NetAddrToString"); else { PR_fprintf(err, "\t%s\n", buffer); rv = PR_StringToNetAddr(buffer, &translation); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_StringToNetAddr"); else { PRSize addr_len = PR_NETADDR_SIZE(address); if (0 != memcmp(address, &translation, addr_len)) { PR_fprintf(err, "Address translations do not match\n"); DumpAddr(address, "original"); DumpAddr(&translation, "translate"); rv = PR_FAILURE; } } } return rv; } /* PrintAddress */
static PRStatus PR_CALLBACK SocketConnect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; /* Return value of _PR_MD_CONNECT */ const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return PR_FAILURE; } #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv)); if (rv == 0) return PR_SUCCESS; else return PR_FAILURE; }
PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv = -1; PRNetAddr remote; PRFileDesc *accepted = NULL; /* ** The timeout does not apply to the accept portion of the ** operation - it waits indefinitely. */ accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT); if (NULL == accepted) return rv; rv = PR_Recv(accepted, buf, amount, 0, timeout); if (rv >= 0) { /* copy the new info out where caller can see it */ #define AMASK ((PRPtrdiff)7) /* mask for alignment of PRNetAddr */ PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK; *raddr = (PRNetAddr*)(aligned & ~AMASK); memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote)); *nd = accepted; return rv; } PR_Close(accepted); return rv; }
PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRIntn al; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr addrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } if (addr == NULL) { addr = &addrCopy; } al = PR_NETADDR_SIZE(addr); osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL); if (osfd == -1) { return 0; } fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); } else { fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->md.io_model_committed = PR_TRUE; PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF fd2->secret->af = fd->secret->af; #endif } return fd2; }
static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } *nd = NULL; #if defined(WINNT) { PROsfd newSock; PRNetAddr *raddrCopy; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif } } } #else rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); #endif return rv; }
PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, _PR_AcceptTimeoutCallback callback, void *callbackArg) { PRInt32 rv; PROsfd newSock; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr *raddrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } *nd = NULL; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout, PR_TRUE, callback, callbackArg); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF (*nd)->secret->af = sd->secret->af; #endif } } return rv; }
static void DumpAddr(const PRNetAddr* address, const char *msg) { PRUint32 *word = (PRUint32*)address; PRUint32 addr_len = sizeof(PRNetAddr); PR_fprintf(err, "%s[%d]\t", msg, PR_NETADDR_SIZE(address)); while (addr_len > 0) { PR_fprintf(err, " %08x", *word++); addr_len -= sizeof(PRUint32); } PR_fprintf(err, "\n"); } /* DumpAddr */
// Errors: // EBADF -- bad socket id PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 osfd = fd->secret->md.osfd; OSStatus err; EndpointRef endpoint = (EndpointRef) osfd; TBind bindReq; PRThread *me = _PR_MD_CURRENT_THREAD(); if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } if (addr == NULL) { err = kEFAULTErr; goto ErrorExit; } #if !defined(_PR_INET6) addr->inet.family = AF_INET; #endif PR_ASSERT(PR_NETADDR_SIZE(addr) >= (*addrlen)); bindReq.addr.len = *addrlen; bindReq.addr.maxlen = *addrlen; bindReq.addr.buf = (UInt8*) addr; bindReq.qlen = 0; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTGetProtAddress(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PR_ASSERT(me->md.cookie == &bindReq); return kOTNoError; ErrorExit: macsock_map_error(err); return -1; }
static PRInt32 PR_CALLBACK SocketSendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 temp, count; const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif count = 0; while (amount > 0) { temp = _PR_MD_SENDTO(fd, buf, amount, flags, addrp, PR_NETADDR_SIZE(addr), timeout); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } return count; }
static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr) { PRInt32 result; PRUint32 addrlen; addrlen = sizeof(PRNetAddr); result = _PR_MD_GETPEERNAME(fd, addr, &addrlen); if (result < 0) { return PR_FAILURE; } PR_ASSERT(addrlen == PR_NETADDR_SIZE(addr)); #if defined(_PR_INET6) PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6); #else PR_ASSERT(addr->raw.family == AF_INET); #endif return PR_SUCCESS; }
static PRStatus PR_CALLBACK SocketConnect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; /* Return value of _PR_MD_CONNECT */ PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return PR_FAILURE; } rv = _PR_MD_CONNECT(fd, addr, PR_NETADDR_SIZE(addr), timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv)); if (rv == 0) return PR_SUCCESS; else return PR_FAILURE; }
static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) { /* * The definition of the length of a Unix domain socket address * is not uniform, so we don't check it. */ if ((addr != NULL) #if defined(XP_UNIX) || defined(XP_OS2) && (addr->raw.family != AF_UNIX) #endif && (PR_NETADDR_SIZE(addr) != addr_len)) { #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1 /* * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2 * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id * field and is 28 bytes. It is possible for socket functions * to return an addr_len greater than sizeof(struct sockaddr_in6). * We need to allow that. (Bugzilla bug #77264) */ if ((PR_AF_INET6 == addr->raw.family) && (sizeof(addr->ipv6) == addr_len)) { return PR_TRUE; } #endif /* * The accept(), getsockname(), etc. calls on some platforms * do not set the actual socket address length on return. * In this case, we verifiy addr_len is still the value we * passed in (i.e., sizeof(PRNetAddr)). */ #if defined(QNX) if (sizeof(PRNetAddr) == addr_len) { return PR_TRUE; } #endif return PR_FALSE; } return PR_TRUE; }
/* * _PR_EmulateAcceptRead * * Accept an incoming connection on sd, set *nd to point to the * newly accepted socket, read 'amount' bytes from the accepted * socket. * * buf is a buffer of length = (amount + sizeof(PRNetAddr)) * *raddr points to the PRNetAddr of the accepted connection upon * return * * return number of bytes read or -1 on error * */ PRInt32 _PR_EmulateAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv; PRFileDesc *newsockfd; PRNetAddr remote; PRIntervalTime start, elapsed; if (PR_INTERVAL_NO_TIMEOUT != timeout) { start = PR_IntervalNow(); } if ((newsockfd = PR_Accept(sd, &remote, timeout)) == NULL) { return -1; } if (PR_INTERVAL_NO_TIMEOUT != timeout) { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); goto failed; } else { timeout = timeout - elapsed; } } rv = PR_Recv(newsockfd, buf, amount, 0, timeout); if (rv >= 0) { *nd = newsockfd; *raddr = (PRNetAddr *)((char *) buf + amount); memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote)); return rv; } failed: PR_Close(newsockfd); return -1; }
static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) { PRInt32 result; int one = 1; #if defined(_PR_INET6) PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6); #else PR_ASSERT(addr->raw.family == AF_INET); #endif #ifdef HAVE_SOCKET_REUSEADDR if ( setsockopt (fd->secret->md.osfd, (int)SOL_SOCKET, SO_REUSEADDR, (const void *)&one, sizeof(one) ) < 0) { return PR_FAILURE; } #endif result = _PR_MD_BIND(fd, addr, PR_NETADDR_SIZE(addr)); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; }
// Errors: // EBADF -- bad socket id PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog) { #if 0 PRInt32 osfd = fd->secret->md.osfd; OSStatus err; EndpointRef endpoint = (EndpointRef) osfd; TBind bindReq; PRNetAddr addr; PRThread *me = _PR_MD_CURRENT_THREAD(); if (backlog == 0) backlog = 1; if (endpoint == NULL) { err = EBADF; goto ErrorExit; } addr.inet.port = addr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr); bindReq.addr.len = 0; bindReq.addr.buf = (UInt8*) &addr; bindReq.qlen = 0; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTGetProtAddress(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTUnbind(endpoint); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; bindReq.qlen = backlog; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTBind(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PR_ASSERT(me->md.cookie == NULL); return kOTNoError; ErrorExit: macsock_map_error(err); return -1; #endif #pragma unused (fd, backlog) return kOTNoError; }
PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; OSStatus err; EndpointRef endpoint = (EndpointRef) osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); TBind bindReq; PRNetAddr bindAddr; PRInt32 newosfd = -1; EndpointRef newEndpoint; TCall call; PRNetAddr callAddr; if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } memset(&call, 0 , sizeof(call)); call.addr.maxlen = PR_NETADDR_SIZE(&callAddr); call.addr.len = PR_NETADDR_SIZE(&callAddr); call.addr.buf = (UInt8*) &callAddr; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTListen (endpoint, &call); if (err != kOTNoError && (err != kOTNoDataErr || fd->secret->nonblocking)) { me->io_pending = PR_FALSE; goto ErrorExit; } while (err == kOTNoDataErr) { WaitOnThisThread(me, timeout); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTListen (endpoint, &call); if (err == kOTNoError) break; PR_ASSERT(err == kOTNoDataErr); } newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0); if (newosfd == -1) return -1; newEndpoint = (EndpointRef)newosfd; // Bind to a local port; let the system assign it. bindAddr.inet.port = bindAddr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr); bindReq.addr.len = 0; bindReq.addr.buf = (UInt8*) &bindAddr; bindReq.qlen = 0; PrepareThreadForAsyncIO(me, newEndpoint, newosfd); err = OTBind(newEndpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, timeout); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PrepareThreadForAsyncIO(me, endpoint, newosfd); err = OTAccept (endpoint, newEndpoint, &call); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, timeout); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PR_ASSERT(me->md.cookie != NULL); if (addr != NULL) *addr = callAddr; if (addrlen != NULL) *addrlen = call.addr.len; return newosfd; ErrorExit: if (newosfd != -1) _MD_closesocket(newosfd); macsock_map_error(err); return -1; }
static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRUint32 al; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifdef WINNT PRNetAddr addrCopy; #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } #ifdef WINNT if (addr == NULL) { addr = &addrCopy; } #endif al = sizeof(PRNetAddr); osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout); if (osfd == -1) return 0; fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); return NULL; } fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->inheritable = fd->secret->inheritable; #ifdef WINNT if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) { /* * The new socket has been associated with an I/O * completion port. There is no going back. */ fd2->secret->md.io_model_committed = PR_TRUE; } PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #endif /* * On some platforms, the new socket created by accept() * inherits the nonblocking (or overlapped io) attribute * of the listening socket. As an optimization, these * platforms can skip the following _PR_MD_MAKE_NONBLOCK * call. */ #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT) _PR_MD_MAKE_NONBLOCK(fd2); #endif #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE); return fd2; }
PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; OSStatus err; EndpointRef endpoint = (EndpointRef) osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); TCall sndCall; TBind bindReq; PRNetAddr bindAddr; if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } if (addr == NULL) { err = kEFAULTErr; goto ErrorExit; } // Bind to a local port; let the system assign it. bindAddr.inet.port = bindAddr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr); bindReq.addr.len = 0; bindReq.addr.buf = (UInt8*) &bindAddr; bindReq.qlen = 0; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTBind(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; memset(&sndCall, 0 , sizeof(sndCall)); sndCall.addr.maxlen = addrlen; sndCall.addr.len = addrlen; sndCall.addr.buf = (UInt8*) addr; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTConnect (endpoint, &sndCall, NULL); if (err != kOTNoError && err != kOTNoDataErr) goto ErrorExit; if (err == kOTNoDataErr && fd->secret->nonblocking) { err = kEINPROGRESSErr; me->io_pending = PR_FALSE; goto ErrorExit; } WaitOnThisThread(me, timeout); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PR_ASSERT(me->md.cookie != NULL); err = OTRcvConnect(endpoint, NULL); PR_ASSERT(err == kOTNoError); return kOTNoError; ErrorExit: macsock_map_error(err); return -1; }