// CreateProxyRegistrationForRealService() checks to see if the given port is currently // in use, and if so, advertises the specified service as present on that port. // This is useful for advertising existing real services (Personal Web Sharing, Personal // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves. mDNSlocal OSStatus CreateProxyRegistrationForRealService(mDNS *m, UInt16 PortAsNumber, const char txtinfo[], const char *servicetype, ServiceRecordSet *recordset) { InetAddress ia; TBind bindReq; OSStatus err; TEndpointInfo endpointinfo; EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err); if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); } ia.fAddressType = AF_INET; ia.fPort = mDNSOpaque16fromIntVal(PortAsNumber).NotAnInteger; ia.fHost = 0; bindReq.addr.maxlen = sizeof(ia); bindReq.addr.len = sizeof(ia); bindReq.addr.buf = (UInt8*)&ia; bindReq.qlen = 0; err = OTBind(ep, &bindReq, NULL); if (err == kOTBadAddressErr) RegisterService(m, recordset, PortAsNumber, txtinfo, &m->nicelabel, servicetype, "local."); else if (err) debugf("OTBind failed %d", err); OTCloseProvider(ep); return(noErr); }
/*---------------------------------------------------------------------------*/ static AGSocket *AGNetSocketNew(AGNetCtx *ctx) { AGSocket *soc; OSStatus err = noErr; /* Note that in this implementation we don't actually need the AGNetCtx pointer. Left in for source-code compatibility. */ soc = (AGSocket *)malloc(sizeof(AGSocket)); if (NULL == soc) return NULL; bzero(soc, sizeof(AGSocket)); soc->ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL, &err); if (noErr == err) { err = OTBind(soc->ep, NULL, NULL); if (noErr == err) { /* Success. Return newly created socket. */ soc->bound = TRUE; return soc; } OTCloseProvider(soc->ep); } /* Didn't successfully bind, so return error. */ free(soc); return NULL; }
// CreateProxyRegistrationForRealService() checks to see if the given port is currently // in use, and if so, advertises the specified service as present on that port. // This is useful for advertising existing real services (Personal Web Sharing, Personal // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves. static DNSServiceErrorType CreateProxyRegistrationForRealService(RegisteredService *rs, const char *servicetype, UInt16 PortAsNumber, const char txtinfo[]) { mDNSOpaque16 OpaquePort = mDNSOpaque16fromIntVal(PortAsNumber); InetAddress ia; TBind bindReq; OSStatus err; TEndpointInfo endpointinfo; EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err); if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); } ia.fAddressType = AF_INET; ia.fPort = OpaquePort.NotAnInteger; ia.fHost = 0; bindReq.addr.maxlen = sizeof(ia); bindReq.addr.len = sizeof(ia); bindReq.addr.buf = (UInt8*)&ia; bindReq.qlen = 0; err = OTBind(ep, &bindReq, NULL); if (err == kOTBadAddressErr) err = RegisterService(rs, OpaquePort, "", servicetype, "local.", txtinfo); else if (err) printf("OTBind failed %d", err); OTCloseProvider(ep); return(err); }
void BindTheEndpoint(OTUDP *x) { // This will be called from within our notifier function after the endpoint is created, // or, when changing hosts, to re-bind the endpoint after unbinding it. OSStatus err; /* Set up the data structure OTBind will use to say what port number we got */ x->o_bindAddrWeActuallyGot.addr.maxlen = sizeof(struct InetAddress); x->o_bindAddrWeActuallyGot.addr.buf = (unsigned char *) &(x->o_addrWeActuallyGot); if (x->o_writer) { /* Let OTBind pick a return address port number for us */ err = OTBind(x->o_udp_ep, nil, &(x->o_bindAddrWeActuallyGot)); if (err != kOTNoError) { error("¥ otudp: Error %d from OTBind. You may not be able to write.", err); return; } } else { /* Tell OTBind what port number we want to use */ struct InetAddress desiredAddress; TBind bindDesiredAddress; OTInitInetAddress(&desiredAddress, x->o_receiveInetPort, (InetHost) 0); bindDesiredAddress.addr.maxlen = sizeof(struct InetAddress); bindDesiredAddress.addr.len = sizeof(struct InetAddress); bindDesiredAddress.addr.buf = (unsigned char *) &desiredAddress; err = OTBind(x->o_udp_ep, &bindDesiredAddress, &(x->o_bindAddrWeActuallyGot)); if (err != kOTNoError) { error("¥ otudp: Error %d from OTBind. You may not be able to read.", err); return; } } /* Could output something to let the Max programmer know that we're now re-bound... */ }
NMErr OTIPEndpoint::DoBind( PrivateEndpoint *inEP, TBind *inRequest, TBind *outReturned) { NMErr status = kNMNoError; NMBoolean active; active = (inRequest->qlen == 0); if (inEP == mStreamEndpoint && !active) { status = OTUtils::DoNegotiateIPReuseAddrOption(inEP->mEP, true); DEBUG_NETWORK_API(inEP->mEP, "Negotiate Reuse Option", status); status = OTUtils::DoNegotiateTCPNoDelayOption(inEP->mEP, true); DEBUG_NETWORK_API(inEP->mEP, "Negotiate No Delay Option", status); } if (inRequest->addr.buf) { long portNum = ((InetAddress *)inRequest->addr.buf)->fPort; status = OTBind(inEP->mEP, inRequest, outReturned); DEBUG_PRINT("binding; requesting port %d; result: %d; returned port %d",portNum,status,((InetAddress *)outReturned->addr.buf)->fPort); } else{ status = OTBind(inEP->mEP, NULL, outReturned); DEBUG_PRINT("binding to any port; result: %d; returned port %d",status,((InetAddress *)outReturned->addr.buf)->fPort); } DEBUG_NETWORK_API(inEP->mEP, "OTBind", status); if (status) { NMErr code = status; return code; } return status; }
void BindTheEndpoint(OTTCP *x) { OSStatus err; /* Set up the data structure OTBind will use to say what port number we get */ x->o_bindAddrWeActuallyGot.addr.maxlen = sizeof(struct InetAddress); x->o_bindAddrWeActuallyGot.addr.buf = (unsigned char *) &(x->o_addrWeActuallyGot); /* Let OTBind pick a return address port number for us */ err = OTBind(x->o_tcp_ep, nil, &(x->o_bindAddrWeActuallyGot)); if (err != kOTNoError) { ouchstring("otudp: Error %d from OTBind", err); return; } }
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; }
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; }
// 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; }
// 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; }
NMErr OTIPEnumerator::StartEnumeration(void) { TEndpointInfo info; NMErr status = kNMNoError; TBind request; TOption optBuf; //NMUInt8 optBuf[64]; //NMUInt8 fooBuf[32]; TOptMgmt cmd; //NMUInt8 *foo = fooBuf; // If they don't want us to actively get the enumeration, there is nothing to do if (! bActive) return kNMNoError; // first clear out any current items (mCallback)(mContext, kNMEnumClear, NULL); // [Edmark/PBE] 11/16/99 added bFirstIdle = true; // Create an OT endpoint mEP = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &status); if (status) goto error; // fill in the option request cmd.flags = T_NEGOTIATE; cmd.opt.len = kOTFourByteOptionSize; cmd.opt.maxlen = kOTFourByteOptionSize; cmd.opt.buf = (NMUInt8*)&optBuf; // fill in the toption struct optBuf.len = sizeof(TOption); optBuf.level = INET_IP; optBuf.name = kIP_BROADCAST; optBuf.status = 0; optBuf.value[0] = 1; /* cmd.opt.len = 0; cmd.opt.maxlen = 64; cmd.opt.buf = (NMUInt8*)optBuf; cmd.flags = T_NEGOTIATE; // Option management kinda sucks strcpy((char *) fooBuf, "Broadcast = 1"); status = OTCreateOptions(kRawIPName, (char **)&foo, &cmd.opt); */ status = OTOptionManagement(mEP, &cmd, &cmd); if (status) goto error; // Allocate the buffer for receiving the endpoint mIncomingData.udata.buf = (NMUInt8 *) InterruptSafe_alloc(info.tsdu); if (mIncomingData.udata.buf == NULL){ status = kNSpMemAllocationErr; goto error; } mIncomingData.udata.maxlen = info.tsdu; // Bind it request.addr.buf = NULL; request.addr.len = 0; request.addr.maxlen = 0; request.qlen = 0; status = OTBind(mEP, &request, NULL); if (status) goto error; OTSetNonBlocking(mEP); // Get our interface info (for the broadcast address) // Do this after we bind so that we know the interface is live if (! bGotInterfaceInfo) { status = OTInetGetInterfaceInfo(&mInterfaceInfo, kDefaultInetInterface); if (status) goto error; bGotInterfaceInfo = true; } // Install notifier status = OTInstallNotifier(mEP, mNotifier.fUPP, this); if (status) goto error; // Make is asynchronous status = OTSetAsynchronous(mEP); if (status) goto error; // Send out the query mEnumPeriod = 250; status = SendQuery(); error: if (status) { if (mEP) { OTCloseProvider(mEP); // ignore errors mEP = kOTInvalidEndpointRef; } } return status; }
/* GSocket_Connect: * For stream (connection oriented) sockets, GSocket_Connect() tries * to establish a client connection to a server using the peer address * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the * connection has been successfully established, or one of the error * codes listed below. Note that for nonblocking sockets, a return * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection * request can be completed later; you should use GSocket_Select() * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the * corresponding asynchronous events. * * For datagram (non connection oriented) sockets, GSocket_Connect() * just sets the peer address established with GSocket_SetPeer() as * default destination. * * Error codes: * GSOCK_INVSOCK - the socket is in use or not valid. * GSOCK_INVADDR - the peer address has not been established. * GSOCK_TIMEDOUT - timeout, the connection failed. * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only) * GSOCK_MEMERR - couldn't allocate memory. * GSOCK_IOERR - low-level error. */ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) { InetAddress addr ; TEndpointInfo info; OSStatus err = kOTNoError; TCall peer ; assert(sck != NULL); /* Enable CONNECTION events (needed for nonblocking connections) */ sck->m_detected &= ~GSOCK_CONNECTION_FLAG; if (sck->m_endpoint != kOTInvalidEndpointRef ) { sck->m_error = GSOCK_INVSOCK; return GSOCK_INVSOCK; } if (!sck->m_peer) { sck->m_error = GSOCK_INVADDR; return GSOCK_INVADDR; } /* Streamed or dgram socket? */ sck->m_stream = (stream == GSOCK_STREAMED); sck->m_oriented = TRUE; sck->m_server = FALSE; /* Create the socket */ #if TARGET_CARBON sck->m_endpoint = OTOpenEndpointInContext( OTCreateConfiguration( kTCPName) , 0 , &info , &err , NULL ) ; #else sck->m_endpoint = OTOpenEndpoint( OTCreateConfiguration( kTCPName) , 0 , &info , &err ) ; #endif if ( sck->m_endpoint == kOTInvalidEndpointRef || err != kOTNoError ) { sck->m_endpoint = kOTInvalidEndpointRef ; sck->m_error = GSOCK_IOERR; return GSOCK_IOERR; } err = OTBind( sck->m_endpoint , nil , nil ) ; if ( err != kOTNoError ) { return GSOCK_IOERR; } SetDefaultEndpointModes( sck->m_endpoint , sck ) ; // TODO #if 0 ioctl(sck->m_endpoint, FIONBIO, &arg); #endif _GSocket_Enable_Events(sck); _GAddress_translate_to( sck->m_peer , &addr ) ; memset( &peer , 0 , sizeof( TCall ) ) ; peer.addr.len = sizeof( InetAddress ) ; peer.addr.buf = (unsigned char*) &addr ; err = OTConnect( sck->m_endpoint , &peer , nil ) ; if ( err != noErr ) { /* If connect failed with EINPROGRESS and the GSocket object * is in blocking mode, we select() for the specified timeout * checking for writability to see if the connection request * completes. */ if ((err == kOTNoDataErr ) && (!sck->m_non_blocking)) { if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT) { OTSndOrderlyDisconnect( sck->m_endpoint ) ; sck->m_endpoint = kOTInvalidEndpointRef ; /* sck->m_error is set in _GSocket_Output_Timeout */ return GSOCK_TIMEDOUT; } else { /* int error; WX_SOCKLEN_T len = sizeof(error); getsockopt(sck->m_endpoint, SOL_SOCKET, SO_ERROR, (void*) &error, &len); if (!error) */ return GSOCK_NOERROR; } } /* If connect failed with EINPROGRESS and the GSocket object * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK * (and return GSOCK_WOULDBLOCK) but we don't close the socket; * this way if the connection completes, a GSOCK_CONNECTION * event will be generated, if enabled. */ if ((err == kOTNoDataErr) && (sck->m_non_blocking)) { sck->m_error = GSOCK_WOULDBLOCK; return GSOCK_WOULDBLOCK; } /* If connect failed with an error other than EINPROGRESS, * then the call to GSocket_Connect has failed. */ OTSndOrderlyDisconnect( sck->m_endpoint ) ; sck->m_endpoint = kOTInvalidEndpointRef ; sck->m_error = GSOCK_IOERR; return GSOCK_IOERR; } // OTInetEventHandler(sck, T_CONNECT , kOTNoError , NULL ) ; return GSOCK_NOERROR; }
/* 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; }
pascal void EndpointHander::Notifier( void *contextPtr, OTEventCode code, OTResult result, void *cookie) { NMErr status; DEBUG_ENTRY_EXIT("EndpointHander::Notifier"); EndpointHander *epHander = (EndpointHander *) contextPtr; UNUSED_PARAMETER(result); switch (code) { case T_OPENCOMPLETE: // one of our endpoints finished opening //if we were waiting on the stream ep, move on to the datagram ep if necessary if (!(epHander->mState & kGotStreamEP)) { epHander->mNewEP->mStreamEndpoint->mEP = (EndpointRef)cookie; epHander->mState |= kGotStreamEP; if (!(epHander->mState & kGotDatagramEP)) { OTAsyncOpenEndpoint(OTCreateConfiguration(epHander->mListenerEP->GetDatagramProtocolName()), 0, NULL, epHander->mNotifier.fUPP, contextPtr); } } //it must be our datagram ep that's done else { epHander->mNewEP->mDatagramEndpoint->mEP = (EndpointRef)cookie; epHander->mState |= kGotDatagramEP; } //once both eps are done, we go ahead and bind if ((epHander->mState & kGotStreamEP) && (epHander->mState & kGotDatagramEP)) { // Bind the endpoint. Execution continues in the notifier for T_BINDCOMPLETE epHander->mBindReq.addr.len = 0; epHander->mBindReq.addr.buf = NULL; epHander->mBindRet.addr = epHander->mNewEP->mDatagramEndpoint->mLocalAddress; //ECF011114 caused problems under MacOSX... status = OTBind(epHander->mNewEP->mDatagramEndpoint->mEP, NULL, &epHander->mBindRet); //status = OTBind(epHander->mNewEP->mDatagramEndpoint->mEP, &epHander->mBindReq, &epHander->mBindRet); DEBUG_NETWORK_API(epHander->mNewEP->mDatagramEndpoint->mEP, "OTBind", status); } break; case T_BINDCOMPLETE: // The datagram endpoint has finished epHander->mState |= kDatagramDone; // by this time, we should have both endpoints ready to go op_assert(epHander->mState & (kStreamDone | kDatagramDone) == (kStreamDone | kDatagramDone)); // we got the local address from the bind epHander->mState |= kDatagramLocalAddr; // Now that everything is ready, accept the connection epHander->Finish(); break; default: break; } }
NMErr EndpointHander::GetDatagramEP(void) { DEBUG_ENTRY_EXIT("EndpointHander::GetDatagramEP"); CachedEP *datagramEP = NULL; OTLink *acceptorLink = NULL; NMErr status = kNMNoError; // if we're not in uber mode, there should be no datagram ep // just jump to the notifier if (mNewEP->mMode != kNMNormalMode) { Notifier(this, T_BINDCOMPLETE, kNMNoError, NULL); return kNMNoError; } //Try_ { // Get a datagram endpoint from the cache acceptorLink = OTLIFODequeue(&OTEndpoint::sDatagramEPCache.Q); if (acceptorLink) { OTAtomicAdd32(-1, &OTEndpoint::sDatagramEPCache.readyCount); OTAtomicAdd32(-1, &OTEndpoint::sDatagramEPCache.totalCount); //jacked up and good to go mState |= kGotDatagramEP; //get the cache reloading itself OTEndpoint::ServiceEPCaches(); } //if we couldn't get one off the cache, we'll make one after we have a stream endpoint // (one at a time for simplicity) else { if (mState & kGotStreamEP) { return OTAsyncOpenEndpoint(OTCreateConfiguration(mListenerEP->GetDatagramProtocolName()), 0, NULL, mNotifier.fUPP, this); } return kNMNoError; //we just wait for the stream endpoint to get done } // Get the pointer to the cached ep object datagramEP = OTGetLinkObject(acceptorLink, CachedEP, link); op_assert(datagramEP != NULL); // Remove the notifier that was being used for cacheing and install the "normal" one OTRemoveNotifier(datagramEP->ep); OTInstallNotifier(datagramEP->ep, mNotifier.fUPP, this); mNewEP->mDatagramEndpoint->mEP = datagramEP->ep; delete datagramEP; //if we got both endpoints, go ahead and bind here if (mState & kGotStreamEP) { // Bind the endpoint. Execution continues in the notifier for T_BINDCOMPLETE mBindReq.addr.len = 0; mBindReq.addr.buf = NULL; mBindRet.addr = mNewEP->mDatagramEndpoint->mLocalAddress; status = OTBind(mNewEP->mDatagramEndpoint->mEP,NULL, &mBindRet); //status = OTBind(mNewEP->mDatagramEndpoint->mEP,&mBindReq, &mBindRet); DEBUG_NETWORK_API(mNewEP->mDatagramEndpoint->mEP, "OTBind", status); //ThrowIfOSErr_(status); if (status) goto error; } } //Catch_(code) error: if (status) { NMErr code = status; return code; } return kNMNoError; }
/* Open a UDP network socket If 'port' is non-zero, the UDP socket is bound to a fixed local port. */ extern UDPsocket SDLNet_UDP_Open(Uint16 port) { UDPsocket sock; #ifdef MACOS_OPENTRANSPORT EndpointRef dummy = NULL; #endif /* Allocate a UDP socket structure */ sock = (UDPsocket)malloc(sizeof(*sock)); if ( sock == NULL ) { SDLNet_SetError("Out of memory"); goto error_return; } memset(sock, 0, sizeof(*sock)); /* Open the socket */ #ifdef MACOS_OPENTRANSPORT { sock->error = OTAsyncOpenEndpoint( OTCreateConfiguration(kUDPName),0, &(sock->info), (OTNotifyProcPtr)AsyncUDPNotifier, sock ); AsyncUDPPopEvent( sock ); while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE))) { AsyncUDPPopEvent( sock ); } if( sock->error ) { SDLNet_SetError("Could not open UDP socket"); goto error_return; } // Should we ?? // (01/05/03 minami<*****@*****.**> OTSetBlocking( sock->channel ); } #else sock->channel = socket(AF_INET, SOCK_DGRAM, 0); #endif /* MACOS_OPENTRANSPORT */ if ( sock->channel == INVALID_SOCKET ) { SDLNet_SetError("Couldn't create socket"); goto error_return; } #ifdef MACOS_OPENTRANSPORT { InetAddress required, assigned; TBind req_addr, assigned_addr; OSStatus status; InetInterfaceInfo info; memset(&assigned_addr, 0, sizeof(assigned_addr)); assigned_addr.addr.maxlen = sizeof(assigned); assigned_addr.addr.len = sizeof(assigned); assigned_addr.addr.buf = (UInt8 *) &assigned; if ( port ) { status = OTInetGetInterfaceInfo( &info, kDefaultInetInterface ); if( status != kOTNoError ) goto error_return; OTInitInetAddress(&required, port, info.fAddress ); req_addr.addr.maxlen = sizeof( required ); req_addr.addr.len = sizeof( required ); req_addr.addr.buf = (UInt8 *) &required; sock->error = OTBind(sock->channel, &req_addr, &assigned_addr); } else { sock->error = OTBind(sock->channel, nil, &assigned_addr ); } AsyncUDPPopEvent(sock); while( !sock->error && !(sock->completion & CompleteMask(T_BINDCOMPLETE))) { AsyncUDPPopEvent(sock); } if (sock->error != noErr) { SDLNet_SetError("Couldn't bind to local port, OTBind() = %d",(int) status); goto error_return; } sock->address.host = assigned.fHost; sock->address.port = assigned.fPort; #ifdef DEBUG_NET printf("UDP open host = %d, port = %d\n", assigned.fHost, assigned.fPort ); #endif } #else /* Bind locally, if appropriate */ if ( port ) { struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = INADDR_ANY; sock_addr.sin_port = SDL_SwapBE16(port); /* Bind the socket for listening */ if ( bind(sock->channel, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR ) { SDLNet_SetError("Couldn't bind to local port"); goto error_return; } /* Fill in the channel host address */ sock->address.host = sock_addr.sin_addr.s_addr; sock->address.port = sock_addr.sin_port; } /* Allow LAN broadcasts with the socket */ { int yes = 1; setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); } #endif /* MACOS_OPENTRANSPORT */ /* The socket is ready */ return(sock); error_return: #ifdef MACOS_OPENTRANSPORT if( dummy ) OTCloseProvider( dummy ); #endif SDLNet_UDP_Close(sock); return(NULL); }
int connect_chuukei_server(char *prf_name) { #ifndef MACINTOSH #ifdef WINDOWS WSADATA wsaData; WORD wVersionRequested = (WORD) (( 1) | ( 1 << 8)); #endif struct sockaddr_in ask; struct hostent *hp; if (read_chuukei_prf(prf_name) < 0) { printf("Wrong prf file\n"); return (-1); } if (init_buffer() < 0) { printf("Malloc error\n"); return (-1); } #ifdef WINDOWS if (WSAStartup(wVersionRequested, &wsaData)) { msg_print("Report: WSAStartup failed."); return (-1); } #endif printf("server = %s\nport = %d\n", server_name, server_port); if ((hp = gethostbyname(server_name)) != NULL) { memset(&ask, 0, sizeof(ask)); memcpy(&ask.sin_addr, hp->h_addr_list[0], hp->h_length); } else { if ((ask.sin_addr.s_addr=inet_addr(server_name)) == 0) { printf("Bad hostname\n"); return (-1); } } ask.sin_family = AF_INET; ask.sin_port = htons((unsigned short)server_port); #ifndef WINDOWS if ((sd=socket(PF_INET,SOCK_STREAM, 0)) < 0) #else if ((sd=socket(PF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET) #endif { printf("Can't create socket\n"); return (-1); } if (connect(sd, (struct sockaddr *)&ask, sizeof(ask)) < 0) { close(sd); printf("Can't connect %s port %d\n", server_name, server_port); return (-1); } return (0); #else /* MACINTOSH */ OSStatus err; InetHostInfo response; InetHost host_addr; InetAddress inAddr; TCall sndCall; Boolean bind = false; OSStatus junk; if (read_chuukei_prf(prf_name) < 0){ printf("Wrong prf file\n"); return (-1); } init_buffer(); printf("server = %s\nport = %d\n", server_name, server_port); #if TARGET_API_MAC_CARBON err = InitOpenTransportInContext(kInitOTForApplicationMask, NULL); #else err = InitOpenTransport(); #endif memset(&response, 0, sizeof(response)); #if TARGET_API_MAC_CARBON inet_services = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, NULL); #else inet_services = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err); #endif if (err == noErr) { err = OTInetStringToAddress(inet_services, (char *)server_name, &response); if (err == noErr) { host_addr = response.addrs[0]; } else { printf("Bad hostname\n"); } #if TARGET_API_MAC_CARBON ep = (void *)OTOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0, nil, &err, NULL); #else ep = (void *)OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err); #endif if (err == noErr) { err = OTBind(ep, nil, nil); bind = (err == noErr); } if (err == noErr){ OTInitInetAddress(&inAddr, server_port, host_addr); sndCall.addr.len = sizeof(InetAddress); sndCall.addr.buf = (unsigned char*) &inAddr; sndCall.opt.buf = nil; /* no connection options */ sndCall.opt.len = 0; sndCall.udata.buf = nil; /* no connection data */ sndCall.udata.len = 0; sndCall.sequence = 0; /* ignored by OTConnect */ err = OTConnect(ep, &sndCall, NULL); if( err != noErr ){ printf("Can't connect %s port %d\n", server_name, server_port); } } err = OTSetSynchronous(ep); if (err == noErr) err = OTSetBlocking(ep); } if( err != noErr ){ if( bind ){ OTUnbind(ep); } /* Clean up. */ if (ep != kOTInvalidEndpointRef) { OTCloseProvider(ep); ep = nil; } if (inet_services != nil) { OTCloseProvider(inet_services); inet_services = nil; } return -1; } return 0; #endif }