Example #1
0
/* Local functions for initializing and cleaning up the DNS resolver */
static int OpenDNS(void)
{
	int retval;
	OSStatus status;

	retval = 0;
	status = OTAsyncOpenInternetServices(
		kDefaultInternetServicesPath, 0, OpenDNSNotifier, NULL);
	if ( status == noErr ) {
		InetInterfaceInfo	info;
		
		dnsStatus.stat = dnsNotReady;
		
		while( dnsStatus.stat != dnsError && dnsStatus.dns == NULL)
		{
			// what's to be done ? Yield ? WaitNextEvent ? or what ?
			// ( 010311 masahiro minami<*****@*****.**> )
			//YieldToAnyThread();
		}
		/* Get the address of the local system -
		   What should it be if ethernet is off?
		 */
		OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
		OTlocalhost = info.fAddress;
	} else {
		SDLNet_SetError("Unable to open DNS handle");
		retval = status;
	}
	
	return(retval);
}
Example #2
0
/* Initialize/Cleanup the network API */
int  SDLNet_Init(void)
{
	OSStatus status;
	int retval;

	dnsStatus.stat = dnsNotReady;
	dnsStatus.dns = 0;


	retval = 0;
	if ( ! SDLNet_started ) {
		status = InitOpenTransport();
		if ( status == noErr ) {
			retval = OpenDNS();
			if ( retval < 0 ) {
				SDLNet_Quit();
			}
		} else {
			SDLNet_SetError("Unable to initialize Open Transport");
			retval = status;
		}
	}
	if ( retval == 0 ) {
		++SDLNet_started;
	}
	return(retval);
}
Example #3
0
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
   This function returns the actual amount of data sent.  If the return value
   is less than the amount of data sent, then either the remote connection was
   closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
{
	const Uint8 *data = (const Uint8 *)datap;	/* For pointer arithmetic */
	int sent, left;

	/* Server sockets are for accepting connections only */
	if ( sock->sflag ) {
		SDLNet_SetError("Server sockets cannot send");
		return(-1);
	}

	/* Keep sending data until it's sent or an error occurs */
	left = len;
	sent = 0;
	errno = 0;
	do {
		len = send(sock->channel, (const char *) data, left, 0);
		if ( len > 0 ) {
			sent += len;
			left -= len;
			data += len;
		}
	} while ( (left > 0) && ((len > 0) || (errno == EINTR)) );

	return(sent);
}
Example #4
0
/* Initialize/Cleanup the network API */
int  SDLNet_Init(void)
{
    if ( !SDLNet_started ) {
#ifdef __USE_W32_SOCKETS
        /* Start up the windows networking */
        WORD version_wanted = MAKEWORD(1,1);
        WSADATA wsaData;

        if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
            SDLNet_SetError("Couldn't initialize Winsock 1.1\n");
            return(-1);
        }
#else
        /* SIGPIPE is generated when a remote socket is closed */
        /*
        void (*handler)(int);
        handler = signal(SIGPIPE, SIG_IGN);
        if ( handler != SIG_DFL ) {
        	signal(SIGPIPE, handler);
        }*/
#endif
    }
    ++SDLNet_started;
    return(0);
}
Example #5
0
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
   This function returns the actual amount of data sent.  If the return value
   is less than the amount of data sent, then either the remote connection was
   closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
{
	const Uint8 *data = (const Uint8 *)datap;	/* For pointer arithmetic */
	int sent, left;

	/* Server sockets are for accepting connections only */
	if ( sock->sflag ) {
		SDLNet_SetError("Server sockets cannot send");
		return(-1);
	}

	/* Keep sending data until it's sent or an error occurs */
	left = len;
	sent = 0;
	errno = 0;
	do {
		len = OTSnd(sock->channel, (void *)data, left, 0);
		if (len == kOTFlowErr)
			len = 0;
		if ( len > 0 ) {
			sent += len;
			left -= len;
			data += len;
		}
		// Do we need to ?
		// ( masahiro minami<*****@*****.**> )
		// (TODO)
		//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
		//AsyncTCPPopEvent(sock);
	} while ( (left > 0) && (len > 0) );

	return(sent);
}
Example #6
0
/* Verify that the channel is in the valid range */
static int ValidChannel(int channel)
{
    if ( (channel < 0) || (channel >= SDLNET_MAX_UDPCHANNELS) ) {
        SDLNet_SetError("Invalid channel");
        return(0);
    }
    return(1);
}
Example #7
0
int	my_send(TCPsocket sock, void *datap, int len)
{
//   Uint8 *data = (Uint8 *)datap;	/* For pointer arithmetic */
  int	sent;

  if (sock->sflag)
    {
      SDLNet_SetError("Server sockets cannot send");
      return (-1);
    }
  errno = 0;
#ifdef MACOS_OPENTRANSPORT
  sent = OTSnd(sock-.channel, datap, len, 0);
#else
  sent = send(sock->channel, (const char *) datap, len, 0);
  if (errno != EINTR && errno)
    SDLNet_SetError(strerror(errno));
#endif
  return (sent);
}
Example #8
0
/* Add a socket to a set of sockets to be checked for available data */
int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
	if ( sock != NULL ) {
		if ( set->numsockets == set->maxsockets ) {
			SDLNet_SetError("socketset is full");
			return(-1);
		}
		set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
	}
	return(set->numsockets);
}
Example #9
0
int	my_recv(TCPsocket sock, void *data, int maxlen)
{
  int	len;

  /* Server sockets are for accepting connections only */
  if (sock->sflag)
    {
      SDLNet_SetError("Server sockets cannot receive");
      return(-1);
    }
  errno = 0;
/* FIXME: necessary or not? */
/*   do { */
    len = recv(sock->channel, (char *) data, maxlen, 0);
/*   } while ( errno == EINTR ); */
  return (len);
}
Example #10
0
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
   and store them in the buffer pointed to by 'data'.
   This function returns the actual amount of data received.  If the return
   value is less than or equal to zero, then either the remote connection was
   closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
{
    int len;

    /* Server sockets are for accepting connections only */
    if ( sock->sflag ) {
        SDLNet_SetError("Server sockets cannot receive");
        return(-1);
    }

    SDLNet_SetLastError(0);
    do {
        len = recv(sock->channel, (char *) data, maxlen, 0);
    } while ( SDLNet_GetLastError() == EINTR );

    sock->ready = 0;
    return(len);
}
Example #11
0
/* Remove a socket from a set of sockets to be checked for available data */
int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
	int i;

	if ( sock != NULL ) {
		for ( i=0; i<set->numsockets; ++i ) {
			if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
				break;
			}
		}
		if ( i == set->numsockets ) {
			SDLNet_SetError("socket not found in socketset");
			return(-1);
		}
		--set->numsockets;
		for ( ; i<set->numsockets; ++i ) {
			set->sockets[i] = set->sockets[i+1];
		}
	}
	return(set->numsockets);
}
Example #12
0
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
   and store them in the buffer pointed to by 'data'.
   This function returns the actual amount of data received.  If the return
   value is less than or equal to zero, then either the remote connection was
   closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
{
	int len = 0;
	OSStatus res;
	/* Server sockets are for accepting connections only */
	if ( sock->sflag ) {
		SDLNet_SetError("Server sockets cannot receive");
		return(-1);
	}

	do
	{
		res = OTRcv(sock->channel, data, maxlen-len, 0);
		if (res > 0) {
			len = res;
		}

#ifdef DEBUG_NET
		if ( res != kOTNoDataErr )
			printf("SDLNet_TCP_Recv received ; %d\n", res );
#endif
		
		AsyncTCPPopEvent(sock);
		if( res == kOTLookErr )
		{
			res = OTLook(sock->channel );
			continue;
		}
	} while ( (len == 0) && (res == kOTNoDataErr) );

	sock->ready = 0;
	if ( len == 0 ) { /* Open Transport error */
#ifdef DEBUG_NET
		printf("Open Transport error: %d\n", res);
#endif
		return(-1);
	}
	return(len);
}
Example #13
0
/* Allocate/free a single UDP packet 'size' bytes long.
   The new packet is returned, or NULL if the function ran out of memory.
 */
