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); }
/* * Function: errorSend * * Arguments: err - This object is destroyed after use in this function. * * Abstract: This function generates a error page from the info contained * by 'err' and then sends it to the client. * The callback function errorSendComplete() is called after * the page has been written to the client socket (fd). * errorSendComplete() deallocates 'err'. We need to add * 'err' to the cbdata because comm_write() requires it * for all callback data pointers. * * Note, normally errorSend() should only be called from * routines in ssl.c and pass.c, where we don't have any * StoreEntry's. In client_side.c we must allocate a StoreEntry * for errors and use errorAppendEntry() to account for * persistent/pipeline connections. */ void errorSend(int fd, ErrorState * err) { HttpReply *rep; debug(4, 3) ("errorSend: FD %d, err=%p\n", fd, err); assert(fd >= 0); /* * ugh, this is how we make sure error codes get back to * the client side for logging and error tracking. */ if (err->request) err->request->err_type = err->type; /* moved in front of errorBuildBuf @?@ */ err->flags.flag_cbdata = 1; rep = errorBuildReply(err); comm_write_mbuf(fd, httpReplyPack(rep), errorSendComplete, err); httpReplyDestroy(rep); }
static void idnsSendTcpQuery(int fd, int status, void *data) { MemBuf buf; idns_query *q = data; short nsz; if (status != COMM_OK) { int ns = (q->nsends - 1) % nns; debug(78, 1) ("idnsSendTcpQuery: Failed to connect to DNS server %d using TCP\n", ns + 1); idnsTcpCleanup(q); return; } memBufInit(&buf, q->sz + 2, q->sz + 2); nsz = htons(q->sz); memBufAppend(&buf, &nsz, 2); memBufAppend(&buf, q->buf, q->sz); comm_write_mbuf(q->tcp_socket, buf, idnsSendTcpQueryDone, q); }
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); }