diff --git a/nsock/src/nsock_proxy.c b/nsock/src/nsock_proxy.c index 8ce57c440..3c89f8e69 100644 --- a/nsock/src/nsock_proxy.c +++ b/nsock/src/nsock_proxy.c @@ -82,9 +82,6 @@ static struct proxy_parser *proxy_parser_new(const char *proxychainstr); static void proxy_parser_next(struct proxy_parser *parser); static void proxy_parser_delete(struct proxy_parser *parser); -static struct proxy_node *proxy_node_new(char *proxystr); -static void proxy_node_delete(struct proxy_node *proxy); - /* --- Implemented proxy backends --- */ extern const struct proxy_op proxy_http_ops; @@ -133,7 +130,7 @@ void nsock_proxychain_delete(nsock_proxychain chain) { free(pchain->specstr); while ((node = (struct proxy_node *)gh_list_pop(&pchain->nodes)) != NULL) { - proxy_node_delete(node); + node->ops->node_delete(node); } gh_list_free(&pchain->nodes); @@ -157,17 +154,69 @@ int nsp_set_proxychain(nsock_pool nspool, nsock_proxychain chain) { struct proxy_chain_context *proxy_chain_context_new(nsock_pool nspool) { mspool *nsp = (mspool *)nspool; struct proxy_chain_context *ctx; + gh_list_elem *elt; ctx = (struct proxy_chain_context *)safe_malloc(sizeof(struct proxy_chain_context)); ctx->px_chain = nsp->px_chain; ctx->px_state = PROXY_STATE_INITIAL; ctx->px_current = GH_LIST_FIRST_ELEM(&nsp->px_chain->nodes); + gh_list_init(&ctx->px_info); + + for (elt = GH_LIST_FIRST_ELEM(&nsp->px_chain->nodes); elt != NULL; elt = GH_LIST_ELEM_NEXT(elt)) { + struct proxy_node *px = (struct proxy_node *)GH_LIST_ELEM_DATA(elt); + void *pinfo = NULL; + + px->ops->info_new(&pinfo); + gh_list_append(&ctx->px_info, pinfo); + } + return ctx; } void proxy_chain_context_delete(struct proxy_chain_context *ctx) { - if (ctx) + if (ctx) { + gh_list_elem *pxe; + + assert(GH_LIST_COUNT(&ctx->px_chain->nodes) == GH_LIST_COUNT(&ctx->px_info)); + + for (pxe = GH_LIST_FIRST_ELEM(&ctx->px_chain->nodes); pxe != NULL; pxe = GH_LIST_ELEM_NEXT(pxe)) { + struct proxy_node *pxn; + void *px_info; + + pxn = (struct proxy_node *)GH_LIST_ELEM_DATA(pxe); + px_info = gh_list_pop(&ctx->px_info); + + pxn->ops->info_delete(px_info); + } + + gh_list_free(&ctx->px_info); free(ctx); + } +} + +/* XXX + * This function is just an ugly PoC. + * + * A clean version should handle: + * - both v4 and v6 adresses + * - hostnames (how do we want to resolve them though??) + * - user:pass@ prefix before host specification + */ +static struct proxy_node *proxy_node_new(char *proxystr) { + int i; + + for (i = 0; ProxyBackends[i] != NULL; i++) { + const struct proxy_op *pxop; + + pxop = ProxyBackends[i]; + if (strncasecmp(proxystr, pxop->prefix, strlen(pxop->prefix)) == 0) { + struct proxy_node *proxy; + + pxop->node_new(&proxy, proxystr); + return proxy; + } + } + fatal("Invalid protocol in proxy specification string: %s", proxystr); } struct proxy_parser *proxy_parser_new(const char *proxychainstr) { @@ -206,37 +255,6 @@ void proxy_parser_delete(struct proxy_parser *parser) { } } -/* XXX - * This function is just an ugly PoC. - * - * A clean version should handle: - * - both v4 and v6 adresses - * - hostnames (how do we want to resolve them though??) - * - user:pass@ prefix before host specification - */ -static struct proxy_node *proxy_node_new(char *proxystr) { - int i; - - for (i = 0; ProxyBackends[i] != NULL; i++) { - const struct proxy_op *pxop; - - pxop = ProxyBackends[i]; - if (strncasecmp(proxystr, pxop->prefix, strlen(pxop->prefix)) == 0) { - struct proxy_node *proxy; - - proxy = (struct proxy_node *)safe_zalloc(sizeof(struct proxy_node)); - pxop->init(proxy, proxystr); - return proxy; - } - } - fatal("Invalid protocol in proxy specification string: %s", proxystr); -} - -static void proxy_node_delete(struct proxy_node *proxy) { - if (proxy) - free(proxy); -} - void forward_event(nsock_pool nspool, nsock_event nsevent, void *udata) { mspool *nsp = (mspool *)nspool; msevent *nse = (msevent *)nsevent; diff --git a/nsock/src/nsock_proxy.h b/nsock/src/nsock_proxy.h index a08399c9e..267c5404c 100644 --- a/nsock/src/nsock_proxy.h +++ b/nsock/src/nsock_proxy.h @@ -85,6 +85,9 @@ enum nsock_proxy_state { /* ------------------- STRUCTURES ------------------- */ +/* Static information about a proxy node in the chain. This is generated by + * parsing the proxy specification string given by user. Those structures are + * then read-only and stored in the nsock_pool. */ struct proxy_node { enum nsock_proxy_type px_type; @@ -95,19 +98,26 @@ struct proxy_node { unsigned short port; }; +/* Ordered list of proxy nodes, as specified in the proxy specification string. */ struct proxy_chain { char *specstr; gh_list nodes; }; +/* IOD-specific context. For each IOD we establish a tunnel through the chain of + * proxies. This structure stores all the related information. */ struct proxy_chain_context { - struct proxy_chain *px_chain; + const struct proxy_chain *px_chain; /* Those fields are used to store current state during the tunnel * establishment phase. */ gh_list_elem *px_current; enum nsock_proxy_state px_state; + /* Each proxy in the chain maintains a data structure. This can contains r/w + * buffers for instance. */ + gh_list px_info; + struct sockaddr_storage target_ss; size_t target_sslen; unsigned short target_port; @@ -118,10 +128,17 @@ struct proxy_op { const char *prefix; enum nsock_proxy_type type; - void (*init)(struct proxy_node *proxy, char *proxystr); + int (*node_new)(struct proxy_node **node, char *proxystr); + void (*node_delete)(struct proxy_node *node); + + int (*info_new)(void **info); + void (*info_delete)(void *info); + void (*handler)(nsock_pool nspool, nsock_event nsevent, void *udata); + nsock_event_id (*connect_tcp)(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int mstimeout, void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port); + char *(*encode)(const char *src, size_t len, size_t *dlen); char *(*decode)(const char *src, size_t len, size_t *dlen); }; diff --git a/nsock/src/proxy_http.c b/nsock/src/proxy_http.c index 63744b253..75082e016 100644 --- a/nsock/src/proxy_http.c +++ b/nsock/src/proxy_http.c @@ -61,9 +61,16 @@ #define DEFAULT_PROXY_PORT_HTTP "8080" +struct http_proxy_info { + void *dummy; +}; -/* --- PROXY INTERFACE PROTOTYPES --- */ -static void proxy_http_init(struct proxy_node *proxy, char *proxystr); + +/* ---- PROTOTYPES ---- */ +static int proxy_http_node_new(struct proxy_node **node, char *proxystr); +static void proxy_http_node_delete(struct proxy_node *node); +static int proxy_http_info_new(void **info); +static void proxy_http_info_delete(void *info); static void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata); static nsock_event_id proxy_http_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *saddr, @@ -76,7 +83,10 @@ static char *proxy_http_decode(const char *src, size_t len, size_t *dlen); const struct proxy_op proxy_http_ops = { .prefix = "http://", .type = PROXY_TYPE_HTTP, - .init = proxy_http_init, + .node_new = proxy_http_node_new, + .node_delete = proxy_http_node_delete, + .info_new = proxy_http_info_new, + .info_delete = proxy_http_info_delete, .handler = proxy_http_handler, .connect_tcp = proxy_http_connect_tcp, .encode = proxy_http_encode, @@ -84,10 +94,12 @@ const struct proxy_op proxy_http_ops = { }; -void proxy_http_init(struct proxy_node *proxy, char *proxystr) { +int proxy_http_node_new(struct proxy_node **node, char *proxystr) { struct sockaddr_in *sin; + struct proxy_node *proxy; char *strhost, *strport, *saveptr; + proxy = (struct proxy_node *)safe_zalloc(sizeof(struct proxy_node)); proxy->ops = &proxy_http_ops; strhost = strtok_r(proxystr + 7, ":", &saveptr); @@ -101,6 +113,31 @@ void proxy_http_init(struct proxy_node *proxy, char *proxystr) { proxy->sslen = sizeof(struct sockaddr_in); proxy->port = (unsigned short)atoi(strport); + + *node = proxy; + + return 1; +} + +void proxy_http_node_delete(struct proxy_node *node) { + if (node) + free(node); +} + +int proxy_http_info_new(void **info) { + struct http_proxy_info *pxi; + + pxi = (struct http_proxy_info *)safe_zalloc(sizeof(struct http_proxy_info)); + pxi->dummy = NULL; // TODO + + *info = pxi; + + return 1; +} + +void proxy_http_info_delete(void *info) { + if (info) + free(info); } void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata) {