extern UDPpacket *SDLNet_AllocPacket(int size)
{
    UDPpacket *packet;
    int error;


    error = 1;
    packet = (UDPpacket *)malloc(sizeof(*packet));
    if ( packet != NULL ) {
        packet->maxlen = size;
        packet->data = (Uint8 *)malloc(size);
        if ( packet->data != NULL ) {
            error = 0;
        }
    }
    if ( error ) {
        SDLNet_SetError("Out of memory");
        SDLNet_FreePacket(packet);
        packet = NULL;
    }
    return(packet);
}
Example #14
0
// Because TCPsocket structure gets bigger and bigger,
// I think we'd better have a constructor function and delete function.
// ( 01/02/25 masahiro minami<*****@*****.**> )
/*static*/ UDPsocket AsyncUDPNewSocket()
{
	UDPsocket sock;
	
	sock = (UDPsocket)malloc(sizeof(*sock));
	if ( sock == NULL ) {
		SDLNet_SetError("Out of memory");
		return NULL;
	}
	
	sock->newEvent = 0;
	sock->event = 0;
	sock->curEvent = 0;
	sock->newCompletion = 0;
	sock->completion = 0;
	sock->curCompletion = 0;
	//sock->info = NULL;
	sock->readShutdown = sock->writeShutdown = false;
	sock->error = 0;
	sock->config = NULL;
	
	return sock;	
}
Example #15
0
// Because TCPsocket structure gets bigger and bigger,
// I think we'd better have a constructor function and delete function.
// ( 01/02/25 masahiro minami<*****@*****.**> )
static TCPsocket AsyncTCPNewSocket()
{
	TCPsocket sock;
	
	sock = (TCPsocket)malloc(sizeof(*sock));
	if ( sock == NULL ) {
		SDLNet_SetError("Out of memory");
		return NULL;
	}
	
	sock->newEvent = 0;
	sock->event = 0;
	sock->curEvent = 0;
	sock->newCompletion = 0;
	sock->completion = 0;
	sock->curCompletion = 0;
	//sock->info = NULL;
	sock->readShutdown = sock->writeShutdown = sock->connected = false;
	sock->error = 0;
	sock->config = NULL;
	sock->nextListener = NULL;
	sock->sflag = 0;
	return sock;	
}
Example #16
0
/* Bind the address 'address' to the requested channel on the UDP socket.
   If the channel is -1, then the first unbound channel will be bound with
   the given address as it's primary address.
   If the channel is already bound, this new address will be added to the
   list of valid source addresses for packets arriving on the channel.
   If the channel is not already bound, then the address becomes the primary
   address, to which all outbound packets on the channel are sent.
   This function returns the channel which was bound, or -1 on error.
*/
int SDLNet_UDP_Bind(UDPsocket sock, int channel, IPaddress *address)
{
	struct UDP_channel *binding;

	if ( channel == -1 ) {
		for ( channel=0; channel < SDLNET_MAX_UDPCHANNELS; ++channel ) {
			binding = &sock->binding[channel];
			if ( binding->numbound < SDLNET_MAX_UDPADDRESSES ) {
				break;
			}
		}
	} else {
		if ( ! ValidChannel(channel) ) {
			return(-1);
		}
		binding = &sock->binding[channel];
	}
	if ( binding->numbound == SDLNET_MAX_UDPADDRESSES ) {
		SDLNet_SetError("No room for new addresses");
		return(-1);
	}
	binding->address[binding->numbound++] = *address;
	return(channel);
}
Example #17
0
/* Send a vector of packets to the the channels specified within the packet.
   If the channel specified in the packet is -1, the packet will be sent to
   the address in the 'src' member of the packet.
   Each packet will be updated with the status of the packet after it has
   been sent, -1 if the packet send failed.
   This function returns the number of packets sent.
*/
int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets)
{
    int numsent, i, j;
    struct UDP_channel *binding;
    int status;
    int sock_len;
    struct sockaddr_in sock_addr;

    if ( sock == NULL ) {
        SDLNet_SetError("Passed a NULL socket");
        return(0);
    }

    /* Set up the variables to send packets */
    sock_len = sizeof(sock_addr);

    numsent = 0;
    for ( i=0; i<npackets; ++i )
    {
        /* Simulate packet loss, if desired */
        if (sock->packetloss) {
            if ((random()%100) <= sock->packetloss) {
                packets[i]->status = packets[i]->len;
                ++numsent;
                continue;
            }
        }

        /* if channel is < 0, then use channel specified in sock */

        if ( packets[i]->channel < 0 )
        {
            sock_addr.sin_addr.s_addr = packets[i]->address.host;
            sock_addr.sin_port = packets[i]->address.port;
            sock_addr.sin_family = AF_INET;
            status = sendto(sock->channel,
                    packets[i]->data, packets[i]->len, 0,
                    (struct sockaddr *)&sock_addr,sock_len);
            if ( status >= 0 )
            {
                packets[i]->status = status;
                ++numsent;
            }
        }
        else
        {
            /* Send to each of the bound addresses on the channel */
#ifdef DEBUG_NET
            printf("SDLNet_UDP_SendV sending packet to channel = %d\n", packets[i]->channel );
#endif

            binding = &sock->binding[packets[i]->channel];

            for ( j=binding->numbound-1; j>=0; --j )
            {
                sock_addr.sin_addr.s_addr = binding->address[j].host;
                sock_addr.sin_port = binding->address[j].port;
                sock_addr.sin_family = AF_INET;
                status = sendto(sock->channel,
                        packets[i]->data, packets[i]->len, 0,
                        (struct sockaddr *)&sock_addr,sock_len);
                if ( status >= 0 )
                {
                    packets[i]->status = status;
                    ++numsent;
                }
            }
        }
    }

    return(numsent);
}
Example #18
0
/* Accept an incoming connection on the given server socket.
   The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Accept(TCPsocket server)
{
	
	/* Only server sockets can accept */
	if ( ! server->sflag ) {
		SDLNet_SetError("Only server sockets can accept()");
		return(NULL);
	}
	server->ready = 0;

	/* Accept a new TCP connection on a server socket */
	{
		InetAddress peer;
		TCall peerinfo;
		TCPsocket sock = NULL;
		Boolean mustListen = false;
		OTResult err;
		
		memset(&peerinfo, 0, (sizeof peerinfo ));
		peerinfo.addr.buf = (Uint8 *) &peer;
		peerinfo.addr.maxlen = sizeof(peer);
		
		while( mustListen || !sock )
		{
			// OTListen
			// We do NOT block ---- right thing ? (TODO)
			err = OTListen( server->channel, &peerinfo );

			if( err )
				goto error_return;
			else
			{
				mustListen = false;
				sock = AsyncTCPNewSocket();
				if( ! sock )
					goto error_return;
			}
		}
		if( sock )
		{
			// OTAsyncOpenEndpoint
			server->error = OTAsyncOpenEndpoint( OTCloneConfiguration( server->config ),
				NULL, &(sock->info), (OTNotifyProcPtr)AsyncTCPNotifier, sock );
			AsyncTCPPopEvent( sock );
			while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
			{
				AsyncTCPPopEvent( sock );
			}
			if( ! sock->channel )
			{
				mustListen = false;
				goto error_return;
			}
			
			// OTAccept
			server->completion &= ~(CompleteMask(T_ACCEPTCOMPLETE));
			server->error = OTAccept( server->channel, sock->channel, &peerinfo );
			AsyncTCPPopEvent( server );
			while( !(server->completion & CompleteMask(T_ACCEPTCOMPLETE)))
			{
				AsyncTCPPopEvent( server );
			}
			
			switch( server->error )
			{
				case kOTLookErr:
					switch( OTLook(server->channel ))
					{
						case T_LISTEN:
							mustListen = true;
							break;
						case T_DISCONNECT:
							goto error_return;
					}
					break;
				case 0:
					sock->nextListener = server->nextListener;
					server->nextListener = sock;
					sock->remoteAddress.host = peer.fHost;
					sock->remoteAddress.port = peer.fPort;
					return sock;
					// accept successful
					break;
				default:
					free( sock );
			}
		}
		sock->remoteAddress.host = peer.fHost;
		sock->remoteAddress.port = peer.fPort;
		sock->sflag = 0;
		sock->ready = 0;

		/* The socket is ready */
		return(sock);
	
	// Error; close the socket and return	
	error_return:
		SDLNet_TCP_Close(sock);
		return(NULL);
	}
}
Example #19
0
/* Open a UDP network socket
   If 'port' is non-zero, the UDP socket is bound to a fixed local port.
*/
UDPsocket SDLNet_UDP_Open(Uint16 port)
{
    UDPsocket sock;
    struct sockaddr_in sock_addr;
    socklen_t sock_len;

    /* 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));
    memset(&sock_addr, 0, sizeof(sock_addr));

    /* Open the socket */
    sock->channel = socket(AF_INET, SOCK_DGRAM, 0);
    if ( sock->channel == INVALID_SOCKET )
    {
        SDLNet_SetError("Couldn't create socket");
        goto error_return;
    }

    /* Bind locally, if appropriate */
    sock_addr.sin_family = AF_INET;
    sock_addr.sin_addr.s_addr = INADDR_ANY;
    sock_addr.sin_port = SDLNet_Read16(&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;
    }

    /* Get the bound address and port */
    sock_len = sizeof(sock_addr);
    if ( getsockname(sock->channel, (struct sockaddr *)&sock_addr, &sock_len) < 0 ) {
        SDLNet_SetError("Couldn't get socket address");
        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;

#ifdef SO_BROADCAST
    /* Allow LAN broadcasts with the socket */
    { int yes = 1;
        setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes));
    }
