Example #1
0
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto, int timeout) {
#if __WINDOWS__
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return R_FALSE;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
	if (s->fd == -1)
		return R_FALSE;

	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
		close (s->fd);
		return R_FALSE;
	}

	sa.sin_addr = *((struct in_addr *)he->h_addr);
	sa.sin_port = htons (atoi (port));
#warning TODO: implement connect timeout on w32
	if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
		close (s->fd);
		return R_FALSE;
	}
	return R_TRUE;
#elif __UNIX__
	if (proto==0) proto= R_SOCKET_PROTO_TCP;
	int gai, ret;
	struct addrinfo hints, *res, *rp;
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host))
			return R_FALSE;
	} else {
		memset (&hints, 0, sizeof (struct addrinfo));
		hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			//eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return R_FALSE;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1)
				continue;
			if (timeout>0)
				fcntl (s->fd, F_SETFL, O_NONBLOCK, 1);
			ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen);
			if (timeout<1 && ret != -1)
				break;
			if (timeout>0) {
				struct timeval tv;
				fd_set fdset;
				FD_ZERO (&fdset);
				FD_SET (s->fd, &fdset);
				tv.tv_sec = timeout;
				tv.tv_usec = 0;
				if (select (s->fd + 1, NULL, &fdset, NULL, &tv) == 1) {
					int so_error;
					socklen_t len = sizeof so_error;
					ret = getsockopt (s->fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
					fcntl (s->fd, F_SETFL, O_NONBLOCK, 0);
				} else {
					close (s->fd);
					return R_FALSE;
				}
			}
			//rp = NULL;
			close (s->fd);
			s->fd = -1;
		}
		freeaddrinfo (res);
		if (rp == NULL) {
			//eprintf ("Could not connect\n");
			return R_FALSE;
		}
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (s->ctx == NULL) {
			r_socket_free (s);
			return R_FALSE;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return R_FALSE;
		}
	}
#endif
	return R_TRUE;
}
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) {
#if __WINDOWS__ && !defined(__CYGWIN__) && !defined(__MINGW64__)
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return false;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
	if (s->fd == -1)
		return false;

	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
		close (s->fd);
		return false;
	}

	sa.sin_addr = *((struct in_addr *)he->h_addr);

	s->port = r_socket_port_by_name (port);
	sa.sin_port = htons (s->port);
#warning TODO: implement connect timeout on w32
	if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
		close (s->fd);
		return false;
	}
	return true;
#elif __UNIX__ || defined(__CYGWIN__)
	int gai, ret;
	struct addrinfo hints, *res, *rp;
	if (!proto) proto = R_SOCKET_PROTO_TCP;
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host))
			return false;
	} else {
		memset (&hints, 0, sizeof (struct addrinfo));
		hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			//eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return false;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			int flag = 1;

			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1)
				continue;

			ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
			if (ret < 0) {
				close (s->fd);
				s->fd = -1;
				continue;
			}

			if (timeout>0) {
				r_socket_block_time (s, 1, timeout);
				//fcntl (s->fd, F_SETFL, O_NONBLOCK, 1);
			}
			ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen);

			if (timeout == 0 && ret == 0) {
				freeaddrinfo (res);
				return true;

			} else if (ret == 0 /* || nonblocking */) {

				struct timeval tv;
				fd_set fdset, errset;
				FD_ZERO (&fdset);
				FD_SET (s->fd, &fdset);
				tv.tv_sec = 1; //timeout;
				tv.tv_usec = 0;

				if (r_socket_is_connected (s)) {
					freeaddrinfo (res);
					return true;
				}
				if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) {
					int so_error;
					socklen_t len = sizeof so_error;
					ret = getsockopt (s->fd, SOL_SOCKET,
						SO_ERROR, &so_error, &len);

					if (ret == 0 && so_error == 0) {
						//fcntl (s->fd, F_SETFL, O_NONBLOCK, 0);
						//r_socket_block_time (s, 0, 0);
						freeaddrinfo (res);
						return true;
					}
				}
			}
			close (s->fd);
			s->fd = -1;
		}
		freeaddrinfo (res);
		if (rp == NULL) {
			eprintf ("Could not resolve address '%s'\n", host);
			return false;
		}
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (s->ctx == NULL) {
			r_socket_free (s);
			return false;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return false;
		}
	}
#endif
	return true;
}
Example #3
0
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto) {
#if __WINDOWS__
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return R_FALSE;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
	if (s->fd == -1)
		return R_FALSE;

	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
		close (s->fd);
		return R_FALSE;
	}

	sa.sin_addr = *((struct in_addr *)he->h_addr);
	sa.sin_port = htons (atoi (port));

	if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
		close (s->fd);
		return R_FALSE;
	}
	return R_TRUE;
