示例#1
0
/// 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);
}
示例#2
0
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);
  }
}
示例#3
0
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);
}
示例#4
0
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);
}