コード例 #1
0
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;
}
コード例 #2
0
R_API int r_socket_listen (RSocket *s, const char *port, const char *certfile) {
#if __UNIX__ || defined(__CYGWIN__)
	int optval = 1;
	int ret;
	struct linger linger = { 0 };
#endif
	if (r_sandbox_enable (0))
		return false;
#if __WINDOWS__ && !defined(__CYGWIN__) && !defined(__MINGW64__)
	WSADATA wsadata;
	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return false;
	}
#endif
	if ((s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
		return false;
#if __UNIX__ || defined(__CYGWIN__)
	linger.l_onoff = 1;
	linger.l_linger = 1;
	ret = setsockopt (s->fd, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof (linger));
	if (ret < 0)
		return false;
	{ // fix close after write bug //
	int x = 1500; // FORCE MTU
	ret = setsockopt (s->fd, SOL_SOCKET, SO_SNDBUF, (void*)&x, sizeof (int));
	if (ret < 0)
		return false;
	}
	ret = setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof optval);
	if (ret < 0)
		return false;
#endif
	memset (&s->sa, 0, sizeof (s->sa));
	s->sa.sin_family = AF_INET;
	s->sa.sin_addr.s_addr = htonl (s->local? INADDR_LOOPBACK: INADDR_ANY);
	s->port = r_socket_port_by_name (port);
	if (s->port <1)
		return false;
	s->sa.sin_port = htons (s->port); // TODO honor etc/services

	if (bind (s->fd, (struct sockaddr *)&s->sa, sizeof(s->sa)) < 0) {
		r_sys_perror ("bind");
		close (s->fd);
		return false;
	}
#if __UNIX__ || defined(__CYGWIN__)
	signal (SIGPIPE, SIG_IGN);
#endif
	if (listen (s->fd, 32) < 0) {
		close (s->fd);
		return false;
	}
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_method ());
		if (s->ctx == NULL) {
			r_socket_free (s);
			return false;
		}
		if (!SSL_CTX_use_certificate_chain_file (s->ctx, certfile)) {
			r_socket_free (s);
			return false;
		}
		if (!SSL_CTX_use_PrivateKey_file (s->ctx, certfile, SSL_FILETYPE_PEM)) {
			r_socket_free (s);
			return false;
		}
		SSL_CTX_set_verify_depth (s->ctx, 1);
	}
#endif
	return true;
}
コード例 #3
0
ファイル: socket.c プロジェクト: aronsky/radare2
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;
}