#elif __UNIX__
	if (proto==0) proto= R_SOCKET_PROTO_TCP;
	int gai;
	struct addrinfo hints, *res, *rp;
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host))
			return R_FALSE;
	} else {
		memset (&hints, 0, sizeof (struct addrinfo));
		hints.ai_family = AF_UNSPEC;		/* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return R_FALSE;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1)
				continue;
			if (connect (s->fd, rp->ai_addr, rp->ai_addrlen) != -1)
				break;
			close (s->fd);
		}
		if (rp == NULL) {
			eprintf ("Could not connect\n");
			return R_FALSE;
		}
		freeaddrinfo (res);
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (s->ctx == NULL) {
			r_socket_free (s);
			return R_FALSE;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return R_FALSE;
		}
	}
#endif
	return R_TRUE;
}
Example #4
0
R_API bool r_socket_connect(RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) {
#if __WINDOWS__
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	TIMEVAL Timeout;
	Timeout.tv_sec = timeout;
	Timeout.tv_usec = 0;

	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return false;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
#ifdef _MSC_VER
	if (s->fd == INVALID_SOCKET) {
#else
	if (s->fd == -1) {
#endif
		return false;
	}

	unsigned long iMode = 1;
	int iResult = ioctlsocket (s->fd, FIONBIO, &iMode);
	if (iResult != NO_ERROR) {
		eprintf ("ioctlsocket error: %d\n", iResult);
	}
	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
#ifdef _MSC_VER
		closesocket (s->fd);
#else
		close (s->fd);
#endif
		return false;
	}
	sa.sin_addr = *((struct in_addr *)he->h_addr);
	s->port = r_socket_port_by_name (port);
	sa.sin_port = htons (s->port);
	if (!connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
#ifdef _MSC_VER
		closesocket (s->fd);
#else
		close (s->fd);
#endif
		return false;
	}
	iMode = 0;
	iResult = ioctlsocket (s->fd, FIONBIO, &iMode);
	if (iResult != NO_ERROR) {
		eprintf ("ioctlsocket error: %d\n", iResult);
	}
	if (timeout > 0) {
		r_socket_block_time (s, 1, timeout);
	}
	fd_set Write, Err;
	FD_ZERO (&Write);
	FD_ZERO (&Err);
	FD_SET (s->fd, &Write);
	FD_SET (s->fd, &Err);
	select (0, NULL, &Write, &Err, &Timeout);
	if (FD_ISSET (s->fd, &Write)) {
		return true;
	}
	return false;
#elif __UNIX__
	int ret;
	struct addrinfo hints = {0};
	struct addrinfo *res, *rp;
	if (!proto) {
		proto = R_SOCKET_PROTO_TCP;
	}
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host)) {
			return false;
		}
	} else {
		hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		int gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return false;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			int flag = 1;

			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1) {
				perror ("socket");
				continue;
			}
			ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag));
			if (ret < 0) {
				perror ("setsockopt");
				close (s->fd);
				s->fd = -1;
				continue;
			}
			if (timeout > 0) {
				r_socket_block_time (s, 1, timeout);
				//fcntl (s->fd, F_SETFL, O_NONBLOCK, 1);
			}
			ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen);

			if (timeout == 0 && ret == 0) {
				freeaddrinfo (res);
				return true;
			}
			if (ret == 0 /* || nonblocking */) {
				struct timeval tv;
				fd_set fdset, errset;
				FD_ZERO (&fdset);
				FD_SET (s->fd, &fdset);
				tv.tv_sec = 1; //timeout;
				tv.tv_usec = 0;

				if (r_socket_is_connected (s)) {
					freeaddrinfo (res);
					return true;
				}
				if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) {
					int so_error;
					socklen_t len = sizeof so_error;
					ret = getsockopt (s->fd, SOL_SOCKET,
						SO_ERROR, &so_error, &len);

					if (ret == 0 && so_error == 0) {
						//fcntl (s->fd, F_SETFL, O_NONBLOCK, 0);
						//r_socket_block_time (s, 0, 0);
						freeaddrinfo (res);
						return true;
					}
				}
			}
			close (s->fd);
			s->fd = -1;
		}
		freeaddrinfo (res);
		if (!rp) {
			eprintf ("Could not resolve address '%s' or failed to connect\n", host);
			return false;
		}
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (!s->ctx) {
			r_socket_free (s);
			return false;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return false;
		}
	}
#endif
	return true;
}

/* close the file descriptor associated with the RSocket s */
R_API int r_socket_close_fd(RSocket *s) {
#ifdef _MSC_VER
	return s->fd != INVALID_SOCKET ? closesocket (s->fd) : false;
#else
	return s->fd != -1 ? close (s->fd) : false;
#endif
}

/* shutdown the socket and close the file descriptor */
R_API int r_socket_close(RSocket *s) {
	int ret = false;
	if (!s) {
		return false;
	}
	if (s->fd != -1) {
#if __UNIX__
		shutdown (s->fd, SHUT_RDWR);
#endif
#if __WINDOWS__
		// https://msdn.microsoft.com/en-us/library/windows/desktop/ms740481(v=vs.85).aspx
		shutdown (s->fd, SD_SEND);
		if (r_socket_ready (s, 0, 250)) {
			do {
				char buf = 0;
				ret = recv (s->fd, &buf, 1, 0);
			} while (ret != 0 && ret != SOCKET_ERROR);
		}
		ret = closesocket (s->fd);
#else
		ret = close (s->fd);
#endif
	}
#if HAVE_LIB_SSL
	if (s->is_ssl && s->sfd) {
		SSL_free (s->sfd);
		s->sfd = NULL;
	}
#endif
	return ret;
}