// Construct a URL object from the string representation URL::URL(const std::string& url_str) { if (url_str.empty()) throw std::invalid_argument("empty url string"); const std::string sr = boost::trim_copy(url_str); try { token_rest scheme_rest = get_scheme(sr); scheme = scheme_rest.first; std::cout << scheme_rest.first << " : " << scheme_rest.second << std::endl; token_rest host_port_rest = get_host_port(scheme_rest.second); std::cout << host_port_rest.first << " : " << host_port_rest.second << std::endl; std::pair<std::string,uint16_t> host_port = split_host_port(host_port_rest.first); std::cout << host_port.first << " : " << host_port.second << std::endl; host = host_port.first; port = host_port.second; token_rest path_rest = get_path(host_port_rest.second); std::cout << path_rest.first << std::endl; path = path_rest.first; if (path_rest.second.empty()) return; token_rest query_rest = get_query(path_rest.second); std::cout << query_rest.first << " : " << query_rest.second << std::endl; if (!query_rest.first.empty()) { query_key_vals = make_query_map(query_rest.first); } std::string fragment = get_fragment(query_rest.second); std::cout << fragment << std::endl; } catch(const std::exception &e) { std::cerr << e.what() << std::endl; throw e; } // parsed successfully, we can copy over the original arg string_rep = url_str; }
void HttpRequest::get_conn_host_port(std::string& host, unsigned int& port) const { if (m_proxy_host.empty()) { get_host_port(host, port); } else { host = m_proxy_host; port = m_proxy_port; } }
/* This function resumes listening on the specified proxy. It scans all of its * listeners and tries to enable them all. If any of them fails, the proxy is * put back to the paused state. It returns 1 upon success, or zero if an error * is encountered. */ int resume_proxy(struct proxy *p) { struct listener *l; int fail; if (p->state != PR_STPAUSED) return 1; Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); fail = 0; for (l = p->listen; l != NULL; l = l->next) { if (!resume_listener(l)) { int port; port = get_host_port(&l->addr); if (port) { Warning("Port %d busy while trying to enable %s %s.\n", port, proxy_cap_str(p->cap), p->id); send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n", port, proxy_cap_str(p->cap), p->id); } else { Warning("Bind on socket %d busy while trying to enable %s %s.\n", l->luid, proxy_cap_str(p->cap), p->id); send_log(p, LOG_WARNING, "Bind on socket %d busy while trying to enable %s %s.\n", l->luid, proxy_cap_str(p->cap), p->id); } /* Another port might have been enabled. Let's stop everything. */ fail = 1; break; } } p->state = PR_STREADY; if (fail) { pause_proxy(p); return 0; } return 1; }
/* prepare the trash with a log prefix for session <sess>. It only works with * embryonic sessions based on a real connection. This function requires that * at sess->origin points to the incoming connection. */ static void session_prepare_log_prefix(struct session *sess) { struct tm tm; char pn[INET6_ADDRSTRLEN]; int ret; char *end; struct connection *cli_conn = __objt_conn(sess->origin); ret = addr_to_str(&cli_conn->addr.from, pn, sizeof(pn)); if (ret <= 0) chunk_printf(&trash, "unknown ["); else if (ret == AF_UNIX) chunk_printf(&trash, "%s:%d [", pn, sess->listener->luid); else chunk_printf(&trash, "%s:%d [", pn, get_host_port(&cli_conn->addr.from)); get_localtime(sess->accept_date.tv_sec, &tm); end = date2str_log(trash.str + trash.len, &tm, &(sess->accept_date), trash.size - trash.len); trash.len = end - trash.str; if (sess->listener->name) chunk_appendf(&trash, "] %s/%s", sess->fe->id, sess->listener->name); else chunk_appendf(&trash, "] %s/%d", sess->fe->id, sess->listener->luid); }
/* * This function assigns a server address to a session, and sets SN_ADDR_SET. * The address is taken from the currently assigned server, or from the * dispatch or transparent address. * * It may return : * SRV_STATUS_OK if everything is OK. * SRV_STATUS_INTERNAL for other unrecoverable errors. * * Upon successful return, the session flag SN_ADDR_SET is set. This flag is * not cleared, so it's to the caller to clear it if required. * * The caller is responsible for having already assigned a connection * to si->end. * */ int assign_server_address(struct session *s) { struct connection *cli_conn = objt_conn(s->si[0].end); struct connection *srv_conn = objt_conn(s->si[1].end); #ifdef DEBUG_FULL fprintf(stderr,"assign_server_address : s=%p\n",s); #endif if ((s->flags & SN_DIRECT) || (s->be->lbprm.algo & BE_LB_KIND)) { /* A server is necessarily known for this session */ if (!(s->flags & SN_ASSIGNED)) return SRV_STATUS_INTERNAL; srv_conn->addr.to = objt_server(s->target)->addr; if (!is_addr(&srv_conn->addr.to) && cli_conn) { /* if the server has no address, we use the same address * the client asked, which is handy for remapping ports * locally on multiple addresses at once. Nothing is done * for AF_UNIX addresses. */ conn_get_to_addr(cli_conn); if (cli_conn->addr.to.ss_family == AF_INET) { ((struct sockaddr_in *)&srv_conn->addr.to)->sin_addr = ((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr; } else if (cli_conn->addr.to.ss_family == AF_INET6) { ((struct sockaddr_in6 *)&srv_conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&cli_conn->addr.to)->sin6_addr; } } /* if this server remaps proxied ports, we'll use * the port the client connected to with an offset. */ if ((objt_server(s->target)->flags & SRV_F_MAPPORTS) && cli_conn) { int base_port; conn_get_to_addr(cli_conn); /* First, retrieve the port from the incoming connection */ base_port = get_host_port(&cli_conn->addr.to); /* Second, assign the outgoing connection's port */ base_port += get_host_port(&srv_conn->addr.to); set_host_port(&srv_conn->addr.to, base_port); } } else if (s->be->options & PR_O_DISPATCH) { /* connect to the defined dispatch addr */ srv_conn->addr.to = s->be->dispatch_addr; } else if ((s->be->options & PR_O_TRANSP) && cli_conn) { /* in transparent mode, use the original dest addr if no dispatch specified */ conn_get_to_addr(cli_conn); if (cli_conn->addr.to.ss_family == AF_INET || cli_conn->addr.to.ss_family == AF_INET6) srv_conn->addr.to = cli_conn->addr.to; } else if (s->be->options & PR_O_HTTP_PROXY) { /* If HTTP PROXY option is set, then server is already assigned * during incoming client request parsing. */ } else { /* no server and no LB algorithm ! */ return SRV_STATUS_INTERNAL; } /* Copy network namespace from client connection */ srv_conn->proxy_netns = cli_conn ? cli_conn->proxy_netns : NULL; s->flags |= SN_ADDR_SET; return SRV_STATUS_OK; }
// main function for parsing a string url into a url struct url_t *parse_url(char const *const url_string,unsigned int *url_err_out) { *url_err_out = UPARSE_ERROR; url_t *url = (url_t *) malloc(sizeof(url_t)); if (NULL == url) { fprintf(stderr,"cannot allocate url\n"); return NULL; } init_url_t(url); url->original = strdup(url_string); if (NULL == url->original) { fprintf(stderr,"cannot allocate original\n"); free_url_t(url); return NULL; } char *mut_url_string = strdup(url_string); char *free_mut_url_string = mut_url_string; if (NULL == mut_url_string) { fprintf(stderr,"cannot allocate url\n"); free_url_t(url); return NULL; } unsigned int scheme_out_err = 0; url->scheme = get_scheme(&mut_url_string,&scheme_out_err); if (NO_UPARSE_ERROR != scheme_out_err) { fprintf(stderr,"fail from get_scheme\n"); free_url_t(url); free(free_mut_url_string); return NULL; } unsigned int host_port_out_err = 0; host_port_t *host_port = get_host_port(&mut_url_string,&host_port_out_err); if (NO_UPARSE_ERROR != host_port_out_err) { fprintf(stderr,"fail from get_host_port\n"); free_url_t(url); free(free_mut_url_string); return NULL; } url->host = strdup(host_port->host); if (NULL == url->host) { fprintf(stderr,"cannot allocate host\n"); free_url_t(url); free(free_mut_url_string); return NULL; } url->port = host_port->port; free_host_port_t(host_port); unsigned int path_err_out = 0; url->path_elt_list = get_path(&mut_url_string,&path_err_out); if (NO_UPARSE_ERROR != path_err_out) { fprintf(stderr,"fail from get_path\n"); free_url_t(url); free(free_mut_url_string); return NULL; } unsigned int query_err_out = 0; url->query_arg_list = get_query_arg_list(&mut_url_string,&query_err_out); if (UPARSE_ERROR == query_err_out) { fprintf(stderr,"fail from get_query_arg_list\n"); free_url_t(url); free(free_mut_url_string); return NULL; } unsigned int fragment_err_out = 0; url->fragment = get_fragment(&mut_url_string,&fragment_err_out); if (UPARSE_ERROR == fragment_err_out) { fprintf(stderr,"fail from get_fragment\n"); free_url_t(url); free(free_mut_url_string); return NULL; } free(free_mut_url_string); *url_err_out = NO_UPARSE_ERROR; return url; }
/* Finish a stream accept() for a proxy (TCP or HTTP). It returns a negative * value in case of a critical failure which must cause the listener to be * disabled, a positive or null value in case of success. */ int frontend_accept(struct stream *s) { struct session *sess = s->sess; struct connection *conn = objt_conn(sess->origin); struct listener *l = sess->listener; struct proxy *fe = sess->fe; if (unlikely(fe->nb_req_cap > 0)) { if ((s->req_cap = pool_alloc2(fe->req_cap_pool)) == NULL) goto out_return; /* no memory */ memset(s->req_cap, 0, fe->nb_req_cap * sizeof(void *)); } if (unlikely(fe->nb_rsp_cap > 0)) { if ((s->res_cap = pool_alloc2(fe->rsp_cap_pool)) == NULL) goto out_free_reqcap; /* no memory */ memset(s->res_cap, 0, fe->nb_rsp_cap * sizeof(void *)); } if (fe->http_needed) { /* we have to allocate header indexes only if we know * that we may make use of them. This of course includes * (mode == PR_MODE_HTTP). */ if (unlikely(!http_alloc_txn(s))) goto out_free_rspcap; /* no memory */ /* and now initialize the HTTP transaction state */ http_init_txn(s); } if ((fe->mode == PR_MODE_TCP || fe->mode == PR_MODE_HTTP) && (!LIST_ISEMPTY(&fe->logsrvs))) { if (likely(!LIST_ISEMPTY(&fe->logformat))) { /* we have the client ip */ if (s->logs.logwait & LW_CLIP) if (!(s->logs.logwait &= ~(LW_CLIP|LW_INIT))) s->do_log(s); } else if (conn) { char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN]; conn_get_from_addr(conn); conn_get_to_addr(conn); switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: addr_to_str(&conn->addr.to, sn, sizeof(sn)); send_log(fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n", pn, get_host_port(&conn->addr.from), sn, get_host_port(&conn->addr.to), fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; case AF_UNIX: /* UNIX socket, only the destination is known */ send_log(fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n", l->luid, fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; } } } if (unlikely((global.mode & MODE_DEBUG) && conn && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) { char pn[INET6_ADDRSTRLEN]; conn_get_from_addr(conn); switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n", s->uniq_id, fe->id, (unsigned short)l->fd, (unsigned short)conn->t.sock.fd, pn, get_host_port(&conn->addr.from)); break; case AF_UNIX: /* UNIX socket, only the destination is known */ chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [unix:%d]\n", s->uniq_id, fe->id, (unsigned short)l->fd, (unsigned short)conn->t.sock.fd, l->luid); break; } shut_your_big_mouth_gcc(write(1, trash.str, trash.len)); } if (fe->mode == PR_MODE_HTTP) s->req.flags |= CF_READ_DONTWAIT; /* one read is usually enough */ /* everything's OK, let's go on */ return 1; /* Error unrolling */ out_free_rspcap: pool_free2(fe->rsp_cap_pool, s->res_cap); out_free_reqcap: pool_free2(fe->req_cap_pool, s->req_cap); out_return: return -1; }
/* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative * value in case of a critical failure which must cause the listener to be * disabled, a positive value in case of success, or zero if it is a success * but the session must be closed ASAP (eg: monitoring). */ int frontend_accept(struct session *s) { int cfd = s->si[0].fd; tv_zero(&s->logs.tv_request); s->logs.t_queue = -1; s->logs.t_connect = -1; s->logs.t_data = -1; s->logs.t_close = 0; s->logs.bytes_in = s->logs.bytes_out = 0; s->logs.prx_queue_size = 0; /* we get the number of pending conns before us */ s->logs.srv_queue_size = 0; /* we will get this number soon */ /* FIXME: the logs are horribly complicated now, because they are * defined in <p>, <p>, and later <be> and <be>. */ s->do_log = sess_log; /* default error reporting function, may be changed by analysers */ s->srv_error = default_srv_error; /* Adjust some socket options */ if (s->listener->addr.ss_family == AF_INET || s->listener->addr.ss_family == AF_INET6) { if (setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1) goto out_return; if (s->fe->options & PR_O_TCP_CLI_KA) setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one)); if (s->fe->options & PR_O_TCP_NOLING) setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger)); #if defined(TCP_MAXSEG) if (s->listener->maxseg < 0) { /* we just want to reduce the current MSS by that value */ int mss; socklen_t mss_len = sizeof(mss); if (getsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &mss_len) == 0) { mss += s->listener->maxseg; /* remember, it's < 0 */ setsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); } } #endif } if (global.tune.client_sndbuf) setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, &global.tune.client_sndbuf, sizeof(global.tune.client_sndbuf)); if (global.tune.client_rcvbuf) setsockopt(cfd, SOL_SOCKET, SO_RCVBUF, &global.tune.client_rcvbuf, sizeof(global.tune.client_rcvbuf)); if (s->fe->mode == PR_MODE_HTTP) { /* the captures are only used in HTTP frontends */ if (unlikely(s->fe->nb_req_cap > 0 && (s->txn.req.cap = pool_alloc2(s->fe->req_cap_pool)) == NULL)) goto out_return; /* no memory */ if (unlikely(s->fe->nb_rsp_cap > 0 && (s->txn.rsp.cap = pool_alloc2(s->fe->rsp_cap_pool)) == NULL)) goto out_free_reqcap; /* no memory */ } if (s->fe->acl_requires & ACL_USE_L7_ANY) { /* we have to allocate header indexes only if we know * that we may make use of them. This of course includes * (mode == PR_MODE_HTTP). */ s->txn.hdr_idx.size = global.tune.max_http_hdr; if (unlikely((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL)) goto out_free_rspcap; /* no memory */ /* and now initialize the HTTP transaction state */ http_init_txn(s); } if ((s->fe->mode == PR_MODE_TCP || s->fe->mode == PR_MODE_HTTP) && (!LIST_ISEMPTY(&s->fe->logsrvs))) { if (likely(s->fe->to_log)) { /* we have the client ip */ if (s->logs.logwait & LW_CLIP) if (!(s->logs.logwait &= ~LW_CLIP)) s->do_log(s); } else { char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN]; if (!(s->flags & SN_FRT_ADDR_SET)) get_frt_addr(s); switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: addr_to_str(&s->req->prod->addr.to, sn, sizeof(sn)); send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n", pn, get_host_port(&s->req->prod->addr.from), sn, get_host_port(&s->req->prod->addr.to), s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; case AF_UNIX: /* UNIX socket, only the destination is known */ send_log(s->fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n", s->listener->luid, s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; } } } if (unlikely((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) { char pn[INET6_ADDRSTRLEN]; int len = 0; if (!(s->flags & SN_FRT_ADDR_SET)) get_frt_addr(s); switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n", s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd, pn, get_host_port(&s->req->prod->addr.from)); break; case AF_UNIX: /* UNIX socket, only the destination is known */ len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [unix:%d]\n", s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd, s->listener->luid); break; } write(1, trash, len); } if (s->fe->mode == PR_MODE_HTTP) s->req->flags |= BF_READ_DONTWAIT; /* one read is usually enough */ /* note: this should not happen anymore since there's always at least the switching rules */ if (!s->req->analysers) { buffer_auto_connect(s->req); /* don't wait to establish connection */ buffer_auto_close(s->req); /* let the producer forward close requests */ } s->req->rto = s->fe->timeout.client; s->rep->wto = s->fe->timeout.client; fdtab[cfd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY; if (s->fe->options & PR_O_TCP_NOLING) fdtab[cfd].flags |= FD_FL_TCP_NOLING; if (unlikely((s->fe->mode == PR_MODE_HTTP && (s->flags & SN_MONITOR)) || (s->fe->mode == PR_MODE_HEALTH && ((s->fe->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK)))) { /* Either we got a request from a monitoring system on an HTTP instance, * or we're in health check mode with the 'httpchk' option enabled. In * both cases, we return a fake "HTTP/1.0 200 OK" response and we exit. */ struct chunk msg; chunk_initstr(&msg, "HTTP/1.0 200 OK\r\n\r\n"); stream_int_retnclose(&s->si[0], &msg); /* forge a 200 response */ s->req->analysers = 0; s->task->expire = s->rep->wex; EV_FD_CLR(cfd, DIR_RD); } else if (unlikely(s->fe->mode == PR_MODE_HEALTH)) { /* health check mode, no client reading */ struct chunk msg; chunk_initstr(&msg, "OK\n"); stream_int_retnclose(&s->si[0], &msg); /* forge an "OK" response */ s->req->analysers = 0; s->task->expire = s->rep->wex; EV_FD_CLR(cfd, DIR_RD); } /* everything's OK, let's go on */ return 1; /* Error unrolling */ out_free_rspcap: pool_free2(s->fe->rsp_cap_pool, s->txn.rsp.cap); out_free_reqcap: pool_free2(s->fe->req_cap_pool, s->txn.req.cap); out_return: return -1; }
char *load_config_from_string(struct config *config, char *buf, int testing) { char *err = "unknown error"; char *host, *key; int port, key_sz; int proxies = 0, servers = 0; char **lines = (char**)malloc(sizeof(char*) * MAX_CONFIG_LINES); int lines_no = split_line(lines, MAX_CONFIG_LINES, buf, "\n\r", ""); int line_no = 0; for(line_no = 0; line_no < lines_no; line_no++) { char *line = lines[line_no]; char *argv[32]; int argc = split_line(argv, NELEM(argv), line, " ,\t", "#"); if(argc == 0) continue; if(0 == strcmp(argv[0], "proxy")) { if(argc != 1+1) { err = "Expected exactly one argument"; goto error; } if(0 != get_host_port(&host, &port, argv[1])) { err = "Bad host description or port number"; goto error; } if(!testing && -1 == new_st_proxy(config, host, port)){ err = "Duplicate proxy"; goto error; } proxies++; }else if(0 == strcmp(argv[0], "server")) { if(argc != 3+1 && argc != 2+1) { err = "Expected two or three arguments"; goto error; } if(0 != get_host_port(&host, &port, argv[1])) { err = "Bad host description or port number"; goto error; } int weight = atoi(argv[2]); if(weight < 1 || weight > 999999) { err = "Broken weight value"; goto error; } if(argc == 3+1) { if(0 != decode_hex(&key, &key_sz, argv[3])) { err = "Broken key value"; goto error; } } else { key = ""; key_sz = 0; } if(!testing && -1 == new_st_server(config, host, port, weight, key, key_sz)) { err = "Duplicate server"; goto error; } servers++; } else { err = argv[0];//"Unrecognized keyword"; goto error; } } if(!proxies) { err = "No proxies defined in config, not even myself!\n" "Are you sure it's a correct autogenerated file?"; goto error; } if(!servers) { err = "No servers defined in config. It's broken!"; goto error; } free(lines); return(NULL); error:; free(lines); static char line[256]; snprintf(line, sizeof(line), "%s on line %i", err, line_no+1); return(line); }
/* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative * value in case of a critical failure which must cause the listener to be * disabled, a positive value in case of success, or zero if it is a success * but the session must be closed ASAP (eg: monitoring). */ int frontend_accept(struct session *s) { int cfd = s->si[0].conn->t.sock.fd; tv_zero(&s->logs.tv_request); s->logs.t_queue = -1; s->logs.t_connect = -1; s->logs.t_data = -1; s->logs.t_close = 0; s->logs.bytes_in = s->logs.bytes_out = 0; s->logs.prx_queue_size = 0; /* we get the number of pending conns before us */ s->logs.srv_queue_size = 0; /* we will get this number soon */ /* FIXME: the logs are horribly complicated now, because they are * defined in <p>, <p>, and later <be> and <be>. */ s->do_log = sess_log; /* default error reporting function, may be changed by analysers */ s->srv_error = default_srv_error; /* Adjust some socket options */ if (s->listener->addr.ss_family == AF_INET || s->listener->addr.ss_family == AF_INET6) { if (setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1) goto out_return; if (s->fe->options & PR_O_TCP_CLI_KA) setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one)); if (s->fe->options & PR_O_TCP_NOLING) setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger)); #if defined(TCP_MAXSEG) if (s->listener->maxseg < 0) { /* we just want to reduce the current MSS by that value */ int mss; socklen_t mss_len = sizeof(mss); if (getsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &mss_len) == 0) { mss += s->listener->maxseg; /* remember, it's < 0 */ setsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); } } #endif } if (global.tune.client_sndbuf) setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, &global.tune.client_sndbuf, sizeof(global.tune.client_sndbuf)); if (global.tune.client_rcvbuf) setsockopt(cfd, SOL_SOCKET, SO_RCVBUF, &global.tune.client_rcvbuf, sizeof(global.tune.client_rcvbuf)); if (s->fe->mode == PR_MODE_HTTP) { /* the captures are only used in HTTP frontends */ if (unlikely(s->fe->nb_req_cap > 0 && (s->txn.req.cap = pool_alloc2(s->fe->req_cap_pool)) == NULL)) goto out_return; /* no memory */ if (unlikely(s->fe->nb_rsp_cap > 0 && (s->txn.rsp.cap = pool_alloc2(s->fe->rsp_cap_pool)) == NULL)) goto out_free_reqcap; /* no memory */ } if (s->fe->http_needed) { /* we have to allocate header indexes only if we know * that we may make use of them. This of course includes * (mode == PR_MODE_HTTP). */ s->txn.hdr_idx.size = global.tune.max_http_hdr; if (unlikely((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL)) goto out_free_rspcap; /* no memory */ /* and now initialize the HTTP transaction state */ http_init_txn(s); } if ((s->fe->mode == PR_MODE_TCP || s->fe->mode == PR_MODE_HTTP) && (!LIST_ISEMPTY(&s->fe->logsrvs))) { if (likely(!LIST_ISEMPTY(&s->fe->logformat))) { /* we have the client ip */ if (s->logs.logwait & LW_CLIP) if (!(s->logs.logwait &= ~(LW_CLIP|LW_INIT))) s->do_log(s); } else { char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN]; conn_get_from_addr(s->req->prod->conn); conn_get_to_addr(s->req->prod->conn); switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: addr_to_str(&s->req->prod->conn->addr.to, sn, sizeof(sn)); send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n", pn, get_host_port(&s->req->prod->conn->addr.from), sn, get_host_port(&s->req->prod->conn->addr.to), s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; case AF_UNIX: /* UNIX socket, only the destination is known */ send_log(s->fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n", s->listener->luid, s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"); break; } } } if (unlikely((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) { char pn[INET6_ADDRSTRLEN]; conn_get_from_addr(s->req->prod->conn); switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) { case AF_INET: case AF_INET6: chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n", s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd, pn, get_host_port(&s->req->prod->conn->addr.from)); break; case AF_UNIX: /* UNIX socket, only the destination is known */ chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [unix:%d]\n", s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd, s->listener->luid); break; } if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */; } if (s->fe->mode == PR_MODE_HTTP) s->req->flags |= CF_READ_DONTWAIT; /* one read is usually enough */ /* note: this should not happen anymore since there's always at least the switching rules */ if (!s->req->analysers) { channel_auto_connect(s->req); /* don't wait to establish connection */ channel_auto_close(s->req); /* let the producer forward close requests */ } s->req->rto = s->fe->timeout.client; s->rep->wto = s->fe->timeout.client; /* everything's OK, let's go on */ return 1; /* Error unrolling */ out_free_rspcap: pool_free2(s->fe->rsp_cap_pool, s->txn.rsp.cap); out_free_reqcap: pool_free2(s->fe->req_cap_pool, s->txn.req.cap); out_return: return -1; }