static void private_fwdNegotiateSSL(int fd,void *data) { SSL *ssl = fd_table[fd].ssl; int ret; server *s=(server *)data; //unsigned char key[22]; errno = 0; ERR_clear_error(); if ((ret = SSL_connect(ssl)) <= 0) { int ssl_error = SSL_get_error(ssl, ret); switch (ssl_error) { case SSL_ERROR_WANT_READ: commSetSelect(fd, COMM_SELECT_READ, private_fwdNegotiateSSL, s, 0); return; case SSL_ERROR_WANT_WRITE: commSetSelect(fd, COMM_SELECT_WRITE, private_fwdNegotiateSSL,s, 0); return; default: debug(153, 1) ("private_fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret, errno); cbdataFree(s); comm_close(fd); return ; } } pconnPush(fd,s->ip_addr,s->port,NULL,NULL,0); commSetTimeout(fd,s->pconn_timeout,NULL,NULL); debug(153, 4) ("private_fwdNegotiateSSL: succeed negotiating SSL connection on FD:%d \n",fd); return; }
void icmpOpen(void) { #if USE_ICMP const char *args[2]; int rfd; int wfd; args[0] = "(pinger)"; args[1] = NULL; pid = ipcCreate(IPC_DGRAM, Config.Program.pinger, args, "Pinger Socket", &rfd, &wfd, &hIpc); if (pid < 0) return; assert(rfd == wfd); icmp_sock = rfd; fd_note(icmp_sock, "pinger"); commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); commSetTimeout(icmp_sock, -1, NULL, NULL); debug(37, 1) ("Pinger socket opened on FD %d\n", icmp_sock); #endif }
static void private_openAnIdleConn(char* server_ip,int server_port , struct in_addr outgoing , unsigned short tos, int ctimeout,FwdState *fwdState) { int fd = comm_openex(SOCK_STREAM,IPPROTO_TCP,outgoing,0,COMM_NONBLOCKING,tos,server_ip); if (fd < 0) { debug(151, 4) ("private_openAnIdleConn: %s\n", xstrerror()); return; } // debug(151,3)("mod_server_persist_connections-->private_openAnIdleConn: openIdleConn fd == %d,timeout:%d\n",fd,ctimeout); server *s = cbdataAlloc(server); s->ip_addr = xstrdup(server_ip); s->port = server_port; s->proto = fwdState->request->protocol; s->pconn_timeout=ctimeout; commSetTimeout(fd,ctimeout,fwdConnectIdleTimeout,s); /* if(ctimeout>36000) commSetTcpKeepalive(fd, 3600, ctimeout/36000, ctimeout); else commSetTcpKeepalive(fd, 3600, 100, 360000); */ commSetTcpKeepalive(fd, 1000, 10000, 360000); commConnectStart(fd, server_ip, server_port, private_openIdleConnDone, s); }
static void sslProxyConnected(int fd, void *data) { SslStateData *sslState = data; MemBuf mb; HttpHeader hdr_out; Packer p; http_state_flags flags; debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); memset(&flags, '\0', sizeof(flags)); memBufDefInit(&mb); memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); httpBuildRequestHeader(sslState->request, sslState->request, NULL, /* StoreEntry */ &hdr_out, sslState->client.fd, flags); /* flags */ packerToMemInit(&p, &mb); httpHeaderPackInto(&hdr_out, &p); httpHeaderClean(&hdr_out); packerClean(&p); memBufAppend(&mb, "\r\n", 2); xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF); debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf); sslState->client.len = mb.size; memBufClean(&mb); commSetTimeout(sslState->server.fd, Config.Timeout.read, sslTimeout, sslState); sslSetSelect(sslState); }
static void identConnectDone(int fd, int status, void *data) { IdentStateData *state = data; IdentClient *c; MemBuf mb; if (status != COMM_OK) { /* Failed to connect */ comm_close(fd); return; } /* * see if our clients still care */ for (c = state->clients; c; c = c->next) { if (cbdataValid(c->callback_data)) break; } if (c == NULL) { /* no clients care */ comm_close(fd); return; } memBufDefInit(&mb); memBufPrintf(&mb, "%d, %d\r\n", ntohs(state->my_peer.sin_port), ntohs(state->me.sin_port)); comm_write_mbuf(fd, mb, NULL, state); commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); }
void icmpOpen(void) { #if USE_ICMP char *args[2]; int x; int rfd; int wfd; args[0] = "(pinger)"; args[1] = NULL; x = ipcCreate(IPC_UDP_SOCKET, Config.Program.pinger, args, "Pinger Socket", &rfd, &wfd); if (x < 0) return; assert(rfd == wfd); icmp_sock = rfd; commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); commSetTimeout(icmp_sock, -1, NULL, NULL); debug(29, 1) ("Pinger socket opened on FD %d\n", icmp_sock); #endif }
/* * peerProbeConnect will be called on dead peers by neighborUp */ static int peerProbeConnect(peer * p) { int fd; time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout : Config.Timeout.peer_connect; int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10; if (p->test_fd != -1) return ret; /* probe already running */ if (squid_curtime - p->stats.last_connect_probe == 0) return ret; /* don't probe to often */ fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL), 0, COMM_NONBLOCKING, p->name); if (fd < 0) return ret; commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p); p->test_fd = fd; p->stats.last_connect_probe = squid_curtime; commConnectStart(p->test_fd, p->host, p->http_port, peerProbeConnectDone, p, NULL); return ret; }
void unlinkdInit(void) { #if USE_UNLINKD int x; char *args[2]; struct timeval slp; args[0] = "(unlinkd)"; args[1] = NULL; #if HAVE_POLL && defined(_SQUID_OSF_) /* pipes and poll() don't get along on DUNIX -DW */ x = ipcCreate(IPC_TCP_SOCKET, #else x = ipcCreate(IPC_FIFO, #endif Config.Program.unlinkd, args, "unlinkd", &unlinkd_rfd, &unlinkd_wfd); if (x < 0) fatal("Failed to create unlinkd subprocess"); slp.tv_sec = 0; slp.tv_usec = 250000; select(0, NULL, NULL, NULL, &slp); fd_note(unlinkd_wfd, "squid -> unlinkd"); fd_note(unlinkd_rfd, "unlinkd -> squid"); commSetTimeout(unlinkd_rfd, -1, NULL, NULL); commSetTimeout(unlinkd_wfd, -1, NULL, NULL); /* * unlinkd_rfd should already be non-blocking because of * ipcCreate. We change unlinkd_wfd to blocking mode because * we never want to lose an unlink request, and we don't have * code to retry if we get EWOULDBLOCK. Unfortunately, we can * do this only for the IPC_FIFO case. */ assert(fd_table[unlinkd_rfd].flags.nonblocking); if (FD_PIPE == fd_table[unlinkd_wfd].type) commUnsetNonBlocking(unlinkd_wfd); debug(12, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd); #else debug(12, 1) ("Unlinkd is disabled\n"); #endif }
void unlinkdInit(void) { const char *args[2]; struct timeval slp; args[0] = "(unlinkd)"; args[1] = NULL; #if (HAVE_POLL && defined(_SQUID_OSF_)) || defined(_SQUID_MSWIN_) /* pipes and poll() don't get along on DUNIX -DW */ /* On Windows select() will fail on a pipe */ pid = ipcCreate(IPC_STREAM, #else /* We currently need to use FIFO.. see below */ pid = ipcCreate(IPC_FIFO, #endif Config.Program.unlinkd, args, "unlinkd", &unlinkd_rfd, &unlinkd_wfd, &hIpc); if (pid < 0) fatal("Failed to create unlinkd subprocess"); slp.tv_sec = 0; slp.tv_usec = 250000; select(0, NULL, NULL, NULL, &slp); fd_note(unlinkd_wfd, "squid -> unlinkd"); fd_note(unlinkd_rfd, "unlinkd -> squid"); commSetTimeout(unlinkd_rfd, -1, NULL, NULL); commSetTimeout(unlinkd_wfd, -1, NULL, NULL); /* * unlinkd_rfd should already be non-blocking because of * ipcCreate. We change unlinkd_wfd to blocking mode because * we never want to lose an unlink request, and we don't have * code to retry if we get EWOULDBLOCK. Unfortunately, we can * do this only for the IPC_FIFO case. */ assert(fd_table[unlinkd_rfd].flags.nonblocking); if (FD_PIPE == fd_table[unlinkd_wfd].type) commUnsetNonBlocking(unlinkd_wfd); debug(2, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd); }
static void set_upperlayer_persist_connection_timeout(FwdState *fwdState,int server_fd) { persist_config *cfg = cc_get_mod_param(fwdState->client_fd,mod); fde *F=&fd_table[fwdState->server_fd]; if(strstr(cfg->server_ips,F->ipaddr) && server_fd >0 ) { commSetTimeout(server_fd,cfg->time_out,NULL,NULL); debug(153, 4) ("set_upperlayer_persist_connection_timeout:update the upperlayer_timeout to %d\n",cfg->time_out); } }
/* * copied from httpReadReply() * * by the time this is called, the ICAP headers have already * been read. */ void icapReadReply(int fd, void *data) { IcapStateData *icap = data; StoreEntry *entry = icap->respmod.entry; const request_t *request = icap->request; int len; debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data); if (icap->flags.no_content && !icap->flags.http_server_eof) { //AI return; } if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; statCounter.syscalls.sock.reads++; len = memBufRead(fd, &icap->chunk_buf); debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len); if (len > 0) { fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.icap.all.kbytes_in, len); commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); if (icap->chunk_buf.size < icap->chunk_buf.capacity) { *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0'; debug(81, 9) ("{%s}\n", icap->chunk_buf.buf); } } if (len <= 0) { debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd); commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0); } else if (entry->mem_obj->inmem_hi == 0) { ErrorState *err; debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd); err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink((request_t *) request); err->xerrno = errno; errorAppendEntry(entry, err); comm_close(fd); } else { debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n", fd); comm_close(fd); } return; } if (icapReadReply2(icap) < 0) comm_close(fd); }
/* * start a TCP connection to the peer host on port 113 */ void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) { IdentStateData *state; int fd; char key1[IDENT_KEY_SZ]; char key2[IDENT_KEY_SZ]; char key[IDENT_KEY_SZ]; snprintf(key1, IDENT_KEY_SZ, "%s:%d", inet_ntoa(me->sin_addr), ntohs(me->sin_port)); snprintf(key2, IDENT_KEY_SZ, "%s:%d", inet_ntoa(my_peer->sin_addr), ntohs(my_peer->sin_port)); snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); if ((state = hash_lookup(ident_hash, key)) != NULL) { identClientAdd(state, callback, data); return; } fd = comm_open(SOCK_STREAM, IPPROTO_TCP, me->sin_addr, 0, COMM_NONBLOCKING, "ident"); if (fd == COMM_ERROR) { /* Failed to get a local socket */ callback(NULL, data); return; } CBDATA_INIT_TYPE(IdentStateData); state = cbdataAlloc(IdentStateData); state->hash.key = xstrdup(key); state->fd = fd; state->me = *me; state->my_peer = *my_peer; identClientAdd(state, callback, data); hash_join(ident_hash, &state->hash); comm_add_close_handler(fd, identClose, state); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); commConnectStart(fd, inet_ntoa(state->my_peer.sin_addr), IDENT_PORT, identConnectDone, state); }
static void private_openIdleConnDone(int fd,int status, void* data) { server* s = data; debug(151,3)("mod_server_persist_connections-->private_openIdleConnDone: ip_addr == %s \t port == %d, fd == %d\n",s->ip_addr, s->port,fd); if(fd>0) { if(s->proto == PROTO_HTTPS) { private_fwdInitiateSSL(fd,s); }else{ pconnPush(fd,s->ip_addr,s->port,NULL,NULL,0); commSetTimeout(fd,s->pconn_timeout,NULL,NULL); cbdataFree(s); //Does fwdConnectIdleTimeOut will free!!! } } }
/* This will be called when data is ready to be read from fd. Read until * error or connection closed. */ static void gopherReadReply(int fd, void *data) { GopherStateData *gopherState = data; StoreEntry *entry = gopherState->entry; char *buf = NULL; int len; int clen; int bin; size_t read_sz; #if DELAY_POOLS delay_id delay_id; #endif if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; buf = memAllocate(MEM_4K_BUF); read_sz = 4096 - 1; /* leave room for termination */ #if DELAY_POOLS delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif /* leave one space for \0 in gopherToHTML */ statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, read_sz); if (len > 0) { fd_bytes(fd, len, FD_READ); #if DELAY_POOLS delayBytesIn(delay_id, len); #endif kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.other.kbytes_in, len); } debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, len); if (len > 0) { commSetTimeout(fd, Config.Timeout.read, NULL, NULL); IOStats.Gopher.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Gopher.read_hist[bin]++; }
int pconnPop(const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port, int *idle) { struct _pconn *p; hash_link *hptr; int fd = -1; assert(table != NULL); hptr = pconnLookup(host, port, domain, client_address, client_port); if (hptr != NULL) { p = (struct _pconn *) hptr; assert(p->nfds > 0); fd = p->fds[p->nfds - 1]; if (idle) *idle = p->nfds - 1; pconnRemoveFD(p, fd); commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); commSetTimeout(fd, -1, NULL, NULL); } return fd; }
void whoisStart(FwdState * fwd) { WhoisState *p; int fd = fwd->server_fd; char *buf; size_t l; CBDATA_INIT_TYPE(WhoisState); p = cbdataAlloc(WhoisState); p->request = fwd->request; p->entry = fwd->entry; p->fwd = fwd; storeLockObject(p->entry); comm_add_close_handler(fd, whoisClose, p); l = strLen(p->request->urlpath) + 3; buf = xmalloc(l); snprintf(buf, l, "%s\r\n", strBuf(p->request->urlpath) + 1); comm_write(fd, buf, strlen(buf), NULL, p, xfree); commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, 0); commSetTimeout(fd, Config.Timeout.read, whoisTimeout, p); }
/* This will be called when data is ready to be read from fd. Read until * error or connection closed. */ static void waisReadReply(int fd, void *data) { WaisStateData *waisState = data; LOCAL_ARRAY(char, buf, 4096); StoreEntry *entry = waisState->entry; int len; int clen; int bin; size_t read_sz; #if DELAY_POOLS delay_id delay_id; #endif if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; read_sz = 4096; #if DELAY_POOLS delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, read_sz); if (len > 0) { fd_bytes(fd, len, FD_READ); #if DELAY_POOLS delayBytesIn(delay_id, len); #endif kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.other.kbytes_in, len); } debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, len); if (len > 0) { commSetTimeout(fd, Config.Timeout.read, NULL, NULL); IOStats.Wais.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Wais.read_hist[bin]++; }
/* * icapRespModKeepAliveOrClose * * Called when we are done reading from the ICAP server. * Either close the connection or keep it open for a future * transaction. */ static void icapRespModKeepAliveOrClose(IcapStateData * icap) { int fd = icap->icap_fd; if (fd < 0) return; if (!icap->flags.keep_alive) { debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__, __LINE__); comm_close(fd); return; } debug(81, 3) ("%s:%d FD %d looks good, keeping alive\n", __FILE__, __LINE__, fd); commSetDefer(fd, NULL, NULL); commSetTimeout(fd, -1, NULL, NULL); commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); comm_remove_close_handler(fd, icapStateFree, icap); pconnPush(fd, icap->current_service->hostname, icap->current_service->port); icap->icap_fd = -1; icapStateFree(-1, icap); }
void pconnPush(int fd, const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port) { struct _pconn *p; int *old; LOCAL_ARRAY(char, desc, FD_DESC_SZ); LOCAL_ARRAY(char, key, PCONN_KEYLEN); if (fdUsageHigh()) { debug(48, 3) ("pconnPush: Not many unused FDs\n"); comm_close(fd); return; } else if (shutting_down) { comm_close(fd); return; } assert(table != NULL); pconnKey(key, host, port, domain, client_address, client_port); p = (struct _pconn *) hash_lookup(table, key); if (p == NULL) p = pconnNew(key); if (p->nfds == p->nfds_alloc) { debug(48, 3) ("pconnPush: growing FD array\n"); p->nfds_alloc <<= 1; old = p->fds; p->fds = xmalloc(p->nfds_alloc * sizeof(int)); xmemcpy(p->fds, old, p->nfds * sizeof(int)); if (p->nfds == PCONN_FDS_SZ) memPoolFree(pconn_fds_pool, old); else xfree(old); } p->fds[p->nfds++] = fd; commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0); commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); snprintf(desc, FD_DESC_SZ, "%s idle connection", host); fd_note(fd, desc); debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); }
static void sslConnectDone(int fdnotused, int status, void *data) { SslStateData *sslState = data; request_t *request = sslState->request; ErrorState *err = NULL; if (status == COMM_ERR_DNS) { debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); err->request = requestLink(request); err->dnsserver_msg = xstrdup(dns_error_message); err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); } else if (status != COMM_OK) { err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); err->xerrno = errno; err->host = xstrdup(sslState->host); err->port = sslState->port; err->request = requestLink(request); err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); } else { if (sslState->servers->peer) sslProxyConnected(sslState->server.fd, sslState); else sslConnected(sslState->server.fd, sslState); commSetTimeout(sslState->server.fd, Config.Timeout.read, sslTimeout, sslState); #if DELAY_POOLS commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); #endif } }
void icapSendRespMod(IcapStateData * icap, char *buf, int len, int theEnd) { MemBuf mb; #if ICAP_PREVIEW int size; const int preview_size = icap->preview_size; #endif debug(81, 5) ("icapSendRespMod: FD %d, len %d, theEnd %d\n", icap->icap_fd, len, theEnd); if (icap->flags.no_content) { /* * ICAP server said there are no modifications to make, so * just append this data to the StoreEntry */ if (icap->respmod.resp_copy.size) { /* * first copy the data that we already sent to the ICAP server */ memBufAppend(&icap->chunk_buf, icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size); icap->respmod.resp_copy.size = 0; } debug(81, 5) ("icapSendRepMod: len=%d theEnd=%d write_pending=%d\n", len, theEnd, icap->flags.write_pending); if (len) { /* * also copy any new data from the HTTP side */ memBufAppend(&icap->chunk_buf, buf, len); } (void) icapReadReply2(icap); return; } if (theEnd) { if (icap->respmod.res_body_sz) icap->flags.send_zero_chunk = 1; icap->flags.http_server_eof = 1; } /* * httpReadReply is going to call us with a chunk and then * right away again with an EOF if httpPconnTransferDone() is true. * Since the first write is already dispatched, we'll have to * hack this in somehow. */ if (icap->flags.write_pending) { debug(81, 3) ("icapSendRespMod: oops, write_pending=1\n"); assert(theEnd); assert(len == 0); return; } if (!cbdataValid(icap)) { debug(81, 3) ("icapSendRespMod: failed to establish connection?\n"); return; } memBufDefInit(&mb); #if SUPPORT_ICAP_204 || ICAP_PREVIEW /* * make a copy of the response in case ICAP server gives us a 204 */ /* * This piece of code is problematic for 204 responces outside preview. * The icap->respmod.resp_copy continues to filled until we had responce * If the icap server waits to gets all data before sends its responce * then we are puting all downloading object to the main system memory. * My opinion is that 204 responces outside preview must be disabled ..... * /chtsanti */ if (len && icap->flags.copy_response) { if (memBufIsNull(&icap->respmod.resp_copy)) memBufDefInit(&icap->respmod.resp_copy); memBufAppend(&icap->respmod.resp_copy, buf, len); } #endif if (icap->sc == 0) { /* No data sent yet. Start with headers */ if((icap->sc = buildRespModHeader(&mb, icap, buf, len, theEnd))>0){ buf += icap->sc; len -= icap->sc; } /* * Then we do not have http responce headers. All data (previous and those in buf) * now are exist to icap->respmod.req_hdr_copy. Lets get them back....... */ if(icap->sc <0){ memBufAppend(&icap->respmod.buffer, icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size); icap->sc=icap->respmod.req_hdr_copy.size; icap->respmod.req_hdr_copy.size=0; buf=NULL; len=0; } } if (0 == icap->sc) { /* check again; bail if we're not ready to send ICAP/HTTP hdrs */ debug(81, 5) ("icapSendRespMod: dont have full HTTP response hdrs\n"); memBufClean(&mb); return; } #if ICAP_PREVIEW if (preview_size < 0 || !Config.icapcfg.preview_enable) /* preview feature off */ icap->flags.preview_done = 1; if (!icap->flags.preview_done) { /* preview not yet sent */ if (icap->sc > 0 && icap->respmod.buffer.size <= preview_size && len > 0) { /* Try to collect at least preview_size+1 bytes */ /* By collecting one more byte than needed for preview we know best */ /* whether we have to send the ieof chunk extension */ size = icap->respmod.buffer.size + len; if (size > preview_size + 1) size = preview_size + 1; size -= icap->respmod.buffer.size; debug(81, 3) ("icapSendRespMod: FD %d: copy %d more bytes to preview buffer.\n", icap->icap_fd, size); memBufAppend(&icap->respmod.buffer, buf, size); buf = ((char *) buf) + size; len -= size; } if (icap->respmod.buffer.size > preview_size || theEnd) { /* we got enough bytes for preview or this is the last call */ /* add preview preview now */ if (icap->respmod.buffer.size > 0) { size = icap->respmod.buffer.size; if (size > preview_size) size = preview_size; memBufPrintf(&mb, "%x\r\n", size); memBufAppend(&mb, icap->respmod.buffer.buf, size); memBufAppend(&mb, crlf, 2); icap->sc += size; } if (icap->respmod.buffer.size <= preview_size) { /* content length is less than preview size+1 */ if (icap->respmod.res_body_sz) memBufAppend(&mb, "0; ieof\r\n\r\n", 11); memBufReset(&icap->respmod.buffer); /* will now be used for other data */ } else { char ch; memBufAppend(&mb, "0\r\n\r\n", 5); /* end of preview, wait for continue or 204 signal */ /* copy the extra byte and all other data to the icap buffer */ /* so that it can be handled next time */ ch = icap->respmod.buffer.buf[preview_size]; memBufReset(&icap->respmod.buffer); /* will now be used for other data */ memBufAppend(&icap->respmod.buffer, &ch, 1); debug(81, 3) ("icapSendRespMod: FD %d: sending preview and keeping %d bytes in internal buf.\n", icap->icap_fd, len + 1); if (len > 0) memBufAppend(&icap->respmod.buffer, buf, len); } icap->flags.preview_done = 1; icap->flags.wait_for_preview_reply = 1; } } else if (icap->flags.wait_for_preview_reply) { /* received new data while waiting for preview response */ /* add data to internal buffer and send later */ debug(81, 3) ("icapSendRespMod: FD %d: add %d more bytes to internal buf while waiting for preview-response.\n", icap->icap_fd, len); if (len > 0) memBufAppend(&icap->respmod.buffer, buf, len); /* do not send any data now while waiting for preview response */ /* but prepare for read more data on the HTTP connection */ memBufClean(&mb); return; } else #endif { /* after preview completed and ICAP preview response received */ /* there may still be some data in the buffer */ if (icap->respmod.buffer.size > 0) { memBufPrintf(&mb, "%x\r\n", icap->respmod.buffer.size); memBufAppend(&mb, icap->respmod.buffer.buf, icap->respmod.buffer.size); memBufAppend(&mb, crlf, 2); icap->sc += icap->respmod.buffer.size; memBufReset(&icap->respmod.buffer); } if (len > 0) { memBufPrintf(&mb, "%x\r\n", len); memBufAppend(&mb, buf, len); memBufAppend(&mb, crlf, 2); icap->sc += len; } if (icap->flags.send_zero_chunk) { /* send zero end chunk */ icap->flags.send_zero_chunk = 0; icap->flags.http_server_eof = 1; memBufAppend(&mb, "0\r\n\r\n", 5); } /* wait for data coming from ICAP server as soon as we sent something */ /* but of course only until we got the response header */ if (!icap->flags.got_reply) icap->flags.wait_for_reply = 1; } commSetTimeout(icap->icap_fd, -1, NULL, NULL); if (!mb.size) { memBufClean(&mb); return; } debug(81, 5) ("icapSendRespMod: FD %d writing {%s}\n", icap->icap_fd, mb.buf); icap->flags.write_pending = 1; comm_write_mbuf(icap->icap_fd, mb, icapSendRespModDone, icap); }
static void icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag, void *data) { IcapStateData *icap = data; ErrorState *err; icap->flags.write_pending = 0; debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n", fd, size, errflag); if (size > 0) { fd_bytes(fd, size, FD_WRITE); kb_incr(&statCounter.icap.all.kbytes_out, size); } if (errflag == COMM_ERR_CLOSING) return; if (errflag) { err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; if (cbdataValid(icap)) err->request = requestLink(icap->request); storeEntryReset(icap->respmod.entry); errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; } if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) { debug(81, 3) ("icapSendRespModDone: Entry Aborded\n"); comm_close(fd); return; } if (icap->flags.send_zero_chunk) { debug(81, 3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n"); icap->flags.send_zero_chunk = 0; icapSendRespMod(icap, NULL, 0, 1); return; } if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) { /* Schedule reading the ICAP response */ debug(81, 3) ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n", fd); commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0); #if 1 commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); #else if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) { /* * Set the read timeout only after all data has been sent * or we are waiting for a preview response * If the ICAP server does not return any data till all data * has been sent, we are likely to hit the timeout for large * HTTP bodies */ commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); } #endif } }
int ipcCreate(int type, const char *prog, char *const args[], const char *name, int *rfd, int *wfd) { pid_t pid; struct sockaddr_in CS; struct sockaddr_in PS; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; int fd; int t1, t2, t3; socklen_t len; int tmp_s; #if HAVE_PUTENV char *env_str; #endif int x; #if HAVE_POLL && defined(_SQUID_OSF_) assert(type != IPC_FIFO); #endif if (rfd) *rfd = -1; if (wfd) *wfd = -1; if (type == IPC_TCP_SOCKET) { crfd = cwfd = comm_open(SOCK_STREAM, 0, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, 0, /* protocol */ local_addr, 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, 0, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, 0, local_addr, 0, 0, name); } else if (type == IPC_FIFO) { int p2c[2]; int c2p[2]; if (pipe(p2c) < 0) { debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); return -1; } if (pipe(c2p) < 0) { debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); return -1; } fd_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read"); fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write"); fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read"); fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write"); } else { assert(IPC_NONE); } debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); if (crfd < 0) { debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pwfd < 0) { debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { len = sizeof(PS); memset(&PS, '\0', len); if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port)); len = sizeof(CS); memset(&CS, '\0', len); if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port)); } if (type == IPC_TCP_SOCKET) { if (listen(crfd, 1) < 0) { debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); } /* flush or else we get dup data if unbuffered_logs is set */ logsFlush(); if ((pid = fork()) < 0) { debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pid > 0) { /* parent */ /* close shared socket with child */ comm_close(crfd); if (cwfd != crfd) comm_close(cwfd); cwfd = crfd = -1; if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } memset(hello_buf, '\0', HELLO_BUF_SZ); if (type == IPC_UDP_SOCKET) x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); else x = read(prfd, hello_buf, HELLO_BUF_SZ - 1); if (x < 0) { debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(50, 0) ("--> read: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } else if (strcmp(hello_buf, hello_string)) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } commSetTimeout(prfd, -1, NULL, NULL); commSetNonBlocking(prfd); commSetNonBlocking(pwfd); if (rfd) *rfd = prfd; if (wfd) *wfd = pwfd; fd_table[prfd].flags.ipc = 1; fd_table[pwfd].flags.ipc = 1; return pwfd; } /* child */ no_suid(); /* give up extra priviliges */ /* close shared socket with parent */ close(prfd); if (pwfd != prfd) close(pwfd); pwfd = prfd = -1; if (type == IPC_TCP_SOCKET) { debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); if ((fd = accept(crfd, NULL, NULL)) < 0) { debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); _exit(1); } debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); close(crfd); cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { if (comm_connect_addr(crfd, &PS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_UDP_SOCKET) { x = send(cwfd, hello_string, strlen(hello_string), 0); if (x < 0) { debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); _exit(1); } } else { if (write(cwfd, hello_string, strlen(hello_string)) < 0) { debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror()); debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); _exit(1); } } #if HAVE_PUTENV env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); putenv(env_str); #endif /* * This double-dup stuff avoids problems when one of * crfd, cwfd, or debug_log are in the rage 0-2. */ do { x = open(_PATH_DEVNULL, 0, 0444); if (x > -1) commSetCloseOnExec(x); } while (x < 3); t1 = dup(crfd); t2 = dup(cwfd); t3 = dup(fileno(debug_log)); assert(t1 > 2 && t2 > 2 && t3 > 2); close(crfd); close(cwfd); close(fileno(debug_log)); dup2(t1, 0); dup2(t2, 1); dup2(t3, 2); close(t1); close(t2); close(t3); #if HAVE_SETSID setsid(); #endif execvp(prog, args); debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); _exit(1); return 0; }
static void clientRecvFd(int sock, void *data) { int retval; struct msghdr msg; struct iovec vec; char cmsgbuf[CMSG_SPACE(sizeof(int))]; struct cmsghdr *p_cmsg; char iov_buf[CACHE_WATCH_RECV_MSG_LENGTH]; vec.iov_base = iov_buf; vec.iov_len = CACHE_WATCH_RECV_MSG_LENGTH; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); msg.msg_flags = 0; /* In case something goes wrong, set the fd to -1 before the syscall */ retval = recvmsg(sock, &msg, 0); if( retval <= 0 ) { comm_close(sock); return; } if( (p_cmsg = CMSG_FIRSTHDR(&msg)) == NULL ) { comm_close(sock); return; } if (squidWatchReply(sock, &msg, iov_buf) != -1) { comm_close(sock); return; } int fd = *((int*)CMSG_DATA(p_cmsg)); // for keep alive commSetSelect(sock, COMM_SELECT_READ, clientRecvFd, NULL, 0); // omm_close(sock); if(fd < 0) { return; } //comm_accept's jobs struct sockaddr_in peername; struct sockaddr_in sockname; socklen_t socklen; socklen = sizeof(struct sockaddr_in); memset(&peername, '\0', socklen); memset(&sockname, '\0', socklen); getpeername(fd, (struct sockaddr *)&peername, &socklen); getsockname(fd, (struct sockaddr *)&sockname, &socklen); commSetCloseOnExec(fd); fd_open(fd, FD_SOCKET, "HTTP Request"); fde *F = &fd_table[fd]; xstrncpy(F->ipaddr, xinet_ntoa(peername.sin_addr), 16); F->remote_port = htons(peername.sin_port); F->local_port = htons(sockname.sin_port); commSetNonBlocking(fd); //rest of httpAccept's jobs // //int on = 1; //if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) // debug(191, 0) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror()); //fd_table[fd].flags.nodelay = 1; #ifdef TCP_NODELAY commSetTcpNoDelay(fd); /*Fix tcp use Negale bug while send packet*/ #endif #ifdef CC_FRAMEWORK cc_call_hook_func_private_http_accept(fd); #endif debug(191, 4) ("clientRecvFd: FD %d: accepted port %d client %s:%d\n", fd, F->local_port, F->ipaddr, F->remote_port); fd_note_static(fd, "client http connect"); ConnStateData * connState = cbdataAlloc(ConnStateData); assert(Config.Sockaddr.http); connState->port = Config.Sockaddr.http; cbdataLock(connState->port); connState->peer = peername; connState->log_addr = peername.sin_addr; connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; connState->me = sockname; connState->fd = fd; connState->pinning.fd = -1; connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(peername.sin_addr, FQDN_LOOKUP_IF_MISS); commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); #if USE_IDENT static aclCheck_t identChecklist; identChecklist.src_addr = peername.sin_addr; identChecklist.my_addr = sockname.sin_addr; identChecklist.my_port = ntohs(sockname.sin_port); if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) identStart(&sockname, &peername, clientIdentDone, connState); #endif commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0); commSetDefer(fd, clientReadDefer, connState); if (connState->port->tcp_keepalive.enabled) { commSetTcpKeepalive(fd, connState->port->tcp_keepalive.idle, connState->port->tcp_keepalive.interval, connState->port->tcp_keepalive.timeout); } clientdbEstablished(peername.sin_addr, 1); incoming_sockets_accepted++; }
pid_t ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) { unsigned long thread; struct ipc_params params; int opt; int optlen = sizeof(opt); DWORD ecode = 0; pid_t pid; struct sockaddr_in CS; struct sockaddr_in PS; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; socklen_t len; int x; requirePathnameExists(name, prog); if (rfd) *rfd = -1; if (wfd) *wfd = -1; if (hIpc) *hIpc = NULL; if (WIN32_OS_version != _WIN_OS_WINNT) { getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT); setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt)); } if (type == IPC_TCP_SOCKET) { crfd = cwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, /* protocol */ local_addr, 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, name); } else if (type == IPC_FIFO) { debug(54, 0) ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n", prog); assert(0); } else { assert(IPC_NONE); } debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); if (WIN32_OS_version != _WIN_OS_WINNT) { getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); opt = opt | SO_SYNCHRONOUS_NONALERT; setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen); } if (crfd < 0) { debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pwfd < 0) { debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { len = sizeof(PS); memset(&PS, '\0', len); if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port)); len = sizeof(CS); memset(&CS, '\0', len); if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port)); } if (type == IPC_TCP_SOCKET) { if (listen(crfd, 1) < 0) { debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); } /* flush or else we get dup data if unbuffered_logs is set */ logsFlush(); params.type = type; params.crfd = crfd; params.cwfd = cwfd; params.PS = PS; params.prog = prog; params.args = (char **) args; thread = _beginthreadex(NULL, 0, ipc_thread_1, ¶ms, 0, NULL); if (thread == 0) { debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) { CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } memset(hello_buf, '\0', HELLO_BUF_SZ); x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } else if (strcmp(hello_buf, hello_string)) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } x = send(pwfd, ok_string, strlen(ok_string), 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } memset(hello_buf, '\0', HELLO_BUF_SZ); x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } else if (!strcmp(hello_buf, err_string)) { debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } hello_buf[x] = '\0'; pid = atol(hello_buf); commSetTimeout(prfd, -1, NULL, NULL); commSetNonBlocking(prfd); commSetNonBlocking(pwfd); commSetCloseOnExec(prfd); commSetCloseOnExec(pwfd); if (rfd) *rfd = prfd; if (wfd) *wfd = pwfd; fd_table[prfd].flags.ipc = 1; fd_table[pwfd].flags.ipc = 1; fd_table[crfd].flags.ipc = 1; fd_table[cwfd].flags.ipc = 1; if (Config.sleep_after_fork) { /* XXX emulation of usleep() */ DWORD sl; sl = Config.sleep_after_fork / 1000; if (sl == 0) sl = 1; Sleep(sl); } if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) { if (hIpc) *hIpc = (HANDLE) thread; return pid; } else { CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } }
void sslStart(int fd, const char *url, request_t * request, size_t * size_ptr) { /* Create state structure. */ SslStateData *sslState = NULL; int sock; ErrorState *err = NULL; debug(26, 3) ("sslStart: '%s %s'\n", RequestMethodStr[request->method], url); Counter.server.all.requests++; Counter.server.other.requests++; /* Create socket. */ sock = comm_open(SOCK_STREAM, 0, Config.Addrs.tcp_outgoing, 0, COMM_NONBLOCKING, url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(request); errorSend(fd, err); return; } sslState = xcalloc(1, sizeof(SslStateData)); cbdataAdd(sslState, cbdataXfree, 0); #if DELAY_POOLS sslState->delay_id = delayClient(request); delayRegisterDelayIdPtr(&sslState->delay_id); #endif sslState->url = xstrdup(url); sslState->request = requestLink(request); sslState->size_ptr = size_ptr; sslState->client.fd = fd; sslState->server.fd = sock; sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF); sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); comm_add_close_handler(sslState->server.fd, sslServerClosed, sslState); comm_add_close_handler(sslState->client.fd, sslClientClosed, sslState); commSetTimeout(sslState->client.fd, Config.Timeout.lifetime, sslTimeout, sslState); commSetTimeout(sslState->server.fd, Config.Timeout.connect, sslTimeout, sslState); peerSelect(request, NULL, sslPeerSelectComplete, sslState); /* * Disable the client read handler until peer selection is complete * Take control away from client_side.c. */ commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); }