Esempio n. 1
0
/* extern */ Boolean
_CFServerStart(_CFServerRef server, CFStringRef name, CFStringRef type, UInt32 port) {
	
	Server* s = (Server*)server;

	CFDataRef address = NULL;
	
	do {
        unsigned i;
		CFRunLoopRef rl = CFRunLoopGetCurrent();
        CFAllocatorRef alloc = CFGetAllocator(server);
		
        struct sockaddr_in addr4;
        struct sockaddr_in6 addr6;
				
		// Make sure the port is valid (0 - 65535).
		if ((port & 0xFFFF0000U) != 0)
			break;
		
		// NULL means to use the machine name.
		if (name == NULL)
			name = _kCFServerEmptyString;
		
		for (i = 0; i < (sizeof(s->_sockets) / sizeof(s->_sockets[0])); i++) {
		
			// Create the run loop source for putting on the run loop.
			CFRunLoopSourceRef src = CFSocketCreateRunLoopSource(alloc, s->_sockets[i], 0);
			if (src == NULL)
				break;
				
			// Add the run loop source to the current run loop and default mode.
			CFRunLoopAddSource(rl, src, kCFRunLoopCommonModes);
			CFRelease(src);
		}

		memset(&addr4, 0, sizeof(addr4));
		
		// Put the local port and address into the native address.
#if !defined(__WIN32__)
        addr4.sin_len = sizeof(addr4);
#endif
		addr4.sin_family = AF_INET;
		addr4.sin_port = htons((UInt16)port);
		addr4.sin_addr.s_addr = htonl(INADDR_ANY);
		
		// Wrap the native address structure for CFSocketCreate.
		address = CFDataCreateWithBytesNoCopy(alloc, (const UInt8*)&addr4, sizeof(addr4), kCFAllocatorNull);
		
		// If it failed to create the address data, bail.
		if (address == NULL)
			break;
			
		// Set the local binding which causes the socket to start listening.
		if (CFSocketSetAddress(s->_sockets[0], address) != kCFSocketSuccess)
			break;
		
		CFRelease(address);
		
		address = CFSocketCopyAddress(s->_sockets[0]);
		memcpy(&addr4, CFDataGetBytePtr(address), CFDataGetLength(address));
            
		port = ntohs(addr4.sin_port);

		CFRelease(address);

		memset(&addr6, 0, sizeof(addr6));

        // Put the local port and address into the native address.
        addr6.sin6_family = AF_INET6;
#ifndef __WIN32__
        addr6.sin6_port = htons((UInt16)port);
        addr6.sin6_len = sizeof(addr6);
        memcpy(&(addr6.sin6_addr), &in6addr_any, sizeof(addr6.sin6_addr));
#else
#ifndef __MINGW32__
        // real MS headers have this
        IN6ADDR_SETANY(addr6);
        addr6.sin6_port = htons((UInt16)port);
#else
        addr6.sin6_port = htons((UInt16)port);
        // mingw's w32 headers have this INIT macro instead, for some odd reason
        struct sockaddr_in6 in6addr_any = IN6ADDR_ANY_INIT;
        memcpy(&(addr6.sin6_addr), &in6addr_any, sizeof(addr6.sin6_addr));
#endif
#endif
        
		// Wrap the native address structure for CFSocketCreate.
		address = CFDataCreateWithBytesNoCopy(alloc, (const UInt8*)&addr6, sizeof(addr6), kCFAllocatorNull);
			
		// Set the local binding which causes the socket to start listening.
		if (CFSocketSetAddress(s->_sockets[1], address) != kCFSocketSuccess)
			break;
		
		// Save the name, service type and port.
        s->_name = CFRetain(name);
		s->_type = type ? CFRetain(type) : NULL;
		s->_port = port;

#if defined(__MACH__)
        // Attempt to register the service on the network. 
		if (type && !_ServerCreateAndRegisterNetService(s))
            break;
#endif

        // Release this since it's not needed any longer. 
		CFRelease(address);
	
		return TRUE;
        
	} while (0);
	
	// Handle the error cleanup.
	
	// Release the address data if it was created.
	if (address)
		CFRelease(address);

	// Kill the socket if it was created.
	_ServerReleaseSocket(s);

	return FALSE;
}
Esempio n. 2
0
JNIEXPORT int JNICALL
NET_BindV6(struct ipv6bind* b) {
    int fd=-1, ofd=-1, rv, len;
    /* need to defer close until new sockets created */
    int close_fd=-1, close_ofd=-1; 
    SOCKETADDRESS oaddr; /* other address to bind */
    int family = b->addr->him.sa_family;
    int ofamily;
    u_short port; /* requested port parameter */
    u_short bound_port;

    if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY)) {
	/* bind to v4 only */
	int ret;
	ret = NET_Bind (b->ipv4_fd, (struct sockaddr *)b->addr, 
				sizeof (struct sockaddr_in));
        if (ret == SOCKET_ERROR) {
	    CLOSE_SOCKETS_AND_RETURN;
        }
	closesocket (b->ipv6_fd);
	b->ipv6_fd = -1;
	return 0;
    }
    if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->him6.sin6_addr))) {
	/* bind to v6 only */
	int ret;
	ret = NET_Bind (b->ipv6_fd, (struct sockaddr *)b->addr, 
				sizeof (struct SOCKADDR_IN6));
        if (ret == SOCKET_ERROR) {
	    CLOSE_SOCKETS_AND_RETURN;
        }
	closesocket (b->ipv4_fd);
	b->ipv4_fd = -1;
	return 0;
    }

    /* We need to bind on both stacks, with the same port number */

    memset (&oaddr, 0, sizeof(oaddr));
    if (family == AF_INET) {
	ofamily = AF_INET6;
	fd = b->ipv4_fd;
	ofd = b->ipv6_fd;
	port = (u_short)GET_PORT (b->addr);
	IN6ADDR_SETANY (&oaddr.him6);
	oaddr.him6.sin6_port = port;
    } else {
	ofamily = AF_INET;
	ofd = b->ipv4_fd;
	fd = b->ipv6_fd;
	port = (u_short)GET_PORT (b->addr);
	oaddr.him4.sin_family = AF_INET;
	oaddr.him4.sin_port = port;
	oaddr.him4.sin_addr.s_addr = INADDR_ANY;
    }

    rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr));
    if (rv == SOCKET_ERROR) {
    	CLOSE_SOCKETS_AND_RETURN;
    }

    /* get the port and set it in the other address */
    len = SOCKETADDRESS_LEN(b->addr);
    if (getsockname(fd, (struct sockaddr *)b->addr, &len) == -1) {
    	CLOSE_SOCKETS_AND_RETURN;
    }
    bound_port = GET_PORT (b->addr);
    SET_PORT (&oaddr, bound_port);
    if ((rv=NET_Bind (ofd, (struct sockaddr *) &oaddr, 
				SOCKETADDRESS_LEN (&oaddr))) == SOCKET_ERROR) {
	int retries;
	int sotype, arglen=sizeof(sotype);

 	/* no retries unless, the request was for any free port */

        if (port != 0) {
    	    CLOSE_SOCKETS_AND_RETURN;
        }

	getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen);

