コード例 #1
0
ファイル: ipv6win.c プロジェクト: jocelyn/EiffelStudio_old
void en_socket_datagram_connect (EIF_INTEGER fd, EIF_INTEGER fd1, EIF_POINTER sockaddr) {

	SOCKETADDRESS* him;
	int family;
	EIF_INTEGER fdc = -1;
	int ipv6_supported;
	int connect_res;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	him = (SOCKETADDRESS*) sockaddr;
	family = him->him.sa_family; 

	if (family == AF_INET6 && !ipv6_supported) {
		eraise ("Protocol family not supported", EN_PROG);
		return;
	}
    	
	fdc = (family == AF_INET? fd: fd1);
	connect_res = connect(fdc, (struct sockaddr *)him, SOCKETADDRESS_LEN(him));
	if ( connect_res == -1) {
    		eraise("Unable to establish connection", EN_PROG);
	}
}
コード例 #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;
}
コード例 #3
0
ファイル: ipv6win.c プロジェクト: jocelyn/EiffelStudio_old
EIF_INTEGER en_socket_datagram_send_to (EIF_INTEGER fd, EIF_INTEGER fd1, EIF_POINTER buf, EIF_INTEGER len, EIF_INTEGER flags, SOCKETADDRESS *him) {

	int result = -1;
	int fduse = -1;

	if (him->him.sa_family == AF_INET) {
		fduse = fd;
	} else if (him->him.sa_family == AF_INET6) {
		fduse = fd1;
	}
	if (fduse != -1) {
		result = sendto ((SOCKET) fduse, (char *) buf, (int) len, (int) flags, (struct sockaddr *) him, SOCKETADDRESS_LEN(him));
		eif_net_check (result);
	}
	
	return (EIF_INTEGER) result;
}
コード例 #4
0
ファイル: ipv6win.c プロジェクト: jocelyn/EiffelStudio_old
void en_socket_stream_bind (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1, EIF_INTEGER *a_local_port, EIF_POINTER sockaddr) {

	SOCKETADDRESS* him;
	int family;
	SOCKET fd, fd1;
	int ipv6_supported;
	int localport;
	int rv;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	him = (SOCKETADDRESS*) sockaddr;
	family = him->him.sa_family; 
	localport = ntohs (GET_PORT (him));

	fd = (SOCKET) *a_fd;
	fd1 = (SOCKET) *a_fd1;
	if (ipv6_supported) {
		struct ipv6bind v6bind;
		v6bind.addr = him;
		v6bind.ipv4_fd = fd;
		v6bind.ipv6_fd = fd1;
		rv = net_bindV6(&v6bind);
		if (rv != -1) {
				/* check if the fds have changed */
			if (v6bind.ipv4_fd != fd) {
				fd = v6bind.ipv4_fd;
				if (fd == INVALID_SOCKET) {
						/* socket is closed. */
					*a_fd = -1;
				} else {
						/* socket was re-created */
					*a_fd = (EIF_INTEGER) fd;
				}
			}
			if (v6bind.ipv6_fd != fd1) {
				fd1 = v6bind.ipv6_fd;
				if (fd1 == INVALID_SOCKET) {
						/* socket is closed. */
					*a_fd1 = -1;
				} else {
						/* socket was re-created */
					*a_fd1 = (EIF_INTEGER) fd1;
				}
			}
		}
	} else {
		rv = net_bind(fd, (struct sockaddr *)him, SOCKETADDRESS_LEN(him));
	}

	if (rv == -1) {	
		eraise("bind error", EN_PROG);
		return;
	}

		/* intialize the local port */
	if (localport == 0) {
			/* Now that we're a bound socket, let's extract the port number
			 * that the system chose for us and store it in the Socket object. */
		int len = SOCKETADDRESS_LEN(him);
		u_short port;
		fd = him->him.sa_family == AF_INET? fd: fd1;

		if ((rv=getsockname(fd, (struct sockaddr *)him, &len)) == -1) {
			eif_net_check(rv);
			return;
		}
		port = ntohs (GET_PORT (him));
		*a_local_port = port;
	} else {
		*a_local_port = localport;
	}
}
コード例 #5
0
ファイル: ipv6win.c プロジェクト: jocelyn/EiffelStudio_old
void en_socket_stream_connect (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1, EIF_INTEGER *a_local_port, EIF_POINTER sockaddr, EIF_INTEGER timeout, EIF_BOOLEAN is_blocking) {

	SOCKETADDRESS* him;
	int family;
	SOCKET fd, fd1 = INVALID_SOCKET;
	int ipv6_supported;
	int connect_res;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	fd = (SOCKET) *a_fd;
	if (ipv6_supported) {
		fd1 = *a_fd1;
	}

	him = (SOCKETADDRESS*) sockaddr;

	family = him->him.sa_family; 
	if (family == AF_INET6) {
		if (!ipv6_supported) {
			eraise ("Protocol family not supported", EN_PROG);
			return;
		} else {
			if (fd1 == -1) {
				eraise ("Destination unreachable", EN_PROG);
				return;
			}
				/* close the v4 socket, and set fd to be the v6 socket */
			*a_fd = (EIF_INTEGER) fd1;
			*a_fd1 = -1;
			net_socket_close(fd); 
			fd = fd1;
		}
	} else {
		if (fd1 != -1) {
				/* close the v6 socket */
			*a_fd1 = -1;
			net_socket_close(fd1); 
		}
		if (fd == INVALID_SOCKET) {
			eraise ("Destination unreachable", EN_PROG);
			return;
		} 
	}

	if (timeout <= 0) {
		connect_res = connect(fd, (struct sockaddr *) him, SOCKETADDRESS_LEN(him));
		if (connect_res == SOCKET_ERROR) {
			connect_res = WSAGetLastError();
			if ((connect_res == WSAEWOULDBLOCK) || (connect_res == WSAEINPROGRESS)) {
				connect_res = 0;
				errno = 0;
			}
		}
	} else {
		u_long optval;
		int optlen = sizeof(int);

			/* make socket non-blocking */
		if (is_blocking) {
			optval = 1;
			ioctlsocket( fd, FIONBIO, &optval );
		}

			/* initiate the connect */
		connect_res = connect(fd, (struct sockaddr *) him, SOCKETADDRESS_LEN(him));
		if (connect_res == SOCKET_ERROR) {
			if (WSAGetLastError() == WSAEWOULDBLOCK) {
				fd_set wr, ex;
				struct timeval t;

				FD_ZERO(&wr);
				FD_ZERO(&ex);
				FD_SET(fd, &wr);
				FD_SET(fd, &ex);
				t.tv_sec = timeout / 1000;
				t.tv_usec = (timeout % 1000) * 1000;

					/* Wait for timout, connection established or
					 * connection failed. */
				connect_res = select((int) fd+1, 0, &wr, &ex, &t);

				/* Timeout before connection is established/failed so
				 * we throw exception and shutdown input/output to prevent
				 * socket from being used.
				 * The socket should be closed immediately by the caller. */
				if (connect_res == 0) {
					shutdown( fd, SD_BOTH );
					if (is_blocking) {
							/* make socket blocking again - just in case */
						optval = 0;
						ioctlsocket( fd, FIONBIO, &optval );
					}
					eraise("connect timed out", EN_PROG);
					return;
				}

					/* We must now determine if the connection has been established
					 * or if it has failed. The logic here is designed to work around
					 * bug on Windows NT whereby using getsockopt to obtain the 
					 * last error (SO_ERROR) indicates there is no error. The workaround
					 * on NT is to allow winsock to be scheduled and this is done by
					 * yielding and retrying. As yielding is problematic in heavy
					 * load conditions we attempt up to 3 times to get the error reason. */
				if (!FD_ISSET(fd, &ex)) {
					connect_res = 0;
				} else {
					int retry;
					for (retry=0; retry<3; retry++) {
						net_get_sock_opt(fd, SOL_SOCKET, SO_ERROR, (char*)&connect_res, &optlen);
						if (connect_res) {
							break;
						}
						Sleep(0);
					}

					if (connect_res == 0) {
						eraise("Unable to establish connection", EN_PROG);
						return;
					}
				}
			}
		}

		if (is_blocking) {
				/* make socket blocking again */
			optval = 0;
			ioctlsocket(fd, FIONBIO, &optval);
		}
	}

	if (connect_res) {
		if (connect_res == WSAEADDRNOTAVAIL) {
			eraise("Address is invalid on local machine, or port is not valid on remote machine", EN_PROG);
		} else {
			eraise("Unable to establish connection", EN_PROG);
		}
		return;
	}

	*a_fd = (EIF_INTEGER) fd;

		/* we need to initialize the local port field if bind was called
		 * previously to the connect (by the client) then localport field
		 * will already be initialized. */
	if (*a_local_port == 0) {
			/* Now that we're a connected socket, let's extract the port number
			 * that the system chose for us and store it in the Socket object. */
		u_short port;
		int len = SOCKETADDRESS_LEN(him);
		if (getsockname(fd, (struct sockaddr *)him, &len) == -1) {
			if (WSAGetLastError() == WSAENOTSOCK) {
				eraise("Socket closed", EN_PROG);
			} else {
				eraise("getsockname failed", EN_PROG);
			}
			return;
		}
		port = ntohs (GET_PORT(him));
		*a_local_port = port;
	}
}
コード例 #6
0
ファイル: ipv6win.c プロジェクト: jocelyn/EiffelStudio_old
static int net_bindV6(struct ipv6bind* b) {
	SOCKET fd=INVALID_SOCKET, ofd=INVALID_SOCKET, rv;
	int len;
		/* need to defer close until new sockets created */
	SOCKET close_fd=INVALID_SOCKET, close_ofd=INVALID_SOCKET; 
	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;

		/* We only bind to only IPv4 or IPv6 if the listen address is different from the ANY IP address or 
		 * the LOOPBACK IP address. */
	if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY) && (b->addr->him4.sin_addr.s_addr != htonl (INADDR_LOOPBACK))) {
			/* 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 = INVALID_SOCKET;
		return 0;
	}
	if (family == AF_INET6 && (!NET_IN6ADDR_ISANY(&b->addr->him6)) && !NET_IN6ADDR_ISLOOPBACK(&b->addr->him6)) {
			/* 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 = INVALID_SOCKET;
		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 = ntohs (GET_PORT (b->addr));
		if (b->addr->him4.sin_addr.s_addr == htonl (INADDR_LOOPBACK)) {
			NET_IN6ADDR_SETLOOPBACK (&oaddr.him6);
		} else {
			NET_IN6ADDR_SETANY (&oaddr.him6);
		}
		oaddr.him6.sin6_port = port;
	} else {
		ofamily = AF_INET;
		ofd = b->ipv4_fd;
		fd = b->ipv6_fd;
		port = ntohs (GET_PORT (b->addr));
		oaddr.him4.sin_family = AF_INET;
		oaddr.him4.sin_port = port;
		if (NET_IN6ADDR_ISLOOPBACK(&b->addr->him6)) {
			oaddr.him4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
		} else {
			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 = ntohs (GET_PORT (b->addr));
	SET_PORT (&oaddr, htons (bound_port));
	len = SOCKETADDRESS_LEN (&oaddr);
	if ((rv=net_bind (ofd, (struct sockaddr *) &oaddr, len)) == 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 = INVALID_SOCKET;
			close_ofd = ofd; ofd = INVALID_SOCKET;
			b->ipv4_fd = INVALID_SOCKET;
			b->ipv6_fd = INVALID_SOCKET;

				/* create two new sockets */
			fd = check_socket_bounds (socket (family, sotype, 0));
			if (fd == INVALID_SOCKET) {
				CLOSE_SOCKETS_AND_RETURN;
			}
			ofd = check_socket_bounds (socket (ofamily, sotype, 0));
			if (ofd == INVALID_SOCKET) {
				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 = INVALID_SOCKET;

				/* bind new port on second socket */
			len = SOCKETADDRESS_LEN(&oaddr);
			if (getsockname(ofd, (struct sockaddr *)&oaddr, &len) == -1) {
				CLOSE_SOCKETS_AND_RETURN;
			}
			bound_port = ntohs (GET_PORT (&oaddr));
			SET_PORT (b->addr, htons (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;
}