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

📄 proxy.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Network proxy abstraction in PuTTY * * A proxy layer, if necessary, wedges itself between the network * code and the higher level backend. */#include <assert.h>#include <ctype.h>#include <string.h>#define DEFINE_PLUG_METHOD_MACROS#include "putty.h"#include "network.h"#include "proxy.h"#define do_proxy_dns(cfg) \    (cfg->proxy_dns == FORCE_ON || \	 (cfg->proxy_dns == AUTO && \              cfg->proxy_type != PROXY_SOCKS4 && \              cfg->proxy_type != PROXY_SOCKS5))/* * Call this when proxy negotiation is complete, so that this * socket can begin working normally. */void proxy_activate (Proxy_Socket p){    void *data;    int len;    long output_before, output_after;        p->state = PROXY_STATE_ACTIVE;    /* we want to ignore new receive events until we have sent     * all of our buffered receive data.     */    sk_set_frozen(p->sub_socket, 1);    /* how many bytes of output have we buffered? */    output_before = bufchain_size(&p->pending_oob_output_data) +	bufchain_size(&p->pending_output_data);    /* and keep track of how many bytes do not get sent. */    output_after = 0;        /* send buffered OOB writes */    while (bufchain_size(&p->pending_oob_output_data) > 0) {	bufchain_prefix(&p->pending_oob_output_data, &data, &len);	output_after += sk_write_oob(p->sub_socket, data, len);	bufchain_consume(&p->pending_oob_output_data, len);    }    /* send buffered normal writes */    while (bufchain_size(&p->pending_output_data) > 0) {	bufchain_prefix(&p->pending_output_data, &data, &len);	output_after += sk_write(p->sub_socket, data, len);	bufchain_consume(&p->pending_output_data, len);    }    /* if we managed to send any data, let the higher levels know. */    if (output_after < output_before)	plug_sent(p->plug, output_after);    /* if we were asked to flush the output during     * the proxy negotiation process, do so now.     */    if (p->pending_flush) sk_flush(p->sub_socket);    /* if the backend wanted the socket unfrozen, try to unfreeze.     * our set_frozen handler will flush buffered receive data before     * unfreezing the actual underlying socket.     */    if (!p->freeze)	sk_set_frozen((Socket)p, 0);}/* basic proxy socket functions */static Plug sk_proxy_plug (Socket s, Plug p){    Proxy_Socket ps = (Proxy_Socket) s;    Plug ret = ps->plug;    if (p)	ps->plug = p;    return ret;}static void sk_proxy_close (Socket s){    Proxy_Socket ps = (Proxy_Socket) s;    sk_close(ps->sub_socket);    sk_addr_free(ps->remote_addr);    sfree(ps);}static int sk_proxy_write (Socket s, const char *data, int len){    Proxy_Socket ps = (Proxy_Socket) s;    if (ps->state != PROXY_STATE_ACTIVE) {	bufchain_add(&ps->pending_output_data, data, len);	return bufchain_size(&ps->pending_output_data);    }    return sk_write(ps->sub_socket, data, len);}static int sk_proxy_write_oob (Socket s, const char *data, int len){    Proxy_Socket ps = (Proxy_Socket) s;    if (ps->state != PROXY_STATE_ACTIVE) {	bufchain_clear(&ps->pending_output_data);	bufchain_clear(&ps->pending_oob_output_data);	bufchain_add(&ps->pending_oob_output_data, data, len);	return len;    }    return sk_write_oob(ps->sub_socket, data, len);}static void sk_proxy_flush (Socket s){    Proxy_Socket ps = (Proxy_Socket) s;    if (ps->state != PROXY_STATE_ACTIVE) {	ps->pending_flush = 1;	return;    }    sk_flush(ps->sub_socket);}static void sk_proxy_set_private_ptr (Socket s, void *ptr){    Proxy_Socket ps = (Proxy_Socket) s;    sk_set_private_ptr(ps->sub_socket, ptr);}static void * sk_proxy_get_private_ptr (Socket s){    Proxy_Socket ps = (Proxy_Socket) s;    return sk_get_private_ptr(ps->sub_socket);}static void sk_proxy_set_frozen (Socket s, int is_frozen){    Proxy_Socket ps = (Proxy_Socket) s;    if (ps->state != PROXY_STATE_ACTIVE) {	ps->freeze = is_frozen;	return;    }        /* handle any remaining buffered recv data first */    if (bufchain_size(&ps->pending_input_data) > 0) {	ps->freeze = is_frozen;	/* loop while we still have buffered data, and while we are	 * unfrozen. the plug_receive call in the loop could result 	 * in a call back into this function refreezing the socket, 	 * so we have to check each time.	 */        while (!ps->freeze && bufchain_size(&ps->pending_input_data) > 0) {	    void *data;	    char databuf[512];	    int len;	    bufchain_prefix(&ps->pending_input_data, &data, &len);	    if (len > lenof(databuf))		len = lenof(databuf);	    memcpy(databuf, data, len);	    bufchain_consume(&ps->pending_input_data, len);	    plug_receive(ps->plug, 0, databuf, len);	}	/* if we're still frozen, we'll have to wait for another	 * call from the backend to finish unbuffering the data.	 */	if (ps->freeze) return;    }        sk_set_frozen(ps->sub_socket, is_frozen);}static const char * sk_proxy_socket_error (Socket s){    Proxy_Socket ps = (Proxy_Socket) s;    if (ps->error != NULL || ps->sub_socket == NULL) {	return ps->error;    }    return sk_socket_error(ps->sub_socket);}/* basic proxy plug functions */static int plug_proxy_closing (Plug p, const char *error_msg,			       int error_code, int calling_back){    Proxy_Plug pp = (Proxy_Plug) p;    Proxy_Socket ps = pp->proxy_socket;    if (ps->state != PROXY_STATE_ACTIVE) {	ps->closing_error_msg = error_msg;	ps->closing_error_code = error_code;	ps->closing_calling_back = calling_back;	return ps->negotiate(ps, PROXY_CHANGE_CLOSING);    }    return plug_closing(ps->plug, error_msg,			error_code, calling_back);}static int plug_proxy_receive (Plug p, int urgent, char *data, int len){    Proxy_Plug pp = (Proxy_Plug) p;    Proxy_Socket ps = pp->proxy_socket;    if (ps->state != PROXY_STATE_ACTIVE) {	/* we will lose the urgentness of this data, but since most,	 * if not all, of this data will be consumed by the negotiation	 * process, hopefully it won't affect the protocol above us	 */	bufchain_add(&ps->pending_input_data, data, len);	ps->receive_urgent = urgent;	ps->receive_data = data;	ps->receive_len = len;	return ps->negotiate(ps, PROXY_CHANGE_RECEIVE);    }    return plug_receive(ps->plug, urgent, data, len);}static void plug_proxy_sent (Plug p, int bufsize){    Proxy_Plug pp = (Proxy_Plug) p;    Proxy_Socket ps = pp->proxy_socket;    if (ps->state != PROXY_STATE_ACTIVE) {	ps->sent_bufsize = bufsize;	ps->negotiate(ps, PROXY_CHANGE_SENT);	return;    }    plug_sent(ps->plug, bufsize);}static int plug_proxy_accepting (Plug p, OSSocket sock){    Proxy_Plug pp = (Proxy_Plug) p;    Proxy_Socket ps = pp->proxy_socket;    if (ps->state != PROXY_STATE_ACTIVE) {	ps->accepting_sock = sock;	return ps->negotiate(ps, PROXY_CHANGE_ACCEPTING);    }    return plug_accepting(ps->plug, sock);}/* * This function can accept a NULL pointer as `addr', in which case * it will only check the host name. */static int proxy_for_destination (SockAddr addr, char *hostname, int port,				  const Config *cfg){    int s = 0, e = 0;    char hostip[64];    int hostip_len, hostname_len;    const char *exclude_list;    /*     * Check the host name and IP against the hard-coded     * representations of `localhost'.     */    if (!cfg->even_proxy_localhost &&	(sk_hostname_is_local(hostname) ||	 (addr && sk_address_is_local(addr))))	return 0;		       /* do not proxy */    /* we want a string representation of the IP address for comparisons */    if (addr) {	sk_getaddr(addr, hostip, 64);	hostip_len = strlen(hostip);    } else	hostip_len = 0;		       /* placate gcc; shouldn't be required */    hostname_len = strlen(hostname);    exclude_list = cfg->proxy_exclude_list;    /* now parse the exclude list, and see if either our IP     * or hostname matches anything in it.     */    while (exclude_list[s]) {	while (exclude_list[s] &&	       (isspace((unsigned char)exclude_list[s]) ||		exclude_list[s] == ',')) s++;	if (!exclude_list[s]) break;	e = s;	while (exclude_list[e] &&	       (isalnum((unsigned char)exclude_list[e]) ||		exclude_list[e] == '-' ||		exclude_list[e] == '.' ||		exclude_list[e] == '*')) e++;	if (exclude_list[s] == '*') {	    /* wildcard at beginning of entry */	    if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),				  exclude_list + s + 1, e - s - 1) == 0) ||		strnicmp(hostname + hostname_len - (e - s - 1),			 exclude_list + s + 1, e - s - 1) == 0)		return 0; /* IP/hostname range excluded. do not use proxy. */	} else if (exclude_list[e-1] == '*') {	    /* wildcard at end of entry */	    if ((addr && strnicmp(hostip, exclude_list + s, e - s - 1) == 0) ||		strnicmp(hostname, exclude_list + s, e - s - 1) == 0)		return 0; /* IP/hostname range excluded. do not use proxy. */	} else {	    /* no wildcard at either end, so let's try an absolute	     * match (ie. a specific IP)	     */	    if (addr && strnicmp(hostip, exclude_list + s, e - s) == 0)		return 0; /* IP/hostname excluded. do not use proxy. */	    if (strnicmp(hostname, exclude_list + s, e - s) == 0)		return 0; /* IP/hostname excluded. do not use proxy. */	}	s = e;	/* Make sure we really have reached the next comma or end-of-string */	while (exclude_list[s] &&	       !isspace((unsigned char)exclude_list[s]) &&	       exclude_list[s] != ',') s++;    }    /* no matches in the exclude list, so use the proxy */    return 1;}SockAddr name_lookup(char *host, int port, char **canonicalname,		     const Config *cfg){    if (cfg->proxy_type != PROXY_NONE &&	do_proxy_dns(cfg) &&	proxy_for_destination(NULL, host, port, cfg)) {	*canonicalname = dupstr(host);	return sk_nonamelookup(host);    }    return sk_namelookup(host, canonicalname);}Socket new_connection(SockAddr addr, char *hostname,		      int port, int privport,		      int oobinline, int nodelay, int keepalive,		      Plug plug, const Config *cfg){    static const struct socket_function_table socket_fn_table = {	sk_proxy_plug,	sk_proxy_close,	sk_proxy_write,	sk_proxy_write_oob,	sk_proxy_flush,	sk_proxy_set_private_ptr,	sk_proxy_get_private_ptr,	sk_proxy_set_frozen,	sk_proxy_socket_error    };    static const struct plug_function_table plug_fn_table = {	plug_proxy_closing,	plug_proxy_receive,	plug_proxy_sent,	plug_proxy_accepting    };    if (cfg->proxy_type != PROXY_NONE &&	proxy_for_destination(addr, hostname, port, cfg))    {	Proxy_Socket ret;	Proxy_Plug pplug;	SockAddr proxy_addr;	char *proxy_canonical_name;	Socket sret;	if ((sret = platform_new_connection(addr, hostname, port, privport,					    oobinline, nodelay, keepalive,					    plug, cfg)) !=	    NULL)	    return sret;	ret = snew(struct Socket_proxy_tag);	ret->fn = &socket_fn_table;	ret->cfg = *cfg;	       /* STRUCTURE COPY */	ret->plug = plug;	ret->remote_addr = addr;       /* will need to be freed on close */	ret->remote_port = port;	ret->error = NULL;	ret->pending_flush = 0;	ret->freeze = 0;	bufchain_init(&ret->pending_input_data);	bufchain_init(&ret->pending_output_data);	bufchain_init(&ret->pending_oob_output_data);	ret->sub_socket = NULL;	ret->state = PROXY_STATE_NEW;	ret->negotiate = NULL;		if (cfg->proxy_type == PROXY_HTTP) {	    ret->negotiate = proxy_http_negotiate;	} else if (cfg->proxy_type == PROXY_SOCKS4) {            ret->negotiate = proxy_socks4_negotiate;	} else if (cfg->proxy_type == PROXY_SOCKS5) {            ret->negotiate = proxy_socks5_negotiate;	} else if (cfg->proxy_type == PROXY_TELNET) {	    ret->negotiate = proxy_telnet_negotiate;	} else {	    ret->error = "Proxy error: Unknown proxy method";	    return (Socket) ret;	}	/* create the proxy plug to map calls from the actual	 * socket into our proxy socket layer */	pplug = snew(struct Plug_proxy_tag);	pplug->fn = &plug_fn_table;	pplug->proxy_socket = ret;	/* look-up proxy */	proxy_addr = sk_namelookup(cfg->proxy_host,				   &proxy_canonical_name);	if (sk_addr_error(proxy_addr) != NULL) {	    ret->error = "Proxy error: Unable to resolve proxy host name";	    return (Socket)ret;	}	sfree(proxy_canonical_name);	/* create the actual socket we will be using,	 * connected to our proxy server and port.	 */	ret->sub_socket = sk_new(proxy_addr, cfg->proxy_port,				 privport, oobinline,				 nodelay, keepalive, (Plug) pplug);	if (sk_socket_error(ret->sub_socket) != NULL)	    return (Socket) ret;	/* start the proxy negotiation process... */	sk_set_frozen(ret->sub_socket, 0);	ret->negotiate(ret, PROXY_CHANGE_NEW);	return (Socket) ret;    }    /* no proxy, so just return the direct socket */    return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug);}Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,		    const Config *cfg){    /* TODO: SOCKS (and potentially others) support inbound     * TODO: connections via the proxy. support them.     */    return sk_newlistener(srcaddr, port, plug, local_host_only);}/* ---------------------------------------------------------------------- * HTTP CONNECT proxy type. */static int get_line_end (char * data, int len){    int off = 0;    while (off < len)    {	if (data[off] == '\n') {	    /* we have a newline */

⌨️ 快捷键说明

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