Ejemplo n.º 1
0
static OSErr CreateSocket(int type, EndpointRef *endpoint)
{
	OSStatus err;
	PRThread *me = _PR_MD_CURRENT_THREAD();

	switch (type){
		case SOCK_STREAM:
			err = OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL, 
					NotifierRoutine, me);
			break;
		case SOCK_DGRAM:
			err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL,
					NotifierRoutine, me);
			break;
	}
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	*endpoint = me->md.cookie;
	PR_ASSERT(*endpoint != NULL);

	return kOTNoError;

ErrorExit:
	return err;
}
Ejemplo n.º 2
0
PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name)
{
	OSStatus err;
	PRUint32 index;
	PRThread *me = _PR_MD_CURRENT_THREAD();

	PrepareThreadForAsyncIO(me, sSvcRef, NULL);    

    err = OTInetStringToAddress(sSvcRef, (char *)name, &sHostInfo);
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	sHostEnt.h_name = sHostInfo.name;
	for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
		sAddresses[index] = &sHostInfo.addrs[index];
	sAddresses[index] = NULL;	
	sHostEnt.h_addr_list = (char **)sAddresses;

	return (&sHostEnt);

ErrorExit:
	macsock_map_error(err);
    return NULL;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
{
	OSStatus err;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	TOptMgmt cmd;
	TOption *opt;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
	
	/* 
	OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
	are equated to IP level and TCP level options respectively and hence we need to set 
	the level correctly.
	*/
	if (level == SOL_SOCKET) {
		if (optname == SO_REUSEADDR)
			level = IPPROTO_IP;
		else if (optname == SO_KEEPALIVE)
			level = INET_TCP;
	}

	opt = (TOption *)&optionBuffer[0];
	opt->len = kOTOptionHeaderSize + optlen;

	/* special case adjustments for length follow */
	if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
		opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
	if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
		opt->len = kOTOneByteOptionSize;
	if (optname == IP_TOS && level == IPPROTO_IP)
		opt->len = kOTOneByteOptionSize;

	opt->level = level;
	opt->name = optname;
	opt->status = 0;
	
	cmd.opt.len = opt->len;
	cmd.opt.maxlen = sizeof(optionBuffer);
	cmd.opt.buf = (UInt8*)optionBuffer;
	
	optionBuffer[opt->len] = 0;
	
	cmd.flags = T_NEGOTIATE;

	switch (optname) {
		case SO_LINGER:
			*((t_linger*)&opt->value) = *((t_linger*)optval);
			break;
		case SO_REUSEADDR:
		case TCP_NODELAY:
		case SO_RCVBUF:
		case SO_SNDBUF:
			*((PRIntn*)&opt->value) = *((PRIntn*)optval);
			break;
		case IP_MULTICAST_LOOP:
			if (*optval != 0)
				opt->value[0] = T_YES;
			else
				opt->value[0] = T_NO;
			break;
		case SO_KEEPALIVE:
			{
			t_kpalive *kpalive = (t_kpalive *)&opt->value;
			
			kpalive->kp_onoff = *((long*)optval);
			kpalive->kp_timeout = 10; /* timeout in minutes */
			break;
			}
		case IP_TTL:
			*((unsigned char*)&opt->value) = *((PRUintn*)optval);
			break;
		case IP_MULTICAST_TTL:
			*((unsigned char*)&opt->value) = *optval;
			break;
		case IP_ADD_MEMBERSHIP:
		case IP_DROP_MEMBERSHIP:
			{
			/* struct ip_mreq and TIPAddMulticast are the same size and optval 
			   is pointing to struct ip_mreq */
			*((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
			break;
			}
		case IP_MULTICAST_IF:
			{
			*((PRUint32*)&opt->value) = *((PRUint32*)optval);
			break;
			}
		/*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
		case TCP_MAXSEG:
			if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
				*((PRIntn*)&opt->value) = *((PRIntn*)optval);
			} else { /* it is IP_TOS */
				*((unsigned char*)&opt->value) = *((PRUintn*)optval);
			}
			break;
		default:
			PR_ASSERT(0);
			break;	
	}
	
	PrepareThreadForAsyncIO(me, endpoint, osfd);    

	err = OTOptionManagement(endpoint, &cmd, &cmd);
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}
	
	if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}

	PR_ASSERT(opt->status == T_SUCCESS);

	return PR_SUCCESS;

ErrorExit:
	macsock_map_error(err);
    return PR_FAILURE;
}
Ejemplo n.º 7
0
PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
{
	OSStatus err;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	TOptMgmt cmd;
	TOption *opt;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
	
	/* 
	OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
	are equated to IP level and TCP level options respectively and hence we need to set 
	the level correctly.
	*/
	if (level == SOL_SOCKET) {
		if (optname == SO_REUSEADDR)
			level = IPPROTO_IP;
		else if (optname == SO_KEEPALIVE)
			level = INET_TCP;
	}

	opt = (TOption *)&optionBuffer[0];
	opt->len = sizeof(TOption);
	opt->level = level;
	opt->name = optname;
	opt->status = 0;
	
	cmd.opt.len = sizeof(TOption);
	cmd.opt.maxlen = sizeof(optionBuffer);
	cmd.opt.buf = (UInt8*)optionBuffer;
	cmd.flags = T_CURRENT;

	PrepareThreadForAsyncIO(me, endpoint, osfd);    

	err = OTOptionManagement(endpoint, &cmd, &cmd);
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}

	PR_ASSERT(opt->status == T_SUCCESS);

	switch (optname) {
		case SO_LINGER:
			*((t_linger*)optval) = *((t_linger*)&opt->value);
			*optlen = sizeof(t_linger);
			break;
		case SO_REUSEADDR:
		case TCP_NODELAY:
		case SO_KEEPALIVE:
		case SO_RCVBUF:
		case SO_SNDBUF:
			*((PRIntn*)optval) = *((PRIntn*)&opt->value);
			*optlen = sizeof(PRIntn);
			break;
		case IP_MULTICAST_LOOP:
			*((PRUint8*)optval) = *((PRIntn*)&opt->value);
			*optlen = sizeof(PRUint8);
			break;
		case IP_TTL:
			*((PRUintn*)optval) = *((PRUint8*)&opt->value);
			*optlen = sizeof(PRUintn);
			break;
		case IP_MULTICAST_TTL:
			*((PRUint8*)optval) = *((PRUint8*)&opt->value);
			*optlen = sizeof(PRUint8);
			break;
		case IP_ADD_MEMBERSHIP:
		case IP_DROP_MEMBERSHIP:
			{
			/* struct ip_mreq and TIPAddMulticast are the same size and optval 
			   is pointing to struct ip_mreq */
			*((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
			*optlen = sizeof(struct ip_mreq);
			break;
			}
		case IP_MULTICAST_IF:
			{
			*((PRUint32*)optval) = *((PRUint32*)&opt->value);
			*optlen = sizeof(PRUint32);
			break;
			}
		/*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
		case TCP_MAXSEG:
			if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
				*((PRIntn*)optval) = *((PRIntn*)&opt->value);
				*optlen = sizeof(PRIntn);
			} else { /* it is IP_TOS */
				*((PRUintn*)optval) = *((PRUint8*)&opt->value);
				*optlen = sizeof(PRUintn);
			}
			break;
		default:
			PR_ASSERT(0);
			break;	
	}
	
	return PR_SUCCESS;

ErrorExit:
	macsock_map_error(err);
    return PR_FAILURE;
}
Ejemplo n.º 8
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;

}
Ejemplo n.º 9
0
// Errors:
// EBADF -- bad socket id
// EFAULT -- bad address format
PRInt32 _MD_bind(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();
	PRUint32 retryCount = 0;

	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
		
	if (addr == NULL) {
		err = kEFAULTErr;
		goto ErrorExit;
	}
		
	// setup our request
#if 0
	if ((addr->inet.port == 0) || (addr->inet.ip == 0))
		bindReq.addr.len = 0;
	else
#endif
/*
 * There seems to be a bug with OT ralted to OTBind failing with kOTNoAddressErr eventhough
 * a proper legal address was supplied.  This happens very rarely and just retrying the
 * operation after a certain time (less than 1 sec. does not work) seems to succeed.
 */

TryAgain:
	bindReq.addr.len = addrlen;
		
	bindReq.addr.maxlen = addrlen;
	bindReq.addr.buf = (UInt8*) addr;
	bindReq.qlen = 1;
	
	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:
	if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
		long finalTicks;
	
	    Delay(100,&finalTicks);
		goto TryAgain;
	}
	macsock_map_error(err);
    return -1;
}
Ejemplo n.º 10
0
// Errors:
// EBADF -- bad socket id
// EFAULT -- bad buffer
static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount, 
                               PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, 
                               PRIntervalTime timeout, SndRcvOpCode opCode)
{
	OSStatus err;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	PRInt32 bytesLeft = amount;
	TUnitData dgram;

	PR_ASSERT(flags == 0);
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
		
	if (buf == NULL || addr == NULL) {
		err = kEFAULTErr;
		goto ErrorExit;
	}
		
	memset(&dgram, 0 , sizeof(dgram));
	dgram.addr.maxlen = *addrlen;
	dgram.addr.len = *addrlen;
	dgram.addr.buf = (UInt8*) addr;
	dgram.udata.maxlen = amount;
	dgram.udata.len = amount;
	dgram.udata.buf = (UInt8*) buf;	

	while (bytesLeft > 0) {
	
		PrepareThreadForAsyncIO(me, endpoint, osfd);    

		if (opCode == kDGRAM_SEND)
			err = OTSndUData(endpoint, &dgram);
		else if (opCode == kDGRAM_RECEIVE)
			err = OTRcvUData(endpoint, &dgram, NULL);
		else {
			err = kEINVALErr;
			goto ErrorExit;
		}

		if (err == kOTNoError) {
			buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
			bytesLeft -= dgram.udata.len;
			dgram.udata.buf = (UInt8*) buf;	
    		me->io_pending = PR_FALSE;
		}
		else {
			PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
			WaitOnThisThread(me, timeout);
			err = me->md.osErrCode;
			if (err != kOTNoError)
				goto ErrorExit;

			PR_ASSERT(me->md.cookie != NULL);
		}
	}

	if (opCode == kDGRAM_RECEIVE)
		*addrlen = dgram.addr.len;

	return amount;

ErrorExit:
	macsock_map_error(err);
    return -1;
}                               
Ejemplo n.º 11
0
// Errors:
// EBADF -- bad socket id
// EFAULT -- bad buffer
static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, 
                               PRIntn flags, PRIntervalTime timeout, SndRcvOpCode opCode)
{
	OSStatus err;
	OTResult result;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	PRInt32 bytesLeft = amount;

	PR_ASSERT(flags == 0);
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
		
	if (buf == NULL) {
		err = kEFAULTErr;
		goto ErrorExit;
	}
		
	while (bytesLeft > 0) {
	
		PrepareThreadForAsyncIO(me, endpoint, osfd);    

		if (opCode == kSTREAM_SEND)
			result = OTSnd(endpoint, buf, bytesLeft, NULL);
		else if (opCode == kSTREAM_RECEIVE)
			result = OTRcv(endpoint, buf, bytesLeft, NULL);
		else {
			err = kEINVALErr;
			goto ErrorExit;
		}

		if (result > 0) {
			buf = (void *) ( (UInt32) buf + (UInt32)result );
			bytesLeft -= result;
    		me->io_pending = PR_FALSE;
    		if (opCode == kSTREAM_RECEIVE)
    			return result;
		} else {
			if (result == kOTOutStateErr) { /* it has been closed */
				return 0;
			}
			if (result == kOTLookErr) {
				PRBool readReady,writeReady,exceptReady;
				/* process the event and then continue the operation */
				(void) GetState(endpoint, &readReady, &writeReady, &exceptReady);
				continue;
			}
			if (result != kOTNoDataErr && result != kOTFlowErr && 
			    result != kEAGAINErr && result != kEWOULDBLOCKErr) {
				err = result;
				goto ErrorExit;
			} else if (fd->secret->nonblocking) {
    			me->io_pending = PR_FALSE;
				err = result;
				goto ErrorExit;
			}
			WaitOnThisThread(me, timeout);
			err = me->md.osErrCode;
			if (err != kOTNoError)
				goto ErrorExit;

			PR_ASSERT(me->md.cookie != NULL);
		}
	}

	return amount;

ErrorExit:
	macsock_map_error(err);
    return -1;
}                               
Ejemplo n.º 12
0
// ====================== 1st thread
PRInt32 readWriteProc(PRFileDesc fd, void buf, PRUint32 bytes, IOOperation op)
{
        PRInt32 refNum; 
	OSErr err;
	int pbAsync_pb;
	int me_io_pending;

	// quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout 
	// note, if a user chooses "seek" or the like as an operation in another function 
	// this will not work 
	if (refNum >= 0 && refNum < 3)
	{
		switch (refNum)
		{
				case 0:
				  //stdin - not on a Mac for now
					err = paramErr;
					goto ErrorExit;
					break;
		                case 1: // stdout 
		                case 2: // stderr
					puts();
					break;
		}
		
		return (bytes);
	}
	else
	{
		PRBool  doingAsync = PR_FALSE;

		// 
		// Issue the async read call and wait for the io semaphore associated
		// with this thread.
		// Async file system calls *never* return error values, so ignore their
		// results (see <http://developer.apple.com/technotes/fl/fl_515.html>);
		// the completion routine is always called.
		//
		if (op == READ_ASYNC)
		{
		  //
		  //  Skanky optimization so that reads < 20K are actually done synchronously
		  //  to optimize performance on small reads (e.g. registry reads on startup)
		  //
			if ( bytes > 20480L )
			{
				doingAsync = PR_TRUE;
				{ __ESBMC_atomic_begin();
				if (__COUNT__ == 0) {
				  me_io_pending = PR_TRUE; // check for order violation
				  __COUNT__ = __COUNT__ + 1;
				} else {
				  assert(0);
				}
                 __ESBMC_atomic_end();
				}
				__START_ASYNC__ = True; // second thread can start
				(void)PBReadAsync(pbAsync_pb);
			}
			else
			{
				me_io_pending = PR_FALSE;
				
				err = PBReadSync(pbAsync_pb);
				if (err != noErr && err != eofErr)
					goto ErrorExit;
			}
		}
		else
		{
			doingAsync = PR_TRUE;
			me_io_pending = PR_TRUE;

			// writes are currently always async 
			(void)PBWriteAsync(pbAsync_pb);
		}
		
		if (doingAsync) {
			WaitOnThisThread(PR_INTERVAL_NO_TIMEOUT);
		}
	}
	
	if (err != noErr)
		goto ErrorExit;

	if (err != noErr && err != eofErr)
		goto ErrorExit;
	
	return; 

ErrorExit:
	_MD_SetError(err);
	return -1;
}