bool build_handshake_packet(nabto_connect* con, uint8_t* buffer, size_t bufferLength, size_t* packetLength) { uint8_t* packetPtr; /* * type, 1 bytes * flags, 1 bytes * nsi cp, 4 bytes * nsi sp, 4 bytes * nsi co, 4 bytes * id, 20 bytes */ size_t nonceLength = 38; uint8_t nonce[38]; uint8_t* noncePtr = nonce; packetPtr = insert_header(buffer, con->cpnsi, con->spnsi, NP_PACKET_HDR_TYPE_GW_CONN_U, false, 0, 0, con->consi); //NOTE: These type and flags must match the connection attributes set //in the unabto_tcp_fallback_connect_thread when a connection is //established. WRITE_U8(noncePtr, NP_GW_CONN_U_TYPE_TCP); noncePtr+=1; WRITE_U8(noncePtr, NP_GW_CONN_U_FLAG_RELIABLE); noncePtr+=1; WRITE_U32(noncePtr, con->cpnsi); noncePtr+=4; WRITE_U32(noncePtr, con->spnsi); noncePtr+=4; memcpy(noncePtr, con->consi, 8); noncePtr+=8; memcpy(noncePtr, con->gatewayId, 20); packetPtr = insert_payload(packetPtr, NP_PAYLOAD_TYPE_NONCE, nonce, nonceLength); *packetLength = packetPtr - buffer; insert_length(buffer, *packetLength); return true; }
/* Insert the next line into the parser. Return 0 on success or true on error with errno set appropriately. */ int rfc822parse_insert (rfc822parse_t msg, const unsigned char *line, size_t length) { return (msg->in_body ? insert_body (msg, line, length) : insert_header (msg, line, length)); }
void send_debug_packet_response(nabto_packet_header* header, uint32_t notification) { uint8_t* buf = nabtoCommunicationBuffer; uint8_t* ptr = nabtoCommunicationBuffer; uint8_t* end = nabtoCommunicationBuffer+nabtoCommunicationBufferSize; ptr = insert_header(ptr, header->nsi_cp, header->nsi_sp, U_DEBUG, true, header->seq, 0, NULL); if (ptr == NULL) { NABTO_LOG_ERROR(("Could not insert debug packet header")); return; } ptr = insert_notify_payload(ptr, end, NP_PAYLOAD_NOTIFY_DEBUG_OK); if (ptr == NULL) { NABTO_LOG_ERROR(("Could not insert notify payload")); return; } { uint16_t length = ptr - buf; insert_length(buf, length); send_to_basestation(buf, length, &nmc.context.gsp); } }
static void set_distiller_type(DistillerBuffer *mime_headers, const char *url, const char *user, C_DistillerType *dtype) { const char *route = NULL; int route_len; char *disttype; if ((route = get_header_value(mime_headers, "x-route",&route_len,NULL,NULL)) == NULL) { /* Aggregator? */ if (strncasecmp(url, fe_agg_string, strlen(fe_agg_string)) == 0) { /* distiller "type" is everything up to but not incl next slash */ char disttype_tmp[256]; int i,j; for (i=0, j=strlen(fe_agg_string); i < strlen(url) && url[j] != '/'; i++,j++) ; strncpy(disttype_tmp, url+strlen(fe_agg_string), i); disttype_tmp[i] = '\0'; SET_DISTILLER_TYPE(*dtype, disttype_tmp); } else { /* generic transformation */ set_distiller_type_generic(mime_headers, url, user, dtype); } } else { /* pop off next element, up to a semicolon */ char *header_value = (char *)ALLOCA(route_len+1); char *semicolon; strncpy(header_value, route, route_len); header_value[route_len] = '\0'; if ((semicolon = strchr(header_value, ';')) != NULL) { int i; for (i=0; i<route_len && route[i] != ';'; i++) ; disttype = (char*)ALLOCA(i+2); strncpy(disttype, route, i); disttype[i] = '\0'; insert_header(mime_headers, "x-route", semicolon+1, 0); } else { /* no semicolon, this is the last guy in the list */ disttype = (char *)ALLOCA(route_len+2); strncpy(disttype, route, route_len); disttype[route_len] = '\0'; } delete_header(mime_headers, "x-route"); SET_DISTILLER_TYPE(*dtype, disttype); } }
void send_connection_statistics(nabto_connect* con, uint8_t event) { size_t length; uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0); uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize; ptr = insert_stats_payload(ptr, end, event); if (ptr == NULL) { return; } ptr = insert_version_payload(ptr, end); if (ptr == NULL) { return; } #if NABTO_ENABLE_CLIENT_ID ptr = insert_cp_id_payload(ptr, end, con); if (ptr == NULL) { return; } #endif ptr = insert_sp_id_payload(ptr, end); if (ptr == NULL) { return; } ptr = insert_ipx_payload(ptr, end); if (ptr == NULL) { return; } ptr = insert_connect_stats_payload(ptr, end, con); if (ptr == NULL) { return; } if (!con->noRendezvous) { ptr = insert_rendezvous_stats_payload(ptr, end, con); if (ptr == NULL) { return; } } ptr = insert_connection_stats_payload(ptr, end, con); if (ptr == NULL) { return; } length = ptr - nabtoCommunicationBuffer; insert_length(nabtoCommunicationBuffer, length); send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp); }
/** * Build U_CONNECT response to GSP * @param buf the destination buffer * @param seq the sequence number * @param notif the result notification * @param nsi the nsi value of the connection * @param cpnsi the nsi of the clientpeer to put into the packet. * @param spnsi the nsi of the serverpeer to put into the packet. * @param isLocalConnectRsp true if a capabilities packet * @return the size of the response */ static size_t mk_gsp_connect_rsp(uint8_t* buf, uint16_t seq, uint32_t notif, uint32_t nsi, uint32_t cpnsi, uint32_t spnsi, bool isLocalConnectRsp) { uint8_t* ptr = insert_header(buf, cpnsi, spnsi, U_CONNECT, true, seq, 0, 0); ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_NOTIFY, 0, 8); WRITE_U32(ptr, notif); ptr += 4; WRITE_U32(ptr, nsi); ptr += 4; if (isLocalConnectRsp) { ptr = insert_capabilities(ptr, 1 /*unenc*/); } insert_length(buf, ptr - buf); return ptr - buf; }
int main(){ int i,j,k, n,pixl, count=0; PIX *pixs; glob_t *flist; FILE *file=fopen("train_file.trn","w"); for(n=0;n<10;n++){ flist=list_files(n); if(flist->gl_pathc==0) { fprintf(stderr,"No files in directory %d... Exiting...\n",n); exit(1); } for(i=0;i<flist->gl_pathc;i++){ pixs=loadimage(flist->gl_pathv[i]); if(pixs==NULL){ fprintf(stderr,"Pix error... Exiting...\n"); exit(1); } for(j=0;j<pixGetHeight(pixs);j++){ for(k=0;k<pixGetWidth(pixs);k++){ pixGetPixel(pixs,k,j,&pixl); fprintf(file,"%d",pixl); /* funny transformation of rows/columns. TODO: works with intels, but others??? */ } fprintf(file,"\n"); } count++; fprintf(file," %d\n",n); } globfree(flist); free(flist); } fclose(file); // *file=fopen("train_file.trn","r"); FILE *file1=fopen("train_file_header.trn","w"); insert_header(file1,count); fclose(file1); return (0); }
static void send_rendezvous_socket(nabto_socket_t socket, nabto_connect* con, uint16_t seq, nabto_endpoint* dest, nabto_endpoint *myAddress) { uint8_t* ptr; uint8_t* buf = nabtoCommunicationBuffer; ptr = insert_header(buf, 0, con->spnsi, U_CONNECT, false, seq, 0, 0); ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6); WRITE_U32(ptr, dest->addr); ptr += 4; WRITE_U16(ptr, dest->port); ptr += 2; if (seq > 0) { if (!myAddress) { NABTO_LOG_ERROR(("Send rendezvous called with an invalid address")); return; } else { ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6); WRITE_U32(ptr, myAddress->addr); ptr += 4; WRITE_U16(ptr, myAddress->port); ptr += 2; } } { size_t len = ptr - buf; insert_length(buf, len); if (seq) { NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=%" PRIu16 " " PRIep, MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest), seq, MAKE_EP_PRINTABLE(*myAddress))); } else { NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=0", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest))); } if (dest->addr != 0 && dest->port != 0) { nabto_write(socket, buf, len, dest->addr, dest->port); } else { NABTO_LOG_TRACE(("invalid rendezvous packet thrown away")); } } }
void send_connection_ended_statistics(nabto_connect* con) { size_t length; uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0); uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize; ptr = insert_stats_payload(ptr, end, NP_PAYLOAD_STATS_TYPE_UNABTO_CONNECTION_ENDED); if (ptr == NULL) { return; } ptr = insert_version_payload(ptr, end); if (ptr == NULL) { return; } #if NABTO_ENABLE_CLIENT_ID ptr = insert_cp_id_payload(ptr, end, con); if (ptr == NULL) { return; } #endif ptr = insert_sp_id_payload(ptr, end); if (ptr == NULL) { return; } ptr = insert_connection_stats_payload(ptr, end, con); if (ptr == NULL) { return; } length = ptr - nabtoCommunicationBuffer; insert_length(nabtoCommunicationBuffer, length); send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp); }
int GGI_vnc_trle(ggi_vnc_client *client, ggi_rect *update) { struct trle_ctx_t *ctx = client->trle_ctx; struct ggi_visual *cvis; const ggi_directbuffer *db; ggi_graphtype gt; int bpp; int cbpp; int count; unsigned char *buf; unsigned char *header; int xtiles, ytiles; unsigned char *work; int lower = 1; int tile_param; tile_func *tile; int xt, yt; int xs, ys; int xs_last, ys_last; int stride; ggi_rect vupdate; int d_frame_num; DPRINT("trle update %dx%d - %dx%d\n", update->tl.x, update->tl.y, update->br.x, update->br.y); cvis = GGI_vnc_encode_init(client, update, &vupdate, &d_frame_num); gt = LIBGGI_GT(cvis); bpp = GT_ByPP(gt); if (bpp == 4) { ggi_pixel mask = LIBGGI_PIXFMT(cvis)->red_mask | LIBGGI_PIXFMT(cvis)->green_mask | LIBGGI_PIXFMT(cvis)->blue_mask; if (!(mask & 0xff000000)) cbpp = 3; else if (!(mask & 0xff)) { lower = 0; cbpp = 3; } else cbpp = 4; } else cbpp = bpp; count = ggi_rect_width(&vupdate) * ggi_rect_height(&vupdate); xtiles = (ggi_rect_width(&vupdate) + 15) / 16; ytiles = (ggi_rect_height(&vupdate) + 15) / 16; GGI_vnc_buf_reserve(&client->wbuf, client->wbuf.size + 12 + xtiles * ytiles + count * cbpp); header = &client->wbuf.buf[client->wbuf.size]; insert_header(header, &update->tl, &vupdate, 15); /* trle */ client->wbuf.size += 12; work = &client->wbuf.buf[client->wbuf.size]; buf = work; db = ggiDBGetBuffer(cvis->instance.stem, d_frame_num); ggiResourceAcquire(db->resource, GGI_ACTYPE_READ); if (bpp == 1) { tile_param = 0; tile = tile_8; } else if (bpp == 2) { tile_param = client->reverse_endian; tile = tile_16; } else if (cbpp == 3 && !client->reverse_endian) { tile_param = lower; tile = tile_24; } else if (cbpp == 3) { tile_param = lower; tile = tile_rev_24; } else { tile_param = client->reverse_endian; tile = tile_32; } stride = LIBGGI_VIRTX(cvis); ys_last = ggi_rect_height(&vupdate) & 0xf; if (!ys_last) ys_last = 16; xs_last = ggi_rect_width(&vupdate) & 0xf; if (!xs_last) xs_last = 16; ys = 16; for (yt = 0; yt < ytiles; ++yt) { if (yt == ytiles - 1) ys = ys_last; xs = 16; for (xt = 0; xt < xtiles; ++xt) { if (xt == xtiles - 1) xs = xs_last; tile(ctx, &buf, (uint8_t *)db->read + ((vupdate.tl.y + 16 * yt) * stride + vupdate.tl.x + 16 * xt) * bpp, xs, ys, stride, tile_param); } } ggiResourceRelease(db->resource); client->wbuf.size += buf - work; return 1; }
int main(int argc, char *argv[]) { FILE *pf; char buff[BUFSIZE]; int c, i, port; unsigned int tsp; char *scheme, *user, *host, *backup; pid_t pid; struct timespec ts; int upp; #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option l_opts[] = { {"help", 0, 0, 'X'}, {"version", 0, 0, 'V'}, {"filename", 1, 0, 'f'}, {"sip-uri", 1, 0, 's'}, {"traceroute-mode", 0, 0, 'T'}, {"usrloc-mode", 0, 0, 'U'}, {"invite-mode", 0, 0, 'I'}, {"message-mode", 0, 0, 'M'}, {"contact", 1, 0, 'C'}, {"appendix-begin", 1, 0, 'b'}, {"appendix-end", 1, 0, 'e'}, {"sleep", 1, 0, 'o'}, {"expires", 1, 0, 'x'}, {"remove-bindings", 1, 0, 'z'}, {"flood-mode", 0, 0, 'F'}, {"random-mode", 0, 0, 'R'}, {"trash-chars", 1, 0, 't'}, {"local-port", 1, 0, 'l'}, {"remote-port", 1, 0, 'r'}, {"outbound-proxy", 1, 0, 'p'}, {"hostname", 1, 0, 'H'}, {"max-fowards", 1, 0, 'm'}, {"numeric", 0, 0, 'n'}, {"no-via", 0, 0, 'i'}, {"password", 1, 0, 'a'}, {"ignore-redirects", 0, 0, 'd'}, {"verbose", 0, 0, 'v'}, {"extract-ip", 0, 0, 'w'}, {"replace-string", 0, 0, 'g'}, {"replace", 0, 0, 'G'}, {"nagios-code", 0, 0, 'N'}, {"nagios-warn", 1, 0, 'W'}, {"search", 1, 0, 'q'}, {"message-body", 1, 0, 'B'}, {"disposition", 1, 0, 'O'}, {"processes", 1, 0, 'P'}, {"auth-username", 1, 0, 'u'}, {"no-crlf", 0, 0, 'L'}, {"timing", 1, 0, 'A'}, {"symmetric", 0, 0, 'S'}, {"from", 1, 0, 'c'}, {"timeout-factor", 1, 0, 'D'}, {"transport", 1, 0, 'E'}, {"headers", 1, 0, 'j'}, {0, 0, 0, 0} }; #endif /* some initialisation to be shure */ file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0; warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0; sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0; namebeg=nameend=maxforw= -1; numeric=via_ins=redirects=fix_crlf=processes = 1; username=password=replace_str=hostname=contact_uri=mes_body = NULL; con_dis=auth_username=from_uri=headers = NULL; scheme = user = host = backup = req = rep = rec = NULL; re = NULL; address= 0; transport=tsp = 0; rport = port = 0; expires_t = USRLOC_EXP_DEF; inv_final = 64 * SIP_T1; memset(buff, 0, BUFSIZE); memset(fqdn, 0, FQDN_SIZE); if (argc==1) { print_help(); } /* lots of command line switches to handle*/ #ifdef HAVE_GETOPT_LONG while ((c=getopt_long(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:Xz:", l_opts, &option_index)) != EOF){ #else while ((c=getopt(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:z:")) != EOF){ #endif switch(c){ case 'a': if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) { password = str_alloc(SIPSAK_MAX_PASSWD_LEN); printf("Please enter the password (max. length %i): ", SIPSAK_MAX_PASSWD_LEN); if (read_stdin(password, SIPSAK_MAX_PASSWD_LEN, 1) == 0) { exit_code(0); } } else { password=str_alloc(strlen(optarg) + 1); strncpy(password, optarg, strlen(optarg)); } break; case 'A': timing=str_to_int(optarg); break; case 'b': namebeg=str_to_int(optarg); break; case 'B': mes_body=str_alloc(strlen(optarg) + 1); strncpy(mes_body, optarg, strlen(optarg)); break; case 'c': backup=str_alloc(strlen(optarg)+1); strncpy(backup, optarg, strlen(optarg)); parse_uri(backup, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: missing scheme in From URI\n"); exit_code(2); } else if (user == NULL) { fprintf(stderr, "error: missing username in From URI\n"); exit_code(2); } else if (host == NULL) { fprintf(stderr, "error: missing host in From URI\n"); exit_code(2); } else { from_uri=str_alloc(strlen(optarg)+1); strncpy(from_uri, optarg, strlen(optarg)); } free(backup); break; case 'C': if ((strlen(optarg) == 5 && STRNCASECMP(optarg, "empty", 5) == 0) || (strlen(optarg) == 4 && STRNCASECMP(optarg, "none", 4) == 0)) { empty_contact = 1; } else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "*", 1) == 0) { contact_uri=str_alloc(strlen(optarg)+1); strncpy(contact_uri, optarg, strlen(optarg)); } else { backup=str_alloc(strlen(optarg)+1); strncpy(backup, optarg, strlen(optarg)); parse_uri(backup, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: REGISTER Contact uri doesn't not contain " "sip:, sips:, *, or is not empty\n"); exit_code(2); } else if (user == NULL) { fprintf(stderr, "error: missing username in Contact uri\n"); exit_code(2); } else if (host == NULL) { fprintf(stderr, "error: missing host in Contact uri\n"); exit_code(2); } else { contact_uri=str_alloc(strlen(optarg)+1); strncpy(contact_uri, optarg, strlen(optarg)); } free(backup); } break; case 'd': redirects=0; break; case 'D': inv_final = str_to_int(optarg) * SIP_T1; break; case 'e': nameend=str_to_int(optarg); break; case 'E': if (strlen(optarg) == 3 && STRNCASECMP(optarg, "udp", 3) == 0) { transport = SIP_UDP_TRANSPORT; } else if (strlen(optarg) == 3 && STRNCASECMP(optarg, "tcp", 3) == 0) { transport = SIP_TCP_TRANSPORT; } else if (strlen(optarg) == 3 && STRNCASECMP(optarg, "tls", 3) == 0) { fprintf(stderr, "error: TLS is not supported yet, supported values: udp, tcp\n"); exit_code(2); transport = SIP_TLS_TRANSPORT; } else { fprintf(stderr, "error: unsupported transport '%s', supported values: udp, tcp\n", optarg); exit_code(2); } break; case 'F': flood=1; break; case 'f': if (strlen(optarg) != 1 && STRNCASECMP(optarg, "-", 1) != 0) { /* file is opened in binary mode so that the cr-lf is preserved */ pf = fopen(optarg, "rb"); if (!pf){ fprintf(stderr, "error: unable to open the file '%s'.\n", optarg); exit_code(2); } if (fread(buff, 1, sizeof(buff), pf) >= sizeof(buff)){ fprintf(stderr, "error:the file is too big. try files of less " "than %i bytes.\n", BUFSIZE); fprintf(stderr, " or recompile the program with bigger " "BUFSIZE defined.\n"); exit_code(2); } fclose(pf); } else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) { if (read_stdin(&buff[0], sizeof(buff), 0) == 0) { exit_code(0); } } else { fprintf(stderr, "error: unable to handle input file name: %s\n", optarg); exit_code(2); } file_b=1; break; case 'g': replace_str=optarg; break; case 'G': replace_b=1; break; case 'h': print_help(); break; case 'H': hostname=optarg; break; case 'i': via_ins=0; break; case 'I': invite=1; break; case 'j': headers=optarg; break; case 'l': lport=str_to_int(optarg); break; case 'L': fix_crlf=0; break; case 'm': maxforw=str_to_int(optarg); break; case 'M': message=1; break; case 'n': numeric = 0; break; case 'N': exit_mode=EM_NAGIOS; break; case 'o': sleep_ms = 0; if (strlen(optarg) == 4 && STRNCASECMP(optarg, "rand", 4) == 0) { sleep_ms = -2; } else { sleep_ms = str_to_int(optarg); } break; case 'O': con_dis=str_alloc(strlen(optarg) + 1); strncpy(con_dis, optarg, strlen(optarg)); break; case 'p': parse_uri(optarg, &scheme, &user, &host, &rport); if (host == NULL) { fprintf(stderr, "error: missing in host in outbound proxy\n"); exit_code(2); } if (is_ip(host)) { address = getaddress(host); if (transport == 0) transport = SIP_UDP_TRANSPORT; } else { if (!rport) { address = getsrvadr(host, &rport, &tsp); if (tsp != 0) transport = tsp; } if (!address) { address = getaddress(host); if (address && verbose > 1) printf("using A record: %s\n", host); } if (!address){ fprintf(stderr, "error:unable to determine the outbound proxy " "address\n"); exit_code(2); } } outbound_proxy=1; break; case 'P': processes=str_to_int(optarg); break; case 'q': if (re) { /* previously allocated -- free */ regfree(re); } else { /* never tried -- allocate */ re=malloc(sizeof(regex_t)); }; if (!re) { fprintf(stderr, "Error: can't allocate RE\n"); exit_code(2); }; if (regcomp(re, optarg, REG_EXTENDED|REG_ICASE|REG_NEWLINE )!=0) { fprintf(stderr, "Error: compiling RE: %s\n", optarg ); exit_code(2); }; break; case 'r': port = 0; port=str_to_int(optarg); if (rport) { fprintf(stderr, "warning: you are overwritting the destination port with the r argument\n"); } rport = port; break; case 'R': randtrash=1; break; case 's': parse_uri(optarg, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: missing scheme in sip uri\n"); exit_code(2); } if (strlen(optarg) == 4 && STRNCASECMP(optarg,"sips",4) == 0){ fprintf(stderr, "error: sips is not supported yet\n"); exit_code(2); } else if (strlen(optarg) != 3 || STRNCASECMP(optarg,"sip",3) != 0){ fprintf(stderr, "error: scheme of sip uri has to be sip\n"); exit_code(2); } if (user != NULL) { username = user; } if (host != NULL) { domainname = host; } else { fprintf(stderr, "error: missing hostname in sip uri\n"); exit_code(2); } if (port && !rport) { rport = port; } if (is_ip(domainname)) { address = getaddress(domainname); if (transport == 0) transport = SIP_UDP_TRANSPORT; } else { if (!rport && !address) { address = getsrvadr(domainname, &rport, &tsp); if (tsp != 0) transport = tsp; } if (!address) { address = getaddress(domainname); if (address && verbose > 1) printf("using A record: %s\n", domainname); } if (!address){ fprintf(stderr, "error:unable to determine the IP address for: %s\n", domainname); exit_code(2); } } if (port != 0) { backup = str_alloc(strlen(domainname)+1+6); snprintf(backup, strlen(domainname)+6, "%s:%i", domainname, port); domainname = backup; } uri_b=1; break; case 'S': fprintf(stderr, "warning: symmetric does not work with a-symmetric servers\n"); symmetric=1; break; case 't': trashchar=str_to_int(optarg); break; case 'T': trace=1; break; case 'U': usrloc=1; break; case 'u': auth_username=str_alloc(strlen(optarg) + 1); strncpy(auth_username, optarg, strlen(optarg)); break; case 'v': verbose++; break; case 'V': printf("sipsak %s by Nils Ohlmeier\n Copyright (C) 2002-2004" " FhG Fokus\n Copyright (C) 2004-2005 Nils Ohlmeier\n", SIPSAK_VERSION); printf(" compiled with DEFAULT_TIMEOUT=%i, FQDN_SIZE=%i", DEFAULT_TIMEOUT, FQDN_SIZE); #ifdef RAW_SUPPORT printf(", RAW_SUPPORT"); #endif #ifdef HAVE_GETOPT_LONG printf(", LONG_OPTS"); #endif #ifdef HAVE_GNUTLS printf(", GNUTLS_MD5"); #else # ifdef HAVE_FULL_OPENSSL printf(", OPENSSL_MD5"); # else printf(", INTERNAL_MD5"); # endif #endif #ifdef HAVE_OPENSSL_SHA1 printf(", OPENSSL_SHA1"); #endif #ifdef HAVE_CARES_H printf(", SRV_SUPPORT(ARES)"); #else # ifdef HAVE_RULI_H printf(", SRV_SUPPORT(RULI)"); # endif #endif #ifdef HAVE_STRCASESTR printf(", STR_CASE_INSENSITIVE"); #endif #ifdef HAVE_STRNCASECMP printf(", CMP_CASE_INSENSITIVE"); #endif printf("\n"); exit_code(0); break; case 'w': warning_ext=1; break; case 'W': nagios_warn = str_to_int(optarg); break; case 'x': expires_t=str_to_int(optarg); break; #ifdef HAVE_GETOPT_LONG case 'X': print_long_help(); break; #endif case 'z': rand_rem=str_to_int(optarg); if (rand_rem < 0 || rand_rem > 100) { fprintf(stderr, "error: z option must between 0 and 100\n"); exit_code(2); } break; default: fprintf(stderr, "error: unknown parameter %c\n", c); exit_code(2); break; } } if (rport == 0) { rport = 5060; } if (rport > 65535 || rport <= 0) { fprintf(stderr, "error: invalid remote port: %i\n", rport); exit_code(2); } if (transport == 0) { transport = SIP_UDP_TRANSPORT; } /* replace LF with CRLF if we read from a file */ if ((file_b) && (fix_crlf)) { insert_cr(buff); } if (headers) { backup = str_alloc(strlen(headers) + 30); // FIXME strcpy(backup, headers); headers = backup; replace_string(headers, "\\n", "\r\n"); backup = headers + strlen(headers) - 1; if (*backup != '\n') { strcpy(backup + 1, "\r\n"); } if (file_b) insert_header(buff, headers, 1); } /* lots of conditions to check */ if (trace) { if (usrloc || flood || randtrash) { fprintf(stderr, "error: trace can't be combined with usrloc, random or " "flood\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: for trace mode a SIPURI is realy needed\n"); exit_code(2); } if (file_b) { fprintf(stderr, "warning: file will be ignored for tracing."); } if (!username) { fprintf(stderr, "error: for trace mode without a file the SIPURI have to " "contain a username\n"); exit_code(2); } if (!via_ins){ fprintf(stderr, "warning: Via-Line is needed for tracing. Ignoring -i\n"); via_ins=1; } if (!warning_ext) { fprintf(stderr, "warning: IP extract from warning activated to be more " "informational\n"); warning_ext=1; } if (maxforw==-1) maxforw=255; } else if (usrloc || invite || message) { if (trace || flood || randtrash) { fprintf(stderr, "error: usrloc can't be combined with trace, random or " "flood\n"); exit_code(2); } if (!username || !uri_b) { fprintf(stderr, "error: for the USRLOC mode you have to give a SIPURI with " "a username\n at least\n"); exit_code(2); } if (namebeg>0 && nameend==-1) { fprintf(stderr, "error: if a starting numbers is given also an ending " "number have to be specified\n"); exit_code(2); } if (invite && message) { fprintf(stderr, "error: invite and message tests are XOR\n"); exit_code(2); } if (!usrloc && invite && !lport) { fprintf(stderr, "warning: Do NOT use the usrloc invite mode without " "registering sipsak before.\n See man page for " "details.\n"); exit_code(2); } if (contact_uri!=NULL) { if (invite || message) { fprintf(stderr, "error: Contact uri is not support for invites or " "messages\n"); exit_code(2); } if (nameend!=-1 || namebeg!=-1) { fprintf(stderr, "warning: ignoring starting or ending number if Contact" " is given\n"); nameend=namebeg=0; } if (rand_rem) { fprintf(stderr, "warning: ignoring -z option when Contact is given\n"); rand_rem=0; } } if (via_ins) { fprintf(stderr, "warning: ignoring -i option when in usrloc mode\n"); via_ins=0; } if (nameend==-1) nameend=0; if (namebeg==-1) namebeg=0; } else if (flood) { if (trace || usrloc || randtrash) { fprintf(stderr, "error: flood can't be combined with trace, random or " "usrloc\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: we need at least a sip uri for flood\n"); exit_code(2); } if (redirects) { fprintf(stderr, "warning: redirects are not expected in flood. " "disableing\n"); redirects=0; } } else if (randtrash) { if (trace || usrloc || flood) { fprintf(stderr, "error: random can't be combined with trace, flood or " "usrloc\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: need at least a sip uri for random\n"); exit_code(2); } if (redirects) { fprintf(stderr, "warning: redirects are not expected in random. " "disableing\n"); redirects=0; } if (verbose) { fprintf(stderr, "warning: random characters may destroy your terminal " "output\n"); } } else if (mes_body) { if (!message) { fprintf(stderr, "warning: to send a message mode (-M) is required. activating\n"); message=1; } if (!uri_b) { fprintf(stderr, "error: need at least a sip uri to send a meesage\n"); exit_code(2); } if (nameend==-1) nameend=0; if (namebeg==-1) namebeg=0; } else { if (!uri_b) { fprintf(stderr, "error: a spi uri is needed at least\n"); exit_code(2); } } switch (transport) { case SIP_TLS_TRANSPORT: transport_str = TRANSPORT_TLS_STR; break; case SIP_TCP_TRANSPORT: transport_str = TRANSPORT_TCP_STR; break; case SIP_UDP_TRANSPORT: transport_str = TRANSPORT_UDP_STR; break; default: fprintf(stderr, "unknown transport: %i\n", transport); exit_code(2); } /* determine our hostname */ get_fqdn(); /* this is not a cryptographic random number generator, but hey this is only a test-tool => should be satisfying*/ srand(time(0) ^ getpid()); if (processes > 1) { if (signal(SIGCHLD , sigchld_handler) == SIG_ERR ) { fprintf(stderr, "error: Could not install SIGCHLD handler\n"); exit_code(2); } } for(i = 0; i < processes - 1; i++) { if ((pid = fork()) < 0) { fprintf(stderr, "error: Cannot fork\n"); exit_code(2); } if (pid == 0){ /* child */ upp = (nameend - namebeg + 1) / processes; namebeg = namebeg + upp * i; nameend = namebeg + upp; shoot(&buff[0], sizeof(buff)); } else { if (lport) { lport++; } } /* Delay execution of children so that the * time of the first transmission gets spread over * the retransmission interval evenly */ ts.tv_sec = 0; ts.tv_nsec = (float)DEFAULT_TIMEOUT / (float)processes * (float)1000 * (float)1000; nanosleep(&ts, 0); } /* here we go...*/ if (processes > 1) { upp = (nameend - namebeg + 1) / processes; namebeg = namebeg + upp * i; nameend = namebeg + upp; } shoot(&buff[0], sizeof(buff)); /* normaly we won't come back here, but to satisfy the compiler */ return 0; }
void * http_go_proc(task_t *t) { int index = TASK_THRINDEX(t); Request h; ArgumentList prefs; userkey k; HTTP_Status result; DistillerStatus dist_result; const char *content_type; Argument *arg; int thresh; gm_Bool no_distill = gm_False; gm_Bool is_text_html = gm_False; #ifdef LOGGING struct loginfo lo; char logmsg[MAX_LOGMSG_LEN]; #endif /* LOGGING */ /* * New task data should be the request structure. */ init_Request(&h); h.cli_fd = (int)TASK_DATA(t); /* socket FD of client */ SET_TASK_DATA(t,&h); INST_begin_timestamp(index); INST_set_size(index,0); INST_set_thread_state(index, THR_ACCEPTED); INST_timestamp(index, m_arrival); #ifdef LOGGING LOGGING_init_loginfo(&lo); h.lo = &lo; #endif /* LOGGING */ /* * this should read all the headers. */ if (TASK_METADATA(t) == NULL) { int result; assert( DistillerBufferAlloc(&h.cli_hdrs, PERF_HTTP_TOTAL_HEADERLEN) == gm_True); result = readline_or_timeout(&h, READ_ALL_HEADERS, NULL); INST_timestamp(index, m_headersdone); if (result == -1) { /* client request timed out, or error reading hdrs */ /* TC::1 client timeout, or request doesn't sanity check */ goto HTTPGO_FINISH; /* NOTREACHED */ } } else { #ifdef NEWFE /* * This task is a child of a previous */ strncpy(h.cli_hdrs.mime_headers, TASK_METADATA(t), PERF_HTTP_TOTAL_HEADERLEN-1); FREE(TASK_METADATA(t)); #endif /* NEWFE */ } /* parse the headers and request line, filling them in to the loginfo */ result = parse_status_and_headers(&h); if (result != HTTP_NO_ERR) { /* BUG:: last arg of http_error_return should be a substitution arg */ /* TC::2 parse_status_and_headers returns an error */ http_error_return(&h, result); printf("Error occured here!\n"); goto HTTPGO_FINISH; } /* * We have a reasonable looking request. Get prefs for this user. */ k = userkey_from_sock_ipaddr(h.cli_fd); #ifdef LOGGING lo.ipaddr = k; #endif /* LOGGING */ (void)get_userprefs(k, &prefs); /* * Extract any arguments embedded in the URL itself, and add them * to the arg list. * TC::3 url is magic vs nonmagic */ if (is_magic ((char *) h.url)) { /* demagifying a url will never lengthen it so this is a good * upper bounds on the length of the non magical url */ char *demagicURL = ALLOCA(strlen(h.url)+1); assert(demagicURL); strcpy(demagicURL, h.url); from_magic((char *) demagicURL, h.url, &prefs); } /* determine the threshold for bypassing */ arg = getArgumentFromIdInList(&prefs, FRONT_MTU); thresh = (arg == NULL ? PERF_FRONT_MTU : ARG_INT(*arg)); /* determine if distillation is turned off for this * request. EXCEPTION: Force distillation for Prefs html form. */ arg = getArgumentFromIdInList(&prefs, FRONT_NO_DISTILL); if (arg != NULL && ARG_INT(*arg) && strcasecmp(fe_get_prefs_url, h.url) != 0) { /* TC::4 no_distill is set */ no_distill = gm_True; } else { no_distill = gm_False; } /* Short-circuit the following special URL's: * - "set my prefs as follows" (e.g. form submission) */ if (is_setpref_url(h.url)) { /* * handle what send user prefs form sends back. * TC::5 is_setpref_url returns true */ result = parse_and_change_prefs(h.url, k, h.errmsg); if (result == HTTP_NO_ERR) { /* TC::5.1 setpref url succeeds in setting prefs */ correct_write(h.cli_fd, "HTTP/1.0 200\r\nContent-type: text/html\r\n\r\n", -1); correct_write(h.cli_fd, "<html><head><title>Preferences Set</title></head>" "<body><center><h1>Preferences set</h1>" "Your new preferences have been set. Press the back " "button twice to resume browsing." "<p></center></body></html>", -1); } else { /* TC::5.2 setpref url fails in setting prefs */ http_error_return(&h, result); } } else if (is_getpref_url(h.url)) { /* TC::6 gimme my prefs*/ send_prefs(&prefs, h.cli_fd); } else if (is_server_url(h.url)==gm_False && strcasecmp(h.method, "get") != 0 && strcasecmp(h.method, "post") != 0) { /* * Doesn't appear to be an HTTP GET or POST request; so act as a * "dumb tunnel" for passing the request to the server (actually, via * the cache) and relaying the result to the client. */ /* TC::7 tunnel */ proxy_debug_3(DBG_HTTP, "Tunneling '%s'", DistillerBufferData(&h.cli_hdrs)); INST_set_thread_state(index, THR_DISTILLERSEND); tunnel(&h); } else { /* * It's not a special URL, and the request appears to be a GET/POST. * Add in the client's IP address as an INT32 argument so that * the distiller driver can get at it. */ SET_ARG_INT(prefs.arg[prefs.nargs], (INT32) k); SET_ARG_ID(prefs.arg[prefs.nargs], FRONT_CLIENT_IP); prefs.nargs++; result = server_dispatch(&prefs, t); /* * If we get a transport-level error (i.e. fetch from cache failed * due to an internal cache error), wrap the error in HTML (if * needed) and return error to user. * Otherwise, if the transaction succeeded but the server return * code indicates failure (i.e. != 200), **OR** if the server data * is smaller than a threshold size, bypass the server data * directly to the client. * Otherwise, attempt to distill. */ if (result != HTTP_NO_ERR) { /* transport level error: wrap in HTML for delivery to user */ /* TC::8 server_dispatch returns transport level error */ http_error_return(&h, result); goto HTTPGO_FINISH; } content_type = get_header_value(&h.svr_hdrs, "content-type", NULL, NULL, NULL); if (content_type == NULL) { /* TC::9 content-type can't be deduced */ content_type = "application/octet-stream"; } is_text_html = ( ((strncasecmp(content_type, "text/html", 9) == 0) || (strncasecmp(content_type, "text/plain", 10) == 0)) ? gm_True : gm_False); /*if ( (*h.url != '/' && strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) != 0) &&*/ /* bypass ONLY if it is not a server-type URL */ /* TC::10.1 bypass because non-200s status */ /* TC::10.2 bypass because not text/html and too small to distill */ /* TC::4 bypass because no_distill is set */ /* bypass server data directly to user */ if ( is_server_url(h.url)==gm_False) { char *bypass_reason = NULL; if (h.svr_http_status != 200) { bypass_reason = "201 Non-OK server status"; } else if (is_text_html == gm_False && DistillerBufferLength(&h.svr_data) <= thresh) { bypass_reason = "202 content-type not text/html and content-length too short"; } else if (no_distill == gm_True) { bypass_reason = "203 distillation not indicated"; } if (bypass_reason) { INST_set_thread_state(index, THR_WRITEBACK); /* * Set return headers to indicate why the bypass occurred. */ insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, bypass_reason, 0); complete_bypass(&h); goto HTTPGO_FINISH; } } /* all is well: continue by dispatching to a worker for distillation */ dist_result = proxy_dispatch(&prefs, t); switch(dist_result) { case distOk: /* TC::11 distillation succeeded */ INST_timestamp(index, m_wbstart); insert_header(&h.pxy_hdrs, TRANSEND_STATUS_HEADER, "200 distillation OK", 0); correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_hdrs), (int)DistillerBufferLength(&h.pxy_hdrs)); /* -1 to avoid NULL term gunk */ correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_data), (int)DistillerBufferLength(&h.pxy_data)); INST_timestamp(thrindex, m_wbdone); break; case distDistillerNotFound: case distLaunchTimeout: case distBadInput: case distConnectionBroken: /* forward original if distiller for this type not found, connection repeatedly broken, or couldn't be launched */ /* TC::12 bypass because distillation failed */ insert_header(&h.svr_hdrs, (dist_result == distBadInput ? TRANSEND_STATUS_HEADER : TRANSEND_ERROR_HEADER), FE_getDistillerStatusString(dist_result), 0); if ((arg = getArgumentFromIdInList(&prefs, FRONT_DEVELOPER)) && ARG_INT(*arg)) { /* return explicit error message */ int tmp_len = snprintf(h.errmsg, HTTP_ERRMSG_MAX, "<i>[set arg <tt>i%d</tt> to 0 to suppress " "this diagnostic]</i><br>", FRONT_DEVELOPER); strncat(h.errmsg, FE_getDistillerStatusString(dist_result), HTTP_ERRMSG_MAX - tmp_len - 1); http_error_return(&h, HTTP_ERR_UNSPECIFIED); } else { /*if (*h.url == '/' || strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/ if (is_server_url(h.url)==gm_True) { /* this is a URL in the frontend's namespace, or an aggregator URL */ strcpy(h.errmsg, h.url); http_error_return(&h, HTTP_ERR_AGGREGATOR_ERROR); } else { complete_bypass(&h); } } break; case distRedispatch: /* * Redispatch count expired: too many redispatches (probably indicates * infinite loop in redispatch route.) */ snprintf(h.errmsg, HTTP_ERRMSG_MAX, "%d", PERF_REQUEST_TTL); http_error_return(&h, HTTP_ERR_ROUTING_ERROR); break; default: /* TC::13 some other distillation error */ insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, FE_getDistillerStatusString(dist_result), 0); http_error_return(&h, HTTP_ERR_UNSPECIFIED); break; } /* switch(dist_result) */ } /* if...else...else...endif */ /* all cases exit through this single exit point */ HTTPGO_FINISH: free_Request(&h); INST_timestamp(index, m_wbdone); INST_end_timestamp(index); if (TASK_PARENT(t) == 0 && TASK_CHILD_INDEX(t) == 0) { /* this is a "root task" */ close(h.cli_fd); } #ifdef LOGGING /* log the request info */ /* BUG::relies on formatting of the userkey */ /* I compare the IP address to 127.0.0.1 so that I don't log connections from localhost, namely the fe_check script. I also MD5 the IP address. */ k = lo.ipaddr; if (((UINT32) k) != ((UINT32) htonl(0x7F000001))) { /* MD5_CTX theHash; UINT32 res; MD5Init(&theHash); MD5Update(&theHash, magicKey, sizeof(magicKey)); MD5Update(&theHash, &k, sizeof(UINT32)); MD5Final(&theHash); memcpy(&res, theHash.digest, sizeof(UINT32)); res = ntohl(res); snprintf(logmsg, MAX_LOGMSG_LEN-1, "(HTTP) %lu %lu \"%s\" %d %ld %ld\n", res, lo.date, lo.url, lo.http_response, lo.size_before, lo.size_after);*/ snprintf(logmsg, MAX_LOGMSG_LEN-1, "(HTTP) %08x %08x \"%s\" %d %ld %ld\n", (UINT32) k, lo.date, lo.url, lo.http_response, lo.size_before, lo.size_after); gm_log(logmsg); } #endif /* LOGGING */ return (void *)0; }
/* void protocol1 * buffer* recv_buffer - buffer containing the message sent by the client to the proxy * server_stat* status - status and general information from the server * Processes the recv_buf as the class protocol dictates */ void protocol1(buffer* recv_buf, server_stat* status){ struct timeval timeout; struct timeval timeout_0; // timeouts timeout.tv_sec = 1; timeout.tv_usec = 0; timeout_0.tv_sec = 0; timeout_0.tv_usec = 0; timeout_setup(status->udp_sock, timeout); // giant mess of conditionals fprintf(stdout, "\tversion 1 protocol\n"); int error = 0; header msg_header = extract_header(recv_buf); if (status->connected == 0) { if (check_pass(&msg_header, 0)) { if (get_command(&msg_header) == CONNECT) { fprintf(stdout, "\tReplying with password\n"); status->connected = 1; msg_header.data[1] = status->password; insert_header(recv_buf, msg_header); if (udp_send(recv_buf, status) < 0) { fprintf(stderr, "sendto()\n"); } } else { fprintf(stderr, "ERROR: Unexpected Command\n"); error = -2; } } else { fprintf(stderr, "ERROR: Incorrect Password\n"); } } else if (status->connected == 1) { if (check_pass(&msg_header, status->password)) { if (get_command(&msg_header) == CONNECT) { status->connected = 2; timeout_setup(status->udp_sock, timeout_0); fprintf(stdout, "\tConnected to a client\n"); } else { fprintf(stderr, "ERROR: Unexpected Command\n"); error = -2; } } else { fprintf(stderr, "ERROR: Incorrect Password\n"); error = -2; } } else { if (!check_pass(&msg_header, status->password)) { fprintf(stderr, "ERROR: Incorrect Password\n"); error = -2; } else { fprintf(stdout, "\t\tReceived Message:\n"); print_header(recv_buf); switch (get_command(&msg_header)) { case CONNECT: fprintf(stderr, "ERROR: Unexpected Command\n"); error = -2; break; case QUIT: quit(recv_buf, status); timeout_setup(status->udp_sock, timeout_0); break; default: error = request_command(recv_buf, status); break; } } } if (error == -2) { fprintf(stderr, "ERROR: Invalid client request\n"); send_error(status, CLIENT_ERROR); } else if (error == -1) { fprintf(stderr, "ERROR: Problem with http response\n"); send_error(status, HTTP_ERROR); } }
HTTP_Status server_dispatch(ArgumentList *al, task_t *tsk) { int thrindex = TASK_THRINDEX(tsk); int agg = 0; int nfound; HTTP_Status retcode = HTTP_NO_ERR; Request *hp = (Request *)TASK_DATA(tsk); #ifdef LOGGING struct loginfo *lo = hp->lo; #endif INST_set_thread_state(thrindex, THR_CACHE); /* * If we got here, we know the request is either GET or POST, * or this is a URL in the frontend's namespace */ tsk->task_age = 0; /* no pipe stages done yet */ /*if (*hp->url == '/' || strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/ if (is_server_url(hp->url)==gm_True) { /* this is a URL in the frontend's namespace, or an aggregator URL */ const char *workerName, *val; int val_len, len, to_copy, already_read; char *orig_hdrs, *eoh, *new_hdrs, *body; extern Options runtime_options; orig_hdrs = DistillerBufferData(&hp->cli_hdrs); eoh = strstr(orig_hdrs, "\r\n\r\n"); if (eoh==NULL) { retcode = HTTP_ERR_MALFORMED_REQUEST; goto DISPATCH_RETURN; } eoh += 4; /* clone the headers */ DistillerBufferAlloc(&hp->svr_hdrs, eoh-orig_hdrs+1); new_hdrs = DistillerBufferData(&hp->svr_hdrs); memcpy(new_hdrs, orig_hdrs, eoh-orig_hdrs); *(new_hdrs+(eoh-orig_hdrs)) = '\0'; DistillerBufferSetLength(&hp->svr_hdrs, eoh - orig_hdrs); DistillerBufferFreeMe(&hp->svr_hdrs, gm_True); /* * look for the content-length field; * if found, read the rest of the data and create svr_data */ if ((val = get_header_value(&hp->cli_hdrs, "content-length", &val_len, NULL, NULL)) != NULL) { len = strtoul(val, NULL, 0); if (len < 0) { retcode = HTTP_ERR_MALFORMED_REQUEST; goto DISPATCH_RETURN; } already_read = DistillerBufferLength(&hp->cli_hdrs) - (eoh - orig_hdrs); if (len <= already_read) { to_copy = len; } else { to_copy = already_read; } DistillerBufferAlloc(&hp->svr_data, len+1); body = DistillerBufferData(&hp->svr_data); memcpy(body, eoh, to_copy); /* get the rest of the data from the socket */ if (to_copy < len) { if (readline_or_timeout(hp, len - to_copy, body+to_copy) != (len-to_copy)) { retcode = HTTP_ERR_MALFORMED_REQUEST; goto DISPATCH_RETURN; } } /* add a trailing '\0' */ *(body+len) = '\0'; DistillerBufferSetLength(&hp->svr_data, len); } workerName = Options_Find(runtime_options, "frontend.myurl.dispatch"); if (workerName==NULL) workerName = "myurl/dispatch"; insert_header(&hp->svr_hdrs, "X-Route", workerName, 1); hp->svr_http_status = 200; /* everything's ok with this HTTP request */ } else { INST_timestamp(thrindex, m_cachestart); if (hp->method[0] == 'g' || hp->method[0] == 'G') { /* handle GET */ #ifdef OLD /* * HACK HACK HACK - this should be replaced with the real interface that * does a regexp match on URL to determine if any aggregator should get * dibs before the original content is fetched. * * Any references in this function to variable 'agg' represent a place * where the hack was spliced in. */ if (strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) != 0) { /* not an aggregator call */ #endif agg = 0; retcode = do_get(hp, al); if (retcode != HTTP_NO_ERR) { goto DISPATCH_RETURN; } #ifdef OLD } else { /* aggregator call */ abort(); agg = 1; /* don't clone the client headers - just point to them. */ DistillerBufferSetStatic(&hp->svr_hdrs, DistillerBufferData(&hp->cli_hdrs), DistillerBufferLength(&hp->cli_hdrs)); /* since we're pointing to a copy, don't try to free */ DistillerBufferFreeMe(&hp->svr_hdrs, gm_False); } #endif } else { /* handle POST */ retcode = do_post(hp, al); if (retcode != HTTP_NO_ERR) { /* post failed! report error to client */ goto DISPATCH_RETURN; } } INST_timestamp(thrindex, m_cachedone); /* * if there was an HTTP-level error (response code not "200"), bypass * the remainder straight to client. */ nfound = sscanf(DistillerBufferData(&hp->svr_hdrs), "%*s %lu", &hp->svr_http_status); if (nfound < 1) { /* no status found */ retcode = HTTP_ERR_GET_FAILED; hp->svr_http_status = 0; } else { retcode = HTTP_NO_ERR; } } #ifdef LOGGING lo->http_response = hp->svr_http_status;; /* log HTTP server response */ #endif /* LOGGING */ /* * Note that HTTP_NO_ERR means "transaction to server succeeded" (ie * at the transport level). it does NOT necessarily mean that the * HTTP *operation* (eg GET) succeeded -- the HTTP status code tells that. */ DISPATCH_RETURN: return retcode; }
DistillerStatus proxy_dispatch(ArgumentList *al, task_t *t) { DistillerStatus status; /* result of this pipe stage distillation */ DistillerInput din; DistillerOutput dout; Request *hp = (Request *)TASK_DATA(t); C_DistillerType dtype; int thrindex = TASK_THRINDEX(t); DistillerStatus retcode; int redispatch = 0; char *static_route = NULL; int static_route_initialized = 0; #ifdef LOGGING struct loginfo *lo = hp->lo; #endif /* * Initialize for *first* pipe stage. */ DistillerBufferClone(&din.data, &hp->svr_data); DistillerBufferFreeMe(&din.data, gm_True); /* * Make a **copy** of the server headers, because they may get * overwritten when preparing headers to send to a distiller. */ DistillerBufferClone(&din.metadata, &hp->svr_hdrs); DistillerBufferFreeMe(&din.metadata, gm_True); do { const char *char_tmp; char content_type[MIME_TYPE_MAX+1]; int content_type_len; Argument *arg; int num_tries_left; /* * Initialize for next pipe stage. */ status = distFatalError; #ifdef LOGGING /* * Log original content-length */ char_tmp = get_header_value(&din.metadata, "content-length", &content_type_len, NULL, NULL); if (char_tmp != NULL) lo->size_before = strtoul(char_tmp, NULL, 0); else lo->size_before = -1; #endif /* LOGGING */ char_tmp = get_header_value(&din.metadata, "content-type", &content_type_len, NULL, NULL); if (char_tmp != NULL) { strncpy(content_type, char_tmp, MIN(content_type_len+1, MIME_TYPE_MAX)); content_type[MIN(content_type_len,MIME_TYPE_MAX)] = '\0'; } else { content_type[0] = '\0'; } /* if there are attributes after the content-type, remove them. */ if ((char_tmp = strchr((const char *)content_type, ';')) != NULL) *(char *)char_tmp = '\0'; /* chop any trailing spaces. */ if ((char_tmp = strchr((const char *)content_type, ' ')) != NULL) *(char *)char_tmp = '\0'; /* * Distillation is definitely needed, so go do it. In case of * distConnectionBroken error, (re)try at most N * times, where N is the value of the FRONT_RETRY_DISTILL argument, * or PERF_HTTP_RETRY_DISTILL by default. In case of any other * error, or if all retries fail, bypass the original content. In * case of distOk (success), return the distilled content. */ arg = getArgumentFromIdInList(al, FRONT_RETRY_DISTILL); num_tries_left = (arg ? ARG_INT(*arg) : PERF_HTTP_RETRY_DISTILL); INST_timestamp(thrindex, m_distillstart); /* * Add a "Location:" header so distillers have a way to get the URL of * this document, if they want. */ if (get_header_value(&din.metadata, "location", NULL, NULL, NULL) == NULL) { insert_header(&din.metadata, "Location", hp->url, 0); } do { INST_set_thread_state(thrindex, THR_DISTILLER); status = do_distillation(hp->url, &din, &dout, &dtype, al); } while (status == distConnectionBroken && num_tries_left-- > 0); #ifdef LOGGING lo->size_after = -status; /* pessimistically assume failure for log */ #endif /* LOGGING */ switch(status) { case distOk: case distRedispatch: /* * The rules for redispatch are as follows. * - If the response headers contain a nonempty X-Static-Route header, it * is the final authority. X-Static-Route is only saved the * first time it's seen. * - Otherwise, if the response code is distRedispatch, use the * default rules to figure out who to go to next. * - Otherwise, the response is distOk --> just finish. */ if (! static_route_initialized && DistillerBufferLength(&dout.metadata) > 0) { /* look for X-Static-Route */ int tmp_len; const char *static_route_hdr = get_header_value(&dout.metadata, "x-static-route", &tmp_len, NULL, NULL); if (static_route_hdr != NULL && tmp_len > 0) { static_route = ALLOCA(tmp_len+1); strncpy(static_route, static_route_hdr, tmp_len); static_route[tmp_len] = '\0'; static_route_initialized = 1; delete_header(&dout.metadata, "x-static-route"); } } if (static_route || (status == distRedispatch && !static_route_initialized)) { /* * this is a redispatch. * The redispatch strategy is as follows. Since the * DistillerInput pointer starts out being a *clone* of the * server headers and data, it's always safe to free it. THen move the * DistillerOutput pointer (result of previous pipestage) to the * DistillerInput pointer of this pipestage. */ DistillerBufferFree(&din.metadata); DistillerBufferFree(&din.data); DistillerBufferClone(&din.metadata, &dout.metadata); DistillerBufferClone(&din.data, &dout.data); DistillerBufferFree(&dout.metadata); DistillerBufferFree(&dout.data); /* * Fix the content-length and content-type, if nec. */ if (get_header_value(&din.metadata, "content-type",NULL,NULL,NULL) == NULL) insert_header(&din.metadata, "Content-type", din.mimeType, 1); if (get_header_value(&din.metadata, "content-length", NULL,NULL,NULL) == NULL) { char __tmp[12]; snprintf(__tmp, 11, "%lu", DistillerBufferLength(&din.data)); insert_header(&din.metadata, "Content-length", __tmp, 1); } if (static_route) { status = distRedispatch; /* add the X-Route header to this request */ insert_header(&din.metadata, "X-Route", static_route, 1); /* scan forward to the next component of the path */ while (*static_route && (*static_route != ';')) { static_route++; } if (*static_route == '\0') { static_route = NULL; } else { /* skip semicolon and any spaces */ while (*static_route && ((*static_route == ';') || (*static_route == ' '))) { static_route++; } if (*static_route == '\0') static_route = NULL; } } redispatch++; t->task_age++; /* "time to live" of this request */ retcode = distRedispatch; } else { /* * Here if any of the following were true: * - status was distOk and no static route header overrides this * - status was distRedispatch, but an existing static route header * indicates that we should override and finish with */ #ifdef LOGGING lo->size_after = DistillerBufferLength(&dout.data); #endif /* LOGGING */ status = retcode = distOk; } break; default: /* some other distiller/ptm error */ /* * BUG::we shouldn't make this visible to the user unless the * "guru" argument is set */ snprintf(hp->errmsg, HTTP_ERRMSG_MAX, (char *)FE_getDistillerStatusString(status)); /* retcode = HTTP_ERR_DISTILLER; XXX - XXX - XXX - */ retcode = status; break; } /* switch(status) */ /* Note that the data size is set last. So if the data size is not zero, it's a reasonable indication that this is a compelte set of valid measurements. (should really have a separate valid bit) */ INST_set_size(thrindex, DistillerBufferLength(&dout.data)); } while ((status == distRedispatch) && t->task_age <= PERF_REQUEST_TTL); /* do */ /* * "Copy" final output buffer to hp->pxy_hdrs/hp->pxy_data. (Really * we just copy the pointers, since the pxy_hdrs/pxy_data buffers * will be freed by the caller.) * * First generate headers to return to client. If last-stage * distiller returned * some headers, use them; otherwise, replace the "content-length" * and "content-type" fields of the ORIGINAL server headers with * new values deduced from the distiller data. */ if (status == distOk) { if (DistillerBufferLength(&(dout.metadata)) > 0) { DistillerBufferClone(&hp->pxy_hdrs, &dout.metadata); } else { /* * If the server headers begin with an HTTP/x.x response code, they are * headers from an origin server; OK to clone them and just replace the * content-type and content-length. Otherwise, they are probably * the result of a server-mode dispatch worker, which means they * actually look like request headers (not response headers), so delete them. */ if (DistillerBufferLength(&hp->svr_hdrs) > 0 && strncasecmp(DistillerBufferData(&hp->svr_hdrs), "HTTP/", 5) == 0) { DistillerBufferClone(&hp->pxy_hdrs, &hp->svr_hdrs); delete_header(&hp->pxy_hdrs, "content-type"); delete_header(&hp->pxy_hdrs, "content-length"); } else { char *s = "HTTP/1.0 200 OK\r\n\r\n"; int l = strlen(s); DistillerBufferAlloc(&hp->pxy_hdrs, 1+l); strcpy((char *)(hp->pxy_hdrs.data), s); DistillerBufferSetLength(&hp->pxy_hdrs,l); } } /* * Replace the "Content-length" and "Content-type" * headers with the correct info. Leave other headers * alone. */ if (get_header_value(&hp->pxy_hdrs, "content-type", NULL,NULL,NULL) == NULL) { insert_header(&hp->pxy_hdrs, "Content-type", dout.mimeType, 1); } if (get_header_value(&hp->pxy_hdrs,"content-length",NULL,NULL,NULL) == NULL) { char __tmp[12]; snprintf(__tmp, 11, "%lu", DistillerBufferLength(&dout.data)); insert_header(&hp->pxy_hdrs, "Content-length", __tmp, 1); } DistillerBufferClone(&hp->pxy_data, &dout.data); } if ((status == distOk) || (status == distRedispatch)) { DistillerBufferFree(&dout.data); DistillerBufferFree(&dout.metadata); } /* Always free this */ DistillerBufferFree(&din.data); DistillerBufferFree(&din.metadata); /* BUG::must do Clib_Put here??? */ return (retcode); }
int rfc822_insert( RFC822 msg, char *line, size_t length ) { return msg->in_body? insert_body( msg, line, length ) : insert_header( msg, line, length ); }