#define SOCK_RETRIES 50
	/* 50 is an arbitrary limit, just to ensure that this
	 * cannot be an endless loop. Would expect socket creation to 
	 * succeed sooner.
	 */
    	for (retries = 0; retries < SOCK_RETRIES; retries ++) {
	    int len;
	    close_fd = fd; fd = -1;
	    close_ofd = ofd; ofd = -1;
	    b->ipv4_fd = SOCKET_ERROR;
	    b->ipv6_fd = SOCKET_ERROR;

	    /* create two new sockets */
	    fd = socket (family, sotype, 0);
	    if (fd == SOCKET_ERROR) {
    	        CLOSE_SOCKETS_AND_RETURN;
	    }
	    ofd = socket (ofamily, sotype, 0);
	    if (ofd == SOCKET_ERROR) {
    	        CLOSE_SOCKETS_AND_RETURN;
	    }

	    /* bind random port on first socket */
	    SET_PORT (&oaddr, 0);
    	    rv = NET_Bind (ofd, (struct sockaddr *)&oaddr, SOCKETADDRESS_LEN(&oaddr));
    	    if (rv == SOCKET_ERROR) {
    	        CLOSE_SOCKETS_AND_RETURN;
	    }
	    /* close the original pair of sockets before continuing */
	    closesocket (close_fd); 
	    closesocket (close_ofd); 
	    close_fd = close_ofd = -1;

	    /* bind new port on second socket */
	    len = SOCKETADDRESS_LEN(&oaddr);
            if (getsockname(ofd, (struct sockaddr *)&oaddr, &len) == -1) {
    	        CLOSE_SOCKETS_AND_RETURN;
            }
    	    bound_port = GET_PORT (&oaddr);
	    SET_PORT (b->addr, bound_port);
    	    rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr));

    	    if (rv != SOCKET_ERROR) {
		if (family == AF_INET) {
	    	    b->ipv4_fd = fd;
	    	    b->ipv6_fd = ofd;
		} else {
	    	    b->ipv4_fd = ofd;
	    	    b->ipv6_fd = fd;
		}
		return 0;
	    }
	}
	CLOSE_SOCKETS_AND_RETURN;
    }
    return 0;
}