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;
}
Example #2
0
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;
}
Example #4
0
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;
}
Example #8
0
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 */
Example #9
0
// 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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #14
0
/*
 * _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;
}
Example #15
0
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;
}
Example #16
0
// 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;

}
Example #17
0
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;
}
Example #19
0
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;
}