示例#1
0
static pascal OSStatus DoIncomingBind(OTMPEndpointRef ep, InetPort portNum, OTQLen qlen)
{
	OSStatus err;
	TBind req;
	TBind ret;
	InetAddress reqAddr;
	InetAddress retAddr;

	OTInitInetAddress(&reqAddr, portNum, kOTAnyInetAddress);
	OTMemzero(&req, sizeof(req));
	req.addr.len    = sizeof(reqAddr);
	req.addr.buf    = (UInt8 *) &reqAddr;
	req.qlen        = qlen;
		
	OTMemzero(&ret, sizeof(ret));
	ret.addr.maxlen = sizeof(retAddr);
	ret.addr.buf    = (UInt8 *) &retAddr;
	
	err = OTMPXBind(ep, &req, &ret);
	if (err == noErr) {
		char addrAsStr[32];
		
		OTInetHostToString(retAddr.fHost, addrAsStr);
		MPLogPrintf("\n");
		MPLogPrintf("Bound to = %s:%d with qlen of %d\n", addrAsStr, retAddr.fPort, ret.qlen);
	}
	return err;
}
示例#2
0
static OSStatus ListenTest(OTMPEndpointRef ep)
{
	OSStatus err;
	OSStatus junk;
	TCall call;
	InetAddress remoteAddr;
	OTMPEndpointRef worker;
	
	worker = NULL;
	err = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 0);
	if (err == noErr) {
		err = DoIncomingBind(ep, 1024, 10);
	}
	if (err == noErr) {
		OTMemzero(&remoteAddr, sizeof(remoteAddr));
		OTMemzero(&call, sizeof(call));
		
		call.addr.buf    = (UInt8 *) &remoteAddr;
		call.addr.maxlen = sizeof(remoteAddr);
		
		err = OTMPXListen(ep, &call);
		if (err == noErr) {
			char addrAsStr[100];
			
			OTInetHostToString(remoteAddr.fHost, addrAsStr);
			printf("\n");
			printf("Call from %s:%d\n", addrAsStr, remoteAddr.fPort);
			
			worker = OTMPXOpenEndpointQInContext("tcp", 0, NULL, &err, NULL);
		}
		if (err == noErr) {
			err = OTMPXAccept(ep, worker, &call);
		}
	}
	if (err == noErr) {
		err = OTMPXSndDisconnect(worker, NULL);
	}
	if (err == noErr) {
		err = OTMPXUnbind(ep);
	}
	if (worker != NULL) {
		junk = OTMPXCloseProvider(worker);
		assert(junk == noErr);
	}
	return err;
}
示例#3
0
static pascal OSStatus DoOutgoingBind(OTMPEndpointRef ep)
{
	OSStatus err;
	TBind ret;
	InetAddress boundAddr;
	
	OTMemzero(&ret, sizeof(ret));
	ret.addr.maxlen = sizeof(boundAddr);
	ret.addr.buf    = (UInt8 *) &boundAddr;
	
	err = OTMPXBind(ep, NULL, &ret);
	if (err == noErr) {
		char addrAsStr[32];
		
		OTInetHostToString(boundAddr.fHost, addrAsStr);
		printf("\n");
		printf("boundAddr = %s:%d\n", addrAsStr, boundAddr.fPort);
	}
	return err;
}
示例#4
0
pascal void OTTCPNotifier(void* vobj, OTEventCode code, OTResult result, void* cookie) {
	OTTCP *x = (OTTCP *) vobj;
	long oldA5;
	OSStatus s;
		
	EnterCallback();
	oldA5 = SetA5(x->o_a5);

	post("*** OTTCPNotifier(code %x, result %ld)", (long) code, (long) result);
	
	if (code == T_OPENCOMPLETE) {
		if (result != noErr) {
			post("OTTCPNotifier got a T_OPENCOMPLETE code with error %ld", result);
		}

		// Even if we got an error, we'll use the endpoint.  
		x->o_tcp_ep = (EndpointRef) cookie;
		
		if (x->o_inetHostName != 0) {
			BindTheEndpoint(x);
			// Now we expect a T_BINDCOMPLETE message.
		}
		
	} else if (code == T_BINDCOMPLETE) {
		TCall sndCall;
		InetAddress inAddr;
		
		// See what ephemeral port number OT gave us
		x->o_receiveInetPort = x->o_addrWeActuallyGot.fPort;
		
		// Now the endpoint has been bound; next trick is connecting
		OTInitInetAddress(&inAddr, x->o_inetPort, x->o_inetHost);
		OTMemzero(&sndCall, sizeof(TCall));
		sndCall.addr.buf = (void *) &inAddr;
		sndCall.addr.len = sizeof(InetAddress);

		post("** About to OTConnect");
		s = OTConnect(x->o_tcp_ep, &sndCall, NULL);
		if (s == kOTNoDataErr) {
			// No problem; that means connection is in progress
			post("** OTConnect returned kOTNoDataErr - good");
		} else {
			post("е OTTCP: error: OTConnect returned %ld; not connecting.", s);
		}
		// Now we expect T_CONNECT
		
	} else if (code == T_CONNECT) {
		if (result == kOTBadAddressErr) {
			post("е OTTCP: error: bad address.  Disconnecting");
			x->o_inetHost = 0;
			change_connection(x);
		} else {
			post("** Got T_CONNECT");
			post("** Result passed to notifier: %ld", (long) result);
			post("** Endpoint state before OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep));
			// We could pass in buffers to find out the actual address we connected to, etc.
			s = OTRcvConnect(x->o_tcp_ep, nil);
			if (s != kOTNoError) {
				post("е OTTCP: error: RcvConnect returned %ld", s);
			}
			post("** Endpoint state after OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep));
			ChangeState(x, NO_REQUEST);
			x->o_connectionSymbol = ps_connected;
			clock_delay(x->o_connectedclock, 0);
		}
	} else if (code == T_UNBINDCOMPLETE) {
		// If we have a new inetHost, try to bind it
		if (x->o_inetHost != 0) {
			BindTheEndpoint(x);
			// Now we expect T_BINDCOMPLETE
		} else {
			// No inetHost, so we're disonnected
			x->o_connectionSymbol = ps_disconnected;
			clock_delay(x->o_connectedclock, 0);
		}
	} else if (code == T_DISCONNECTCOMPLETE) {
		// We always want to rebind when we reconnect, so after disconnecting we unbind
		s = OTUnbind(x->o_tcp_ep);
		if (s != kOTNoError) {
			post("OTTCP: warning: OTUnbind returned %ld", s);
		}		
	} else if (code == T_DATA) {
		ottcp_handleIncomingData(x);
	} else if (code == T_UDERR) {
		if (x->o_errorreporting) {
			PostUDERR("OTTCPNotifier was called for a T_UDERR code", x->o_tcp_ep);
		} else {
			/* We still have to receive the error to clear the condition */
			OTRcvUDErr(x->o_tcp_ep, 0);
		}
	} else if (code == T_GODATA) {
		// Flow control restriction has lifted; now it's OK to send more data.
		do_write(x, 0, 0);
	} else if (code == T_DISCONNECT) {
		// The other dude wants to disconnect
		post("OTTCP: peer wants to disconnect");
		s = OTRcvDisconnect(x->o_tcp_ep, NULL);
		if (s == kOTNoError) {
			x->o_inetHost = 0;
			change_connection(x);
		} else if (s == kOTNoDisconnectErr) {
			// false alarm
		} else {
			post("е OTTCP: error: OTRcvDisconnect returned %ld", s);
		}
	} else if (code == T_ORDREL) {
		post("*** Got T_ORDREL");
		s = OTRcvOrderlyDisconnect(x->o_tcp_ep);
		if (s == kOTNoReleaseErr) {
			post("...false alarm!");
		} else if (s == kOTNoError) {
			x->o_inetHost = 0;
			change_connection(x);
		} else {
			post("е OTTCP: error: OTRcvOrderlyDisconnect returned %ld", s);
		}
	} else {
	 	if (x->o_errorreporting) {
			post("OTTCP: Unrecognized OTEventCode %ld in event handler.  Oh well.", (long) code);
		}
	}

done:
	SetA5(oldA5);
	ExitCallback();
}
示例#5
0
static OSStatus SFCSnd(void *parameter)
{
	#pragma unused(parameter)
	OSStatus err;
	OSStatus junk;
	OTMPEndpointRef ep;
	TCall call;
	InetAddress inet;
	OTByteCount bytesThisTime;
	OTByteCount bytesRemaining;

	ep = NULL;
	
	err = OTMPXPrepareThisTask();
	if (err == noErr) {
		ep = OTMPXOpenEndpointQInContext("tcp", 0, NULL, &err, NULL);
	}
	if (err == noErr) {
		gLookerEP = ep;
		err = OTMPXBind(ep, NULL, NULL);
	}
	if (err == noErr) {
		OTInitInetAddress(&inet, 1025, 0x7f000001);			// 127.0.0.1:1025
		OTMemzero(&call, sizeof(call));
		call.addr.buf = (UInt8 *) &inet;
		call.addr.len = sizeof(inet);
		err = OTMPXConnect(ep, &call, NULL);
	}
	if (err == noErr) {
		if (false) {
			bytesRemaining = 0x01000000;						// 16 MB
		} else {
			bytesRemaining = 0x00100000;						// 1 MB
		}
		do {
			if (bytesRemaining > sizeof(gJunkBuffer)) {
				bytesThisTime = sizeof(gJunkBuffer);
			} else {
				bytesThisTime = bytesRemaining;
			}
			err = OTMPXSnd(ep, gJunkBuffer, bytesThisTime, 0);
			if (err > noErr) {
				bytesRemaining -= err;
				err = noErr;
			}
		} while ( (err == noErr) && (bytesRemaining != 0) );
	}
	if (err == noErr) {
		err = OTMPXSndDisconnect(ep, NULL);
	}
	
	gLookerEP = NULL;
	gQuitLooker = true;
	if (ep != NULL) {
		junk = OTMPXCloseProvider(ep);
		assert(junk == noErr);
	}
	
	OTMPXUnprepareThisTask();
	return err;
}
示例#6
0
static OSStatus SFCRcv(void *parameter)
{
	#pragma unused(parameter)
	OSStatus err;
	OSStatus junk;
	OTMPEndpointRef ep;
	TCall call;
	OTFlags junkFlags;
	UInt32  sleepCounter;

	ep = NULL;
	
	err = OTMPXPrepareThisTask();
	if (err == noErr) {
		ep = OTMPXOpenEndpointQInContext("tcp", 0, NULL, &err, NULL);
	}
	if (err == noErr) {
		err = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 1);
	}
	if (err == noErr) {
		err = DoIncomingBind(ep, 1025, 1);
	}
	gRcvStarted = true;
	if (err == noErr) {
		OTMemzero(&call, sizeof(call));
		err = OTMPXListen(ep, &call);
	}
	if (err == noErr) {
		err = OTMPXAccept(ep, ep, &call);
	}
	if (err == noErr) {
		sleepCounter = 0;
		do {
			if (sleepCounter == 0) {
				RcvSleep();
			}
			err = OTMPXRcv(ep, gJunkBuffer, sizeof(gJunkBuffer), &junkFlags);
			if (err > noErr) {
				err = noErr;
			}
			sleepCounter += 1;
			if (sleepCounter > 64) {
				sleepCounter = 0;
			}
		} while (err == noErr);
		if (err == kOTLookErr) {
			OTResult look;
			
			look = OTMPXLook(ep);
			switch (look) {
				case T_ORDREL:
					err = OTMPXRcvOrderlyDisconnect(ep);
					if (err == noErr) {
						err = OTMPXSndOrderlyDisconnect(ep);
					}
					break;
				case T_DISCONNECT:
					err = OTMPXRcvDisconnect(ep, NULL);
					break;
				default:
					MPLogPrintf("look = %08lx\n", look);
					break;
			}
		}
	}
	
	if (ep != NULL) {
		junk = OTMPXCloseProvider(ep);
		assert(junk == noErr);
	}
	
	OTMPXUnprepareThisTask();
	return err;
}
示例#7
0
static OSStatus UnitDataTest(void)
{
	OSStatus err;
	OTMPEndpointRef ep;
	TUnitData udata;
	const char *message = "Hello Cruel World!\x0d\x0a";
	
	ep = OTMPXOpenEndpointQInContext("udp", 0, NULL, &err, NULL);
	if (err == noErr) {
		err = OTMPXBind(ep, NULL, NULL);
	}
	if (err == noErr) {
		InetAddress dest;
		
		OTMemzero(&udata, sizeof(udata));
		OTInitInetAddress(&dest, 7, 0x01020304);
		udata.addr.len = sizeof(dest);
		udata.addr.buf = (UInt8 *) &dest;
		udata.udata.len = OTStrLength(message);
		udata.udata.buf = (UInt8 *) message;
		err = OTMPXSndUData(ep, &udata);
	}
	if (err == noErr) {
		char buffer[256];
		InetAddress src;
		OTFlags junkFlags;
		
		OTMemzero(&udata, sizeof(udata));
		OTMemzero(&src, sizeof(src));
		udata.addr.maxlen  = sizeof(src);
		udata.addr.buf     = (UInt8 *) &src;
		udata.udata.maxlen = sizeof(buffer);
		udata.udata.buf    = (UInt8 *) buffer;
		
		err = OTMPXRcvUData(ep, &udata, &junkFlags);
		if (err == noErr) {
			if ( udata.udata.len != OTStrLength(message) ||
					! OTMemcmp(buffer, message, udata.udata.len) ) {
				err = -1;
			}
		} else if (err == kOTLookErr) {
			OTResult look;

			// If echo server isn't running, previous send will generate 
			// an ICMP port unreachable, which the above RcvUData will return 
			// as a look error and which we consume here.
			
			look = OTMPXLook(ep);
			if (look == T_UDERR) {
				TUDErr   uderr;
				
				OTMemzero(&uderr, sizeof(uderr));
				OTMemzero(&src, sizeof(src));
				uderr.addr.maxlen = sizeof(src);
				uderr.addr.buf    = (UInt8 *) &src;
				uderr.opt.maxlen  = sizeof(buffer);
				uderr.opt.buf     = (UInt8 *) buffer;
				
				err = OTMPXRcvUDErr(ep, &uderr);
				if (err == noErr) {
					printf("uderr src = %08xl\n", src.fHost);
					printf("uderr error = %ld\n", uderr.error);
				}
			}
		}
	}
	if (err == noErr) {
		err = OTMPXUnbind(ep);
	}
	
	if (ep != NULL) {
		OTMPXCloseProvider(ep);
	}
	
	return err;
}
示例#8
0
static OSStatus MiscEndpointTest(OTMPEndpointRef ep)
{
	OSStatus err;
	OSStatus junk;
	TEndpointInfo info;
	char addrAsStr[100];
	
	err = OTMPXGetEndpointInfo(ep, &info);
	if (err == noErr) {
		printf("addr     = %ld\n", info.addr);
		printf("options  = %ld\n", info.options);
		printf("tsdu     = %ld\n", info.tsdu);
		printf("etsdu    = %ld\n", info.etsdu);
		printf("connect  = %ld\n", info.connect);
		printf("discon   = %ld\n", info.discon);
		printf("servtype = %ld\n", info.servtype);
		printf("flags    = %ld\n", info.flags);
	}
	if (err == noErr) {
		err = OTMPXGetEndpointState(ep);
		if (err >= noErr) {
			printf("state1 = %ld\n", err);
			err = noErr;
		}
	}
	if (err == noErr) {
		err = OTMPXBind(ep, NULL, NULL);
	}
	if (err == noErr) {
		err = OTMPXGetEndpointState(ep);
		if (err >= noErr) {
			printf("state2 = %ld\n", err);
			err = noErr;
		}
		if (err == noErr) {
			TBind local;
			InetAddress localAddr;
			
			OTMemzero(&localAddr, sizeof(localAddr));
			OTMemzero(&local, sizeof(local));
			local.addr.maxlen = sizeof(localAddr);
			local.addr.buf    = (UInt8 *) &localAddr;
			err = OTMPXGetProtAddress(ep, &local, NULL);
			if (err == noErr) {
				OTInetHostToString(localAddr.fHost, addrAsStr);
				printf("localAddr = %s:%d\n", addrAsStr, localAddr.fPort);
			}
		}
		if (err == noErr) {
			TBind dns;
			TBind inet;
			DNSAddress  dnsAddr;
			InetAddress inetAddr;
			
			OTMemzero(&dns, sizeof(dns));
			OTMemzero(&inet, sizeof(inet));
			OTMemzero(&inetAddr, sizeof(inetAddr));
			
			dns.addr.len = OTInitDNSAddress(&dnsAddr, "1.2.3.4:80");
			dns.addr.buf = (UInt8 *) &dnsAddr;
			
			inet.addr.maxlen = sizeof(inetAddr);
			inet.addr.buf    = (UInt8 *) &inetAddr;
			
			err = OTMPXResolveAddress(ep, &dns, &inet, 1000);
			if (err == noErr) {
				OTInetHostToString(inetAddr.fHost, addrAsStr);
				printf("inetAddr = %s:%d\n", addrAsStr, inetAddr.fPort);
			}
		}
		junk = OTMPXUnbind(ep);
		assert(junk == noErr);
	}
	if (err == noErr) {
		OTByteCount byteCount;

		byteCount = 666;
		err = OTMPXCountDataBytes(ep, &byteCount);
		assert(err == kOTNoDataErr);
		assert(byteCount == 0);
		if (err == kOTNoDataErr) {
			printf("byteCount = %ld\n", byteCount);
			err = noErr;
		} else {
			err = -1;
		}
	}

	return err;
}
示例#9
0
static OSStatus EchoDisconnectTest(OTMPEndpointRef ep)
{
	OSStatus err;
	
	err = DoOutgoingBind(ep);
	
	if (err == noErr) {
		InetAddress sndAddr;
		InetAddress rcvAddr;
		TCall sndCall;
		TCall rcvCall;
		
		OTInitInetAddress(&sndAddr, 7, 0x7f000001);		// localhost addr
		OTMemzero(&rcvAddr, sizeof(rcvAddr));

		OTMemzero(&sndCall, sizeof(sndCall));
		sndCall.addr.buf = (UInt8 *) &sndAddr;
		sndCall.addr.len = sizeof(sndAddr);
		
		OTMemzero(&rcvCall, sizeof(rcvCall));
		rcvCall.addr.buf    = (UInt8 *) &rcvAddr;
		rcvCall.addr.maxlen = sizeof(rcvAddr);
		
		err = OTMPXConnect(ep, &sndCall, &rcvCall);
		if (err == noErr) {
			OTFlags flags;
			char rcvBuf[100];
			
			printf("\n");
			printf("Now quit Mac TCP Watcher.\n");
			
			OTMemzero(rcvBuf, sizeof(rcvBuf));
			flags = 0;
			err = OTMPXRcv(ep, rcvBuf, sizeof(rcvBuf), &flags);
			if (err == kOTLookErr) {
				OTResult look;

				look = OTMPXLook(ep);
				if (look == T_DISCONNECT) {
					TDiscon discon;
					
					OTMemzero(&discon, sizeof(discon));
					err = OTMPXRcvDisconnect(ep, &discon);
					if (err == noErr) {
						printf("\n");
						printf("Received disconnected with reason %ld.\n", discon.reason);
					}
				} else {
					printf("\n");
					printf("look = %ld\n", look);
				}
			}
		}
	}
	
	if (err == noErr) {
		err = OTMPXUnbind(ep);
	}

	return err;
}
示例#10
0
static OSStatus BasicEchoTest(OTMPEndpointRef ep)
{
	OSStatus err;
	OSStatus err2;
	
	err = DoOutgoingBind(ep);
	
	if (err == noErr) {
		InetAddress sndAddr;
		InetAddress rcvAddr;
		TCall sndCall;
		TCall rcvCall;
		
		OTInitInetAddress(&sndAddr, 7, 0x7f000001);		// localhost addr
		OTMemzero(&rcvAddr, sizeof(rcvAddr));

		OTMemzero(&sndCall, sizeof(sndCall));
		sndCall.addr.buf = (UInt8 *) &sndAddr;
		sndCall.addr.len = sizeof(sndAddr);
		
		OTMemzero(&rcvCall, sizeof(rcvCall));
		rcvCall.addr.buf    = (UInt8 *) &rcvAddr;
		rcvCall.addr.maxlen = sizeof(rcvAddr);
		
		err = OTMPXConnect(ep, &sndCall, &rcvCall);
		if (err == kOTLookErr) {
			OTResult look;
			
			look = OTMPXLook(ep);
			if (look == T_DISCONNECT) {
				TDiscon discon;
				
				OTMemzero(&discon, sizeof(discon));
				err = OTMPXRcvDisconnect(ep, &discon);
				if (err == noErr) {
					printf("\n");
					printf("Connect failed with reason %ld.\n", discon.reason);
				}
			}
		} else if (err == noErr) {
			err = OTMPXSnd(ep, "Hello Cruel World!\x0d\x0a", 20, 0);
			if (err == 20) {
				err = noErr;
			}
			if (err == noErr) {
				OTFlags flags;
				char rcvBuf[100];
				
				OTMemzero(rcvBuf, sizeof(rcvBuf));
				flags = 0;
				err = OTMPXRcv(ep, rcvBuf, sizeof(rcvBuf), &flags);
				if (err == 20) {
					err = noErr;
				}
			}
		
			err2 = OTMPXSndDisconnect(ep, NULL);
			if (err == noErr) {
				err = err2;
			}
		}
	}
	
	if (err == noErr) {
		err = OTMPXUnbind(ep);
	}

	return err;
}
示例#11
0
/* Open a TCP network socket
   If 'remote' is NULL, this creates a local server socket on the given port,
   otherwise a TCP connection to the remote host and port is attempted.
   The newly created socket is returned, or NULL if there was an error.

   ( re-written by masahiro minami<*****@*****.**>
     Now endpoint is created in Async mode.
     01/02/20 )
*/
TCPsocket SDLNet_TCP_Open(IPaddress *ip)
{
	EndpointRef dummy = NULL;

	TCPsocket sock = AsyncTCPNewSocket();
	if( ! sock)
		return NULL;

	// Determin whether bind locally, or connect to remote
	if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) )
	{
		// ######## Connect to remote
		OTResult stat;
		InetAddress inAddr;
		TBind bindReq;

		// Open endpoint
		sock->error = OTAsyncOpenEndpoint(
			OTCreateConfiguration(kTCPName), NULL, &(sock->info),
			(OTNotifyProcPtr)(AsyncTCPNotifier),
			sock );

		AsyncTCPPopEvent( sock );
		while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE)))
		{
			//SetThreadState( kCurrentThreadID, kReadyThreadState, kNoThreadID );
			//YieldToAnyThread();
			//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
			AsyncTCPPopEvent( sock );
		}

		if( !sock->channel )
		{
			SDLNet_SetError("OTAsyncOpenEndpoint failed --- client socket could not be opened");
			goto error_return;
		}

		// Set blocking mode
		// I'm not sure if this is a good solution....
		// Check out Apple's sample code, OT Virtual Server
		// ( 010314 masahiro minami<*****@*****.**>)

		sock->error = OTSetBlocking( sock->channel );
		if( sock->error != kOTNoError )
		{
			SDLNet_SetError("OTSetBlocking() returned an error");
			goto error_return;
		}

		// Bind the socket
		OTInitInetAddress(&inAddr, 0, 0 );
		bindReq.addr.len = sizeof( InetAddress );
		bindReq.addr.buf = (unsigned char*)&inAddr;
		bindReq.qlen = 0;

		sock->error = OTBind( sock->channel, &bindReq, NULL );
		AsyncTCPPopEvent(sock);
		while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
		{
			//YieldToAnyThread();
			//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
			AsyncTCPPopEvent(sock);
		}


		switch( stat = OTGetEndpointState( sock->channel ))
		{
			InetAddress inAddr;
			TCall sndCall;
			OTResult res;

			case T_OUTCON:
				SDLNet_SetError("SDLNet_Open() failed -- T_OUTCON");
				goto error_return;
				break;
			case T_IDLE:
				sock->readShutdown = false;
				sock->writeShutdown = false;
				sock->event &=~T_CONNECT;

				OTMemzero(&sndCall, sizeof(TCall));
				OTInitInetAddress(&inAddr, ip->port, ip->host );
				sndCall.addr.len = sizeof(InetAddress);
				sndCall.addr.buf = (unsigned char*)&inAddr;
				sock->connected = 0;
				res = OTConnect( sock->channel, &sndCall, NULL );
				AsyncTCPPopEvent(sock);
				while( sock->error == kOTNoDataErr || !sock->connected )
					AsyncTCPPopEvent(sock);
				break;
			default:
				// What's to be done ? (TODO)
				SDLNet_SetError("SDLNet_TCP_Open() failed -- EndpointState not good");
				goto error_return;

		}
		if( !(sock->event & (T_CONNECT|T_DISCONNECT)))
			goto error_return;

		AsyncTCPPopEvent( sock );
		while( !(sock->event & (T_CONNECT|T_DISCONNECT)))
		{
			AsyncTCPPopEvent( sock );
		}
		// OTConnect successfull
		if( sock->event & T_CONNECT)
		{
			sock->remoteAddress.host = inAddr.fHost;
			sock->remoteAddress.port = inAddr.fPort;
			sock->sflag = false;
		}
		else
		{
			// OTConnect failed
			sock->event &= ~T_DISCONNECT;
			goto error_return;
		}
	}
	else
	{
		// ######## Bind locally
		TBind bindReq;
		InetAddress	inAddr;

	// First, get InetInterfaceInfo.
	// I don't search for all of them.
	// Does that matter ?

		sock->error = OTAsyncOpenEndpoint(
			OTCreateConfiguration("tilisten, tcp"), NULL, &(sock->info),
			(OTNotifyProcPtr)(AsyncTCPNotifier),
			sock);
		AsyncTCPPopEvent( sock );
		while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
		{
			AsyncTCPPopEvent( sock );
		}

		if( ! sock->channel )
		{
			SDLNet_SetError("OTAsyncOpenEndpoint failed --- server socket could not be opened");
			goto error_return;
		}

		// Create a master OTConfiguration
		sock->config = OTCreateConfiguration(kTCPName);
		if( ! sock->config )
		{
			SDLNet_SetError("Could not create master OTConfiguration");
			goto error_return;
		}

		// Bind the socket
		OTInitInetAddress(&inAddr, ip->port, 0 );
		inAddr.fAddressType = AF_INET;
		bindReq.addr.len = sizeof( InetAddress );
		bindReq.addr.buf = (unsigned char*)&inAddr;
		bindReq.qlen = 35;	// This number is NOT well considered. (TODO)
		sock->localAddress.host = inAddr.fHost;
		sock->localAddress.port = inAddr.fPort;
		sock->sflag = true;
		
		sock->error = OTBind( sock->channel, &bindReq, NULL );
		AsyncTCPPopEvent(sock);
		while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
		{
			AsyncTCPPopEvent(sock);
		}
		if( sock->error != kOTNoError )
		{
			SDLNet_SetError("Could not bind server socket");
			goto error_return;
		}
		
		if( dummy )
			OTCloseProvider( dummy );

	}
	
	sock->ready = 0;
	return sock;
	
	error_return:
	if( dummy )
		OTCloseProvider( dummy );
	SDLNet_TCP_Close( sock );
	return NULL;	
}