/*! * Send socket port that matches dpi_id to client */ void send_sockport(int sock_fd, char *dpi_tag, struct dp *dpi_attr_list) { int i; char *dpi_id, *d_cmd, port_str[16]; struct service *serv; dReturn_if_fail((dpi_id = get_message(sock_fd, dpi_tag)) != NULL); serv = dList_find_custom(services_list,dpi_id,(dCompareFunc)service_match); if (serv == NULL || (i = serv->dp_index) == -1) for (i = 0; i < numdpis; i++) if (!strncmp(dpi_attr_list[i].id, dpi_id, dpi_attr_list[i].id - strchr(dpi_attr_list[i].id, '.'))) break; if (i < numdpis) { /* found */ snprintf(port_str, 8, "%d", dpi_attr_list[i].port); d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "send_data", port_str); (void) CKD_WRITE(sock_fd, d_cmd); dFree(d_cmd); } dFree(dpi_id); }
/* * CCC function for the HTTP module */ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2) { int SKey = VOIDP2INT(Info->LocalKey); (void)Data2; /* suppress unused parameter warning */ dReturn_if_fail( a_Chain_check("a_Http_ccc", Op, Branch, Dir, Info) ); if (Branch == 1) { if (Dir == BCK) { /* HTTP query branch */ switch (Op) { case OpStart: /* ( Data1 = Web ) */ SKey = Http_sock_new(); Info->LocalKey = INT2VOIDP(SKey); /* link IO */ a_Chain_link_new(Info, a_Http_ccc, BCK, a_IO_ccc, 1, 1); a_Chain_bcb(OpStart, Info, NULL, NULL); /* async. connection */ Http_get(Info, Data1); break; case OpEnd: /* finished the HTTP query branch */ a_Chain_bcb(OpEnd, Info, NULL, NULL); Http_socket_free(SKey); dFree(Info); break; case OpAbort: /* something bad happened... */ a_Chain_bcb(OpAbort, Info, NULL, NULL); Http_socket_free(SKey); dFree(Info); break; } } else { /* 1 FWD */ /* HTTP send-query status branch */ switch (Op) { default: MSG_WARN("Unused CCC\n"); break; } } } }
/* * Receive new data, update the reception buffer (for next read), update the * cache, and service the client queue. * * This function gets called whenever the IO has new data. * 'Op' is the operation to perform * 'VPtr' is a (void) pointer to the IO control structure */ void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, const DilloUrl *Url) { int offset, len; const char *str; Dstr *dstr1, *dstr2, *dstr3; CacheEntry_t *entry = Cache_entry_search(Url); /* Assert a valid entry (not aborted) */ dReturn_if_fail (entry != NULL); _MSG("__a_Cache_process_dbuf__\n"); if (Op == IORead) { /* * Cache_get_header() will set CA_GotHeader if it has a full header, and * Cache_parse_header() will unset it if the header ends being * merely an informational response from the server (i.e., 100 Continue) */ for (offset = 0; !(entry->Flags & CA_GotHeader) && (len = Cache_get_header(entry, buf + offset, buf_size - offset)); Cache_parse_header(entry) ) { offset += len; } if (entry->Flags & CA_GotHeader) { str = buf + offset; len = buf_size - offset; entry->TransferSize += len; dstr1 = dstr2 = dstr3 = NULL; /* Decode arrived data (<= 3 stages) */ if (entry->TransferDecoder) { dstr1 = a_Decode_process(entry->TransferDecoder, str, len); str = dstr1->str; len = dstr1->len; } if (entry->ContentDecoder) { dstr2 = a_Decode_process(entry->ContentDecoder, str, len); str = dstr2->str; len = dstr2->len; } dStr_append_l(entry->Data, str, len); if (entry->CharsetDecoder && entry->UTF8Data) { dstr3 = a_Decode_process(entry->CharsetDecoder, str, len); dStr_append_l(entry->UTF8Data, dstr3->str, dstr3->len); } dStr_free(dstr1, 1); dStr_free(dstr2, 1); dStr_free(dstr3, 1); if (entry->Data->len) entry->Flags &= ~CA_IsEmpty; entry = Cache_process_queue(entry); } } else if (Op == IOClose) { if ((entry->ExpectedSize || entry->TransferSize) && entry->TypeHdr == NULL) { MSG_HTTP("Message with a body lacked Content-Type header.\n"); } if ((entry->Flags & CA_GotLength) && (entry->ExpectedSize != entry->TransferSize)) { MSG_HTTP("Content-Length does NOT match message body,\n" " at: %s\n", URL_STR_(entry->Url)); MSG("entry->ExpectedSize = %d, entry->TransferSize = %d\n", entry->ExpectedSize, entry->TransferSize); } if (!entry->TransferSize && !(entry->Flags & CA_Redirect) && (entry->Flags & WEB_RootUrl)) { char *eol = strchr(entry->Header->str, '\n'); if (eol) { char *status_line = dStrndup(entry->Header->str, eol - entry->Header->str); MSG_HTTP("Body was empty. Server sent status: %s\n", status_line); dFree(status_line); } } entry->Flags |= CA_GotData; entry->Flags &= ~CA_Stopped; /* it may catch up! */ if (entry->TransferDecoder) { a_Decode_free(entry->TransferDecoder); entry->TransferDecoder = NULL; } if (entry->ContentDecoder) { a_Decode_free(entry->ContentDecoder); entry->ContentDecoder = NULL; } dStr_fit(entry->Data); /* fit buffer size! */ if ((entry = Cache_process_queue(entry))) { if (entry->Flags & CA_GotHeader) { Cache_unref_data(entry); } } } else if (Op == IOAbort) { /* unused */ MSG("a_Cache_process_dbuf Op = IOAbort; not implemented!\n"); } }
/* * Set a bit */ void a_Bitvec_set_bit(bitvec_t *bvec, int pos) { dReturn_if_fail (pos < bvec->len); bvec->vec[pos/BVEC_SIZE] |= 1 << (pos % BVEC_SIZE); }
/* * CCC function for the CAPI module */ void a_Capi_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2) { capi_conn_t *conn; dReturn_if_fail( a_Chain_check("a_Capi_ccc", Op, Branch, Dir, Info) ); if (Branch == 1) { if (Dir == BCK) { /* Command sending branch */ switch (Op) { case OpStart: /* Data1 = conn; Data2 = {Web | server} */ conn = Data1; Capi_conn_ref(conn); Info->LocalKey = conn; conn->InfoSend = Info; if (strcmp(conn->server, "http") == 0) { a_Chain_link_new(Info, a_Capi_ccc, BCK, a_Http_ccc, 1, 1); a_Chain_bcb(OpStart, Info, Data2, NULL); } else { a_Chain_link_new(Info, a_Capi_ccc, BCK, a_Dpi_ccc, 1, 1); a_Chain_bcb(OpStart, Info, Data2, NULL); } break; case OpSend: /* Data1 = dbuf */ a_Chain_bcb(OpSend, Info, Data1, NULL); break; case OpEnd: conn = Info->LocalKey; conn->InfoSend = NULL; a_Chain_bcb(OpEnd, Info, NULL, NULL); Capi_conn_unref(conn); dFree(Info); break; case OpAbort: conn = Info->LocalKey; conn->InfoSend = NULL; a_Chain_bcb(OpAbort, Info, NULL, NULL); Capi_conn_unref(conn); dFree(Info); break; default: MSG_WARN("Unused CCC\n"); break; } } else { /* 1 FWD */ /* Command sending branch (status) */ switch (Op) { case OpSend: if (!Data2) { MSG_WARN("Capi.c: Opsend [1F] Data2 = NULL\n"); } else if (strcmp(Data2, "FD") == 0) { conn = Info->LocalKey; conn->SockFD = *(int*)Data1; /* communicate the FD through the answer branch */ a_Capi_ccc(OpSend, 2, BCK, conn->InfoRecv, &conn->SockFD, "FD"); } else if (strcmp(Data2, "DpidOK") == 0) { /* resume pending dpi requests */ Capi_conn_resume(); } break; case OpAbort: conn = Info->LocalKey; conn->InfoSend = NULL; if (Data2) { if (!strcmp(Data2, "DpidERROR")) { a_UIcmd_set_msg(conn->bw, "ERROR: can't start dpid daemon " "(URL scheme = '%s')!", conn->url ? URL_SCHEME(conn->url) : ""); } else if (!strcmp(Data2, "Both") && conn->InfoRecv) { /* abort the other branch too */ a_Capi_ccc(OpAbort, 2, BCK, conn->InfoRecv, NULL, NULL); } } /* if URL == expect-url */ a_Nav_cancel_expect_if_eq(conn->bw, conn->url); /* finish conn */ Capi_conn_unref(conn); dFree(Info); break; default: MSG_WARN("Unused CCC\n"); break; } } } else if (Branch == 2) { if (Dir == BCK) { /* Answer branch */ switch (Op) { case OpStart: /* Data1 = conn; Data2 = {"http" | "<dpi server name>"} */ conn = Data1; Capi_conn_ref(conn); Info->LocalKey = conn; conn->InfoRecv = Info; a_Chain_link_new(Info, a_Capi_ccc, BCK, a_Dpi_ccc, 2, 2); a_Chain_bcb(OpStart, Info, NULL, Data2); break; case OpSend: /* Data1 = FD */ if (Data2 && strcmp(Data2, "FD") == 0) { a_Chain_bcb(OpSend, Info, Data1, Data2); } break; case OpAbort: conn = Info->LocalKey; conn->InfoRecv = NULL; a_Chain_bcb(OpAbort, Info, NULL, NULL); /* remove the cache entry for this URL */ a_Cache_entry_remove_by_url(conn->url); Capi_conn_unref(conn); dFree(Info); break; default: MSG_WARN("Unused CCC\n"); break; } } else { /* 2 FWD */ /* Server listening branch */ switch (Op) { case OpSend: conn = Info->LocalKey; if (strcmp(Data2, "send_page_2eof") == 0) { /* Data1 = dbuf */ DataBuf *dbuf = Data1; a_Cache_process_dbuf(IORead, dbuf->Buf, dbuf->Size, conn->url); } else if (strcmp(Data2, "send_status_message") == 0) { a_UIcmd_set_msg(conn->bw, "%s", Data1); } else if (strcmp(Data2, "chat") == 0) { a_UIcmd_set_msg(conn->bw, "%s", Data1); a_Bookmarks_chat_add(NULL, NULL, Data1); } else if (strcmp(Data2, "dialog") == 0) { a_Dpiapi_dialog(conn->bw, conn->server, Data1); } else if (strcmp(Data2, "reload_request") == 0) { a_Nav_reload(conn->bw); } else if (strcmp(Data2, "start_send_page") == 0) { /* prepare the cache to receive the data stream for this URL * * a_Capi_open_url() already added a new cache entry, * and a client for it. */ } break; case OpEnd: conn = Info->LocalKey; conn->InfoRecv = NULL; a_Cache_process_dbuf(IOClose, NULL, 0, conn->url); if (conn->InfoSend) { /* Propagate OpEnd to the sending branch too */ a_Capi_ccc(OpEnd, 1, BCK, conn->InfoSend, NULL, NULL); } Capi_conn_unref(conn); dFree(Info); break; default: MSG_WARN("Unused CCC\n"); break; } } } }