⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connect.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Sockets-o-matic *//* $Id: connect.c,v 1.114.2.6 2005/05/01 21:18:43 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <string.h>#include <sys/types.h>#ifdef HAVE_NETINET_IN_H#include <netinet/in.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_GETIFADDRS#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_NET_IF_H#include <net/if.h>#endif#ifdef HAVE_IFADDRS_H#include <ifaddrs.h>		/* getifaddrs() */#endif#endif				/* HAVE_GETIFADDRS */#include "elinks.h"#include "config/options.h"#include "lowlevel/connect.h"#include "lowlevel/dns.h"#include "lowlevel/select.h"#include "osdep/osdep.h"#include "osdep/getifaddrs.h"#include "protocol/protocol.h"#include "protocol/uri.h"#include "sched/connection.h"#include "ssl/connect.h"#include "util/error.h"#include "util/memory.h"#include "util/string.h"/* To enable logging of tranfers, for debugging purposes. */#if 0#define DEBUG_TRANSFER_LOGFILE "/tmp/log"static voiddebug_transfer_log(unsigned char *data, int len){	int fd = open(DEBUG_TRANSFER_LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0622);	if (fd == -1) return;	set_bin(fd);	write(fd, data, len < 0 ? strlen(data) : len);	close(fd);}#undef DEBUG_TRANSFER_LOGFILE#else#define debug_transfer_log(data, len)#endifvoid dns_found(/* struct connection */ void *, int);static void connected(/* struct connection */ void *);voidclose_socket(struct connection *conn, struct connection_socket *socket){	if (socket->fd == -1) return;#ifdef CONFIG_SSL	if (conn && socket->ssl) ssl_close(conn, socket);#endif	close(socket->fd);	clear_handlers(socket->fd);	socket->fd = -1;}voiddns_exception(void *data){	struct connection *conn = data;	set_connection_state(conn, S_EXCEPT);	close_socket(NULL, conn->conn_info->socket);	dns_found(conn, 0);}static voidexception(void *data){	retry_conn_with_state((struct connection *) data, S_EXCEPT);}struct conn_info *init_connection_info(struct uri *uri, struct connection_socket *socket,		     void (*done)(struct connection *)){	struct conn_info *conn_info = mem_calloc(1, sizeof(*conn_info));	if (!conn_info) return NULL;	conn_info->done = done;	conn_info->socket = socket;	conn_info->port = get_uri_port(uri);	conn_info->triedno = -1;	conn_info->addr = NULL;	return conn_info;}voiddone_connection_info(struct connection *conn){	struct conn_info *conn_info = conn->conn_info;	conn->conn_info = NULL;	if (conn_info->done) conn_info->done(conn);	mem_free_if(conn_info->addr);	mem_free(conn_info);}voidmake_connection(struct connection *conn, struct connection_socket *socket,		void (*done)(struct connection *)){	unsigned char *host = get_uri_string(conn->uri, URI_DNS_HOST);	struct conn_info *conn_info;	int async;	if (!host) {		retry_conn_with_state(conn, S_OUT_OF_MEM);		return;	}	conn_info = init_connection_info(conn->uri, socket, done);	if (!conn_info) {		mem_free(host);		retry_conn_with_state(conn, S_OUT_OF_MEM);		return;	}	conn->conn_info = conn_info;	debug_transfer_log("\nCONNECTION: ", -1);	debug_transfer_log(host, -1);	debug_transfer_log("\n", -1);	if (conn->cache_mode >= CACHE_MODE_FORCE_RELOAD)		async = find_host_no_cache(host, &conn_info->addr, &conn_info->addrno,					   &conn->dnsquery, dns_found, conn);	else		async = find_host(host, &conn_info->addr, &conn_info->addrno,				  &conn->dnsquery, dns_found, conn);	mem_free(host);	if (async) set_connection_state(conn, S_DNS);}/* Returns negative if error, otherwise pasv socket's fd. */intget_pasv_socket(struct connection *conn, int ctrl_sock, unsigned char *port){	struct sockaddr_in sa, sb;	int sock, len;	memset(&sa, 0, sizeof(sa));	memset(&sb, 0, sizeof(sb));	/* Get our endpoint of the control socket */	len = sizeof(sa);	if (getsockname(ctrl_sock, (struct sockaddr *) &sa, &len)) {sock_error:		retry_conn_with_state(conn, -errno);		return -1;	}	/* Get a passive socket */	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	if (sock < 0)		goto sock_error;	/* Set it non-blocking */	if (set_nonblocking_fd(sock) < 0)		goto sock_error;	/* Bind it to some port */	copy_struct(&sb, &sa);	sb.sin_port = 0;	if (bind(sock, (struct sockaddr *) &sb, sizeof(sb)))		goto sock_error;	/* Get our endpoint of the passive socket and save it to port */	len = sizeof(sa);	if (getsockname(sock, (struct sockaddr *) &sa, &len))		goto sock_error;	memcpy(port, &sa.sin_addr.s_addr, 4);	memcpy(port + 4, &sa.sin_port, 2);	/* Go listen */	if (listen(sock, 1))		goto sock_error;	set_ip_tos_throughput(sock);	return sock;}#ifdef CONFIG_IPV6intget_pasv6_socket(struct connection *conn, int ctrl_sock,		 struct sockaddr_storage *s6){	int sock;	struct sockaddr_in6 s0;	int len = sizeof(s0);	memset(&s0, 0, sizeof(s0));	memset(s6, 0, sizeof(*s6));	/* Get our endpoint of the control socket */	if (getsockname(ctrl_sock, (struct sockaddr *) s6, &len)) {sock_error:		retry_conn_with_state(conn, -errno);		return -1;	}	/* Get a passive socket */	sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);	if (sock < 0)		goto sock_error;	/* Set it non-blocking */	if (set_nonblocking_fd(sock) < 0)		goto sock_error;	/* Bind it to some port */	memcpy(&s0, s6, sizeof(s0));	s0.sin6_port = 0;	if (bind(sock, (struct sockaddr *) &s0, sizeof(s0)))		goto sock_error;	/* Get our endpoint of the passive socket and save it to port */	len = sizeof(s0);	if (getsockname(sock, (struct sockaddr *) s6, &len))		goto sock_error;	/* Go listen */	if (listen(sock, 1))		goto sock_error;	set_ip_tos_throughput(sock);	return sock;}static inline intcheck_if_local_address6(struct sockaddr_in6 *addr){	struct ifaddrs *ifaddrs;	int local = IN6_IS_ADDR_LOOPBACK(&(addr->sin6_addr));	if (!local && !getifaddrs(&ifaddrs)) {		struct ifaddrs *ifa;		for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {			if (!ifa->ifa_addr)				continue;			if (ifa->ifa_addr->sa_family == AF_INET6			    && !memcmp(&addr->sin6_addr.s6_addr,			    &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr.s6_addr,			    sizeof(addr->sin6_addr.s6_addr))) {				local = 1;				break;			}			if (ifa->ifa_addr->sa_family == AF_INET			    && !memcmp(&((struct sockaddr_in *) &addr)->sin_addr.s_addr,				&((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,				sizeof(((struct sockaddr_in *) &addr)->sin_addr.s_addr))) {					local = 1;					break;			}		}		freeifaddrs(ifaddrs);	}	return local;}#endif /* CONFIG_IPV6 */static inline intcheck_if_local_address4(struct sockaddr_in *addr){	struct ifaddrs *ifaddrs;	int local = (ntohl(addr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;	if (!local && !getifaddrs(&ifaddrs)) {		struct ifaddrs *ifa;		for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {			if (!ifa->ifa_addr)				continue;			if (ifa->ifa_addr->sa_family != AF_INET) continue;			if (!memcmp(&addr->sin_addr.s_addr,				&((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,				sizeof(addr->sin_addr.s_addr))) {					local = 1;					break;			}		}		freeifaddrs(ifaddrs);	}	return local;}voiddns_found(void *data, int state){	int sock = -1;	struct connection *conn = (struct connection *) data;	struct conn_info *conn_info = conn->conn_info;	int i;	int trno = conn_info->triedno;	int only_local = get_cmd_opt_bool("localhost");	int saved_errno = 0;	int at_least_one_remote_ip = 0;	/* We tried something but we failed in such a way that we would rather	 * prefer the connection to retain the information about previous	 * failures.  That is, we i.e. decided we are forbidden to even think	 * about such a connection attempt.	 * XXX: Unify with @local_only handling? --pasky */	int silent_fail = 0;	if (state < 0) {		abort_conn_with_state(conn, S_NO_DNS);		return;	}	/* Clear handlers, the connection to the previous RR really timed	 * out and doesn't interest us anymore. */	if (conn_info->socket && conn_info->socket->fd >= 0)		clear_handlers(conn_info->socket->fd);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -