static int
rest_stream_data(noit_http_rest_closure_t *restc,
                 int npats, char **pats) {
  /* We're here and want to subvert the rest system */
  const char *document_domain = NULL;
  noit_http_session_ctx *ctx = restc->http_ctx;
  noit_http_connection *conn = noit_http_session_connection(ctx);
  eventer_t e;
  acceptor_closure_t *ac = restc->ac;

  /* Rewire the handler */
  if(ac->service_ctx_free)
    ac->service_ctx_free(ac->service_ctx);
  ac->service_ctx = ctx;
  ac->service_ctx_free = noit_http_ctx_acceptor_free;

  if(!noit_hash_retr_str(ac->config,
                         "document_domain", strlen("document_domain"),
                         &document_domain)) {
    noitL(noit_error, "Document domain not set!  Realtime streaming will be broken\n");
    document_domain = "";
  }

  noit_http_process_querystring(noit_http_session_request(ctx));
  /* Rewire the http context */
  e = noit_http_connection_event(conn);
  e->callback = stratcon_realtime_http_handler;
  noit_http_session_set_dispatcher(ctx, stratcon_request_dispatcher,
                                   alloc_realtime_context(document_domain));
  return stratcon_request_dispatcher(ctx);
}
예제 #2
0
noit_boolean
noit_http_rest_client_cert_auth(noit_http_rest_closure_t *restc,
                               int npats, char **pats) {
  struct noit_rest_acl *acl;
  struct noit_rest_acl_rule *rule;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);
  const char *uri_str;
  const char *remote_cn = "";
  int ovector[30];

  if(restc->remote_cn) remote_cn = restc->remote_cn;
  uri_str = noit_http_request_uri_str(req);
  for(acl = global_rest_acls; acl; acl = acl->next) {
    if(acl->cn && pcre_exec(acl->cn, NULL, remote_cn, 0, 0, 0,
                            ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
      continue;
    if(acl->url && pcre_exec(acl->url, NULL, uri_str, strlen(uri_str), 0, 0,
                             ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
      continue;
    for(rule = acl->rules; rule; rule = rule->next) {
      if(rule->cn && pcre_exec(rule->cn, NULL, remote_cn, 0, 0, 0,
                               ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
        continue;
      if(rule->url && pcre_exec(rule->url, NULL, uri_str, strlen(uri_str), 0, 0,
                                ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
        continue;
      return rule->allow;
    }
    return acl->allow;
  }
  return noit_false;
}
예제 #3
0
static rest_request_handler
noit_http_get_handler(noit_http_rest_closure_t *restc) {
  struct rule_container *cont = NULL;
  struct rest_url_dispatcher *rule;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);
  const char *uri_str;
  const char *eoq, *eob;
  uri_str = noit_http_request_uri_str(req);
  eoq = strchr(uri_str, '?');
  if(!eoq)
    eoq = uri_str + strlen(uri_str);
  eob = eoq - 1;

  /* find the right base */
  while(1) {
    void *vcont;
    while(eob >= uri_str && *eob != '/') eob--;
    if(eob < uri_str) break; /* off the front */
    if(noit_hash_retrieve(&dispatch_points, uri_str,
                          eob - uri_str + 1, &vcont)) {
      cont = vcont;
      eob++; /* move past the determined base */
      break;
    }
    eob--;
  }
  if(!cont) return NULL;
  for(rule = cont->rules; rule; rule = rule->next) {
    int ovector[30];
    int cnt;
    if(strcmp(rule->method, noit_http_request_method_str(req))) continue;
    if((cnt = pcre_exec(rule->expression, rule->extra, eob, eoq - eob, 0, 0,
                        ovector, sizeof(ovector)/sizeof(*ovector))) > 0) {
      /* We match, set 'er up */
      restc->fastpath = rule->handler;
      restc->nparams = cnt - 1;
      if(restc->nparams) {
        restc->params = calloc(restc->nparams, sizeof(*restc->params));
        for(cnt = 0; cnt < restc->nparams; cnt++) {
          int start = ovector[(cnt+1)*2];
          int end = ovector[(cnt+1)*2+1];
          restc->params[cnt] = malloc(end - start + 1);
          memcpy(restc->params[cnt], eob + start, end - start);
          restc->params[cnt][end - start] = '\0';
        }
      }
      if(rule->auth && !rule->auth(restc, restc->nparams, restc->params))
        return noit_http_rest_permission_denied;
      return restc->fastpath;
    }
  }
  return NULL;
}
예제 #4
0
int
noit_rest_eventer_logs(noit_http_rest_closure_t *restc, int n, char **p) {
  char *endptr = NULL;
  const char *since_s, *last_s;
  const char *jsonstr;
  char errbuf[128];
  unsigned long long since;
  int last = 0;
  struct json_object *doc;
  noit_log_stream_t ls;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);
  since_s = noit_http_request_querystring(req, "since");
  if(since_s) since = strtoull(since_s, &endptr, 10);
  last_s = noit_http_request_querystring(req, "last");
  if(last_s) last = atoi(last_s);

  assert(n==1);
  ls = noit_log_stream_find(p[0]);
  if(!ls || strcmp(noit_log_stream_get_type(ls),"memory"))
    goto not_found;

  doc = json_object_new_array();
  if(endptr != since_s)
    noit_log_memory_lines_since(ls, since, json_spit_log, doc);
  else
    noit_log_memory_lines(ls, last, json_spit_log, doc);

  noit_http_response_ok(restc->http_ctx, "application/json");
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
 not_found:
  doc = json_object_new_object();
  snprintf(errbuf, sizeof(errbuf), "log '%s' not found", p[0]);
  json_object_object_add(doc, "error", json_object_new_string(errbuf));
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_not_found(restc->http_ctx, "application/json");
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
}
예제 #5
0
void *
rest_get_raw_upload(noit_http_rest_closure_t *restc,
                    int *mask, int *complete, int *size) {
  struct rest_raw_payload *rxc;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);

  *size = 0;
  if(restc->call_closure == NULL) {
    restc->call_closure = calloc(1, sizeof(*rxc));
    restc->call_closure_free = rest_raw_payload_free;
  }
  rxc = restc->call_closure;
  while(!rxc->complete) {
    int len;
    if(rxc->len == rxc->allocd) {
      char *b;
      rxc->allocd += 32768;
      b = rxc->buffer ? realloc(rxc->buffer, rxc->allocd) :
                        malloc(rxc->allocd);
      if(!b) {
        *complete = 1;
        return NULL;
      }
      rxc->buffer = b;
    }
    len = noit_http_session_req_consume(restc->http_ctx,
                                        rxc->buffer + rxc->len,
                                        rxc->allocd - rxc->len,
                                        rxc->allocd - rxc->len,
                                        mask);
    if(len > 0) rxc->len += len;
    if(len < 0 && errno == EAGAIN) return NULL;
    else if(len < 0) {
      *complete = 1;
      return NULL;
    }
    if(rxc->len == noit_http_request_content_length(req)) {
      *size = rxc->len;
      rxc->complete = 1;
    }
  }

  *complete = 1;
  return rxc->buffer;
}
int
stratcon_request_dispatcher(noit_http_session_ctx *ctx) {
  const char *key, *value;
  realtime_context *rc = noit_http_session_dispatcher_closure(ctx);
  int klen;
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  noit_http_request *req = noit_http_session_request(ctx);

  if(rc->setup == RC_INITIAL) {
    eventer_t completion;
    struct realtime_tracker *node;
    char c[1024];
    int num_interests;
    const char *uri_str = noit_http_request_uri_str(req);
    noit_hash_table *headers = noit_http_request_headers_table(req);

    num_interests = stratcon_realtime_uri_parse(rc, uri_str);
    if(num_interests == 0) {
      noit_http_response_status_set(ctx, 404, "OK");
      noit_http_response_option_set(ctx, NOIT_HTTP_CLOSE);
      noit_http_response_end(ctx);
      return 0;
    }

    noitL(noit_error, "http: %s %s %s\n",
          noit_http_request_method_str(req), uri_str,
          noit_http_request_protocol_str(req));
    while(noit_hash_next_str(headers, &iter, &key, &klen, &value)) {
      noitL(noit_error, "http: [%s: %s]\n", key, value);
    }
    noit_http_response_status_set(ctx, 200, "OK");
    noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED);
    /*noit_http_response_option_set(ctx, NOIT_HTTP_GZIP);*/
    /*noit_http_response_option_set(ctx, NOIT_HTTP_DEFLATE);*/
    noit_http_response_header_set(ctx, "Content-Type", "text/html");

    snprintf(c, sizeof(c),
             "<html><head><script>document.domain='%s';</script></head><body>\n",
             rc->document_domain);
    noit_http_response_append(ctx, c, strlen(c));

    /* this dumb crap is to make some browsers happy (Safari) */
    memset(c, ' ', sizeof(c));
    noit_http_response_append(ctx, c, sizeof(c));
    noit_http_response_flush(ctx, noit_false);

    rc->setup = RC_REQ_RECV;
    /* Each interest references the ctx */
    for(node = rc->checklist; node; node = node->next) {
      char uuid_str[UUID_STR_LEN+1];
      noit_http_session_ref_inc(ctx);
      uuid_unparse_lower(node->checkid, uuid_str);
      noitL(noit_error, "Resolving uuid: %s\n", uuid_str);
    }
    completion = eventer_alloc();
    completion->mask = EVENTER_TIMER;
    completion->callback = stratcon_realtime_http_postresolve;
    completion->closure = ctx;
    gettimeofday(&completion->whence, NULL);
    stratcon_datastore_push(DS_OP_FIND_COMPLETE, NULL, NULL,
                            rc->checklist, completion);
  }
  return EVENTER_EXCEPTION;
}
int
stratcon_line_to_javascript(noit_http_session_ctx *ctx, char *in_buff,
                            u_int32_t *inc_id) {
  char buffer[1024];
  char *scp, *ecp, *token, *buff;
  int i, len, cnt;
  const char *v, *cb = NULL;
  noit_hash_table json = NOIT_HASH_EMPTY;
  noit_http_request *req = noit_http_session_request(ctx);
  char s_inc_id[42];
  char **outrows = NULL;

  cb = noit_http_request_querystring(req, "cb"); 
  for(v = cb; v && *v; v++)
    if(!((*v >= '0' && *v <= '9') ||
         (*v >= 'a' && *v <= 'z') ||
         (*v >= 'A' && *v <= 'Z') ||
         (*v == '_') || (*v == '.'))) {
      cb = NULL;
      break;
    }
  if(!cb) cb = "window.parent.plot_iframe_data";

#define BAIL_HTTP_WRITE do { \
  if(outrows) { \
    for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]); \
    free(outrows); \
  } \
  noit_hash_destroy(&json, NULL, free); \
  noitL(noit_error, "javascript emit failed: %s:%s:%d\n", \
        __FILE__, __FUNCTION__, __LINE__); \
  return -1; \
} while(0)

#define PROCESS_NEXT_FIELD(t,l) do { \
  if(!*scp) goto bad_row; \
  ecp = strchr(scp, '\t'); \
  if(!ecp) goto bad_row; \
  t = scp; \
  l = (ecp-scp); \
  scp = ecp + 1; \
} while(0)
#define PROCESS_LAST_FIELD(t,l) do { \
  if(!*scp) ecp = scp; \
  else { \
    ecp = scp + strlen(scp); /* Puts us at the '\0' */ \
    if(*(ecp-1) == '\n') ecp--; /* We back up on letter if we ended in \n */ \
  } \
  t = scp; \
  l = (ecp-scp); \
} while(0)

  noitL(noit_error, "recv(%s)\n", in_buff);
  if(in_buff[0] == 'B' && in_buff[1] != '\0' && in_buff[2] == '\t') {
    cnt = noit_check_log_b_to_sm(in_buff, strlen(in_buff), &outrows);
  }
  else {
    cnt = 1;
    outrows = malloc(sizeof(*outrows));
    outrows[0] = strdup(in_buff);
  }
  for(i=0; i<cnt; i++) {
    buff = outrows[i];
    if(!buff) continue;
    noitL(noit_error, "recv_xlt(%s)\n", buff);
    scp = buff;
    PROCESS_NEXT_FIELD(token,len); /* Skip the leader */
    if(buff[1] == '\t' && (buff[0] == 'M' || buff[0] == 'S')) {
      char target[256], module[256], name[256], uuid_str[UUID_STR_LEN+1];
      noit_http_request *req = noit_http_session_request(ctx);
      noit_hash_table *qs;
      noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
      const char *key;
      int klen, i=0;
      void *vval;
      char type[2] = { '\0', '\0' };
      type[0] = buff[0];

#define ra_write(a,b) if(noit_http_response_append(ctx, a, b) == noit_false) BAIL_HTTP_WRITE

      snprintf(s_inc_id, sizeof(s_inc_id), "script-%08x", (*inc_id)++);
      snprintf(buffer, sizeof(buffer), "<script id=\"%s\">%s({", s_inc_id, cb);
      ra_write(buffer, strlen(buffer));

      qs = noit_http_request_querystring_table(req);
      while(noit_hash_next(qs, &iter, &key, &klen, &vval)) {
        if(!strcmp(key, "cb")) continue;
        noit_hash_store(&json, key, klen, strdup(vval ?(char *)vval : "true"));
      }
      /* Time */
      noit_hash_store(&json, "script_id", 9, strdup(s_inc_id));
      noit_hash_store(&json, "type", 4, strdup(type));
      PROCESS_NEXT_FIELD(token,len);
      noit_hash_store(&json, "time", 4, noit__strndup(token, len));
      /* UUID */
      PROCESS_NEXT_FIELD(token,len);
      noit_check_extended_id_split(token, len, target, sizeof(target),
                                   module, sizeof(module), name, sizeof(name),
                                   uuid_str, sizeof(uuid_str));
      if(*uuid_str)
        noit_hash_store(&json, "id", 2,
                        noit__strndup(uuid_str, strlen(uuid_str)));
      if(*target)
        noit_hash_store(&json, "check_target", 12,
                        noit__strndup(target, strlen(target)));
      if(*module)
        noit_hash_store(&json, "check_module", 12,
                        noit__strndup(module, strlen(module)));
      if(*name)
        noit_hash_store(&json, "check_name", 10,
                        noit__strndup(name, strlen(name)));
      if(buff[0] == 'M') {
        /* name */
        PROCESS_NEXT_FIELD(token,len);
        noit_hash_store(&json, "metric_name", 11, noit__strndup(token, len));
        /* type */
        PROCESS_NEXT_FIELD(token,len);
        noit_hash_store(&json, "metric_type", 11, noit__strndup(token, len));
        /* value */
        PROCESS_LAST_FIELD(token,len); /* value */
        noit_hash_store(&json, "value", 5, noit__strndup(token, len));
      }
      else if(buff[0] == 'S') {
        /* state */
        PROCESS_NEXT_FIELD(token,len);
        noit_hash_store(&json, "check_state", 11, noit__strndup(token, len));
        /* availability */
        PROCESS_NEXT_FIELD(token,len);
        noit_hash_store(&json, "check_availability", 18, noit__strndup(token, len));
        /* duration */
        PROCESS_NEXT_FIELD(token,len);
        noit_hash_store(&json, "check_duration_ms", 17, noit__strndup(token, len));
        /* status */
        PROCESS_LAST_FIELD(token,len);
        noit_hash_store(&json, "status_message", 14, noit__strndup(token, len));
      }

      memset(&iter, 0, sizeof(iter));
      while(noit_hash_next(&json, &iter, &key, &klen, &vval)) {
        char *val = (char *)vval;
        if(i++) ra_write(",", 1);
        ra_write("\"", 1);
        ra_write(key, klen);
        ra_write("\":\"", 3);
        while(*val) {
          if(*val == '\"' || *val == '\\') {
            ra_write((char *)"\\", 1);
          }
          if(isprint(*val)) {
            ra_write((char *)val, 1);
          }
          else {
            char od[5];
            snprintf(od, sizeof(od), "\\%03o", *((unsigned char *)val));
            ra_write(od, strlen(od));
          }
          val++;
        }
        ra_write("\"", 1);
      }
      snprintf(buffer, sizeof(buffer), "});</script>\n");
      ra_write(buffer, strlen(buffer));

      if(noit_http_response_flush(ctx, noit_false) == noit_false) BAIL_HTTP_WRITE;
    }

    noit_hash_destroy(&json, NULL, free);
    memset(&json, 0, sizeof(json));
  }
  if(outrows) {
    for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]);
    free(outrows);
  }

  return 0;

 bad_row:
  BAIL_HTTP_WRITE;
}
예제 #8
0
static int
noit_http_ctx_index_func(lua_State *L) {
  OO_LUA_DECL(L, noit_http_session_ctx, http_ctx, k);
  switch(*k) {
    case 'C':
      if(!strcmp(k, "CHUNKED")) {
        lua_pushinteger(L, NOIT_HTTP_CHUNKED);
        return 1;
      }
      if(!strcmp(k, "CLOSE")) {
        lua_pushinteger(L, NOIT_HTTP_CLOSE);
        return 1;
      }
      break;
    case 'D':
      if(!strcmp(k, "DEFATE")) {
        lua_pushinteger(L, NOIT_HTTP_DEFLATE);
        return 1;
      }
      break;
    case 'G':
      if(!strcmp(k, "GZIP")) {
        lua_pushinteger(L, NOIT_HTTP_GZIP);
        return 1;
      }
      break;
    case 'f':
      if(!strcmp(k, "flush")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_flush, 1);
        return 1;
      }
      if(!strcmp(k, "flush_end")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_flush_and_end, 1);
        return 1;
      }
      break;
    case 'h':
      if(!strcmp(k, "htmlentities")) {
        lua_getglobal(L, "noit");
        lua_getfield(L, -1, "utf8tohtml");
        lua_remove(L, -2);  /* pop noit */
        return 1;
      }
      if(!strcmp(k, "header")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_header_set, 1);
        return 1;
      }
      break;
    case 'o':
      if(!strcmp(k, "option")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_option_set, 1);
        return 1;
      }
      break;
    case 'r':
      if(!strcmp(k, "request")) {
        lua_pushlightuserdata(L, noit_http_session_request(http_ctx));
        lua_pushcclosure(L, noit_lua_http_request_func, 1);
        return 1;
      }
      if(!strcmp(k, "response")) {
        return 0;
      }
      break;
    case 's':
      if(!strcmp(k, "status")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_status_set, 1);
        return 1;
      }
      if(!strcmp(k, "set_cookie")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_set_cookie, 1);
        return 1;
      }
      break;
    case 'u':
      if(!strcmp(k, "url_decode")) {
        lua_pushcclosure(L, noit_lua_http_url_decode, 0);
        return 1;
      }
      if(!strcmp(k, "url_encode")) {
        lua_pushcclosure(L, noit_lua_http_url_encode, 0);
        return 1;
      }
      break;
    case 'w':
      if(!strcmp(k, "write")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_write, 1);
        return 1;
      }
      if(!strcmp(k, "write_fd")) {
        lua_pushlightuserdata(L, http_ctx);
        lua_pushcclosure(L, noit_lua_http_write_fd, 1);
        return 1;
      }
      break;
    default:
      break;
  }
  luaL_error(L, "noit_http_session_ctx no such element: %s", k);
  return 0;
}