#endif
#ifdef IP_ADD_MEMBERSHIP
    /* Receive LAN multicast packets on 224.0.0.1
       This automatically works on Mac OS X, Linux and BSD, but needs
       this code on Windows.
    */
    /* A good description of multicast can be found here:
        http://www.docs.hp.com/en/B2355-90136/ch05s05.html
    */
    /* FIXME: Add support for joining arbitrary groups to the API */
    {
        struct ip_mreq  g;

        g.imr_multiaddr.s_addr = inet_addr("224.0.0.1");
        g.imr_interface.s_addr = INADDR_ANY;
        setsockopt(sock->channel, IPPROTO_IP, IP_ADD_MEMBERSHIP,
               (char*)&g, sizeof(g));
    }
#endif

    /* The socket is ready */

    return(sock);

error_return:
    SDLNet_UDP_Close(sock);

    return(NULL);
}
Example #20
0
/* Open a TCP network socket
   If 'remote' is nullptr, 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 nullptr if there was an error.
*/
TCPsocket SDLNet_TCP_Open(IPaddress *ip)
{
	TCPsocket sock;
	struct sockaddr_in sock_addr;

	/* Allocate a TCP socket structure */
	sock = (TCPsocket)malloc(sizeof(*sock));
	if ( sock == NULL ) 
	{
		SDLNet_SetError("Out of memory");
		goto error_return;
	}

	/* Open the socket */
	sock->channel = socket(AF_INET, SOCK_STREAM, 0);
	if ( sock->channel == INVALID_SOCKET ) 
	{
		SDLNet_SetError("Couldn't create socket");
		goto error_return;
	}

	/* Connect to remote, or bind locally, as appropriate */
	if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) 
	{

	// #########  Connecting to remote
	
		memset(&sock_addr, 0, sizeof(sock_addr));
		sock_addr.sin_family = AF_INET;
		sock_addr.sin_addr.s_addr = ip->host;
		sock_addr.sin_port = ip->port;

		/* Connect to the remote host */
		if ( connect(sock->channel, (struct sockaddr *)&sock_addr,
				sizeof(sock_addr)) == SOCKET_ERROR ) 
		{
			SDLNet_SetError("Couldn't connect to remote host");
			goto error_return;
		}
		sock->iServerFlag = 0;
	}
	else 
	{

	// ##########  Binding locally

		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 = ip->port;

/*
 * Windows gets bad mojo with SO_REUSEADDR:
 * http://www.devolution.com/pipermail/sdl/2005-September/070491.html
 *   --ryan.
 */
#ifndef WIN32
		/* allow local address reuse */
		{ int yes = 1;
			setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
		}
#endif

		/* 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;
		}
		if ( listen(sock->channel, 5) == SOCKET_ERROR ) {
			SDLNet_SetError("Couldn't listen to local port");
			goto error_return;
		}

		/* Set the socket to non-blocking mode for accept() */
#if defined(__BEOS__) && defined(SO_NONBLOCK)
		/* On BeOS r5 there is O_NONBLOCK but it's for files only */
		{
			long b = 1;
			setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
		}
#elif defined(O_NONBLOCK)
		{
			fcntl(sock->channel, F_SETFL, O_NONBLOCK);
		}
#elif defined(WIN32)
		{
			unsigned long mode = 1;
			ioctlsocket (sock->channel, FIONBIO, &mode);
		}
#elif defined(__OS2__)
		{
			int dontblock = 1;
			ioctl(sock->channel, FIONBIO, &dontblock);
		}
#else
#warning How do we set non-blocking mode on other operating systems?
#endif
		sock->iServerFlag = 1;
	}
	sock->ready = 0;

#ifdef TCP_NODELAY
	/* Set the nodelay TCP option for real-time games */
	{ int yes = 1;
	setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
	}
#endif /* TCP_NODELAY */

	/* Fill in the channel host address */
	sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
	sock->remoteAddress.port = sock_addr.sin_port;

	/* The socket is ready */
	return(sock);

error_return:
	SDLNet_TCP_Close(sock);
	return(NULL);
}
Example #21
0
/* 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);
}
Example #22
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;	
}