/// Delete all existing copies of a header and replace with a new one. /// The header to delete must not be one that has an abbreviation. void PJUtils::set_generic_header(pjsip_tx_data* tdata, const pj_str_t* name, const pj_str_t* value) { delete_header(tdata->msg, name); pjsip_generic_string_hdr* new_hdr = pjsip_generic_string_hdr_create(tdata->pool, name, value); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)new_hdr); }
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); } }
t_header parser_header(t_line **file, int comment, int name) { t_header result; int line; line = 0; result.prog_size = (*file)->size; result.magic = COREWAR_EXEC_MAGIC; while (++line && token_header((*file)->line->token)) { if ((*file)->line->token == COMMAND_NAME && name--) parser_name(result.name, (*file)); else if ((*file)->line->token == COMMAND_COMMENT && comment--) parser_comment(result.comment, (*file)); else if ((*file)->line->token != ENDLINE) print_error_token((*file), (*file)->line, SYNTAX_MSG); (*file) = (*file)->next; } if (name || comment) print_error_token((*file), (*file)->line, SYNTAX_MSG); (*file) = delete_header((*file)->start, line); return (result); }
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); }