Example #1
0
int match(const char * pload,int len,char ** source_path)
{
	const char* method;
  	size_t method_len;
  	const char* path;
  	size_t path_len;
  	int minor_version;
  	struct phr_header headers[HEADER_NUM];
    size_t num_headers = sizeof(headers) / sizeof(headers[0]);

    int re =phr_parse_request(pload,len, &method, &method_len, &path,&path_len, &minor_version, headers,&num_headers,0);  
    printf("~~~~%d~~~\n",re );
    if(re<=0)
    	return FALSE;

    // find_host
    int i;
    for(i=0;i<num_headers;i++)
    {
    	if (memcmp(headers[i].name,"Host",headers[i].name_len)==0)
    	{
    		int index = check_ini(headers[i].value,headers[i].value_len,path,path_len);
    		if(index!=-1)
    		{
    			*source_path = soft_array[index].source;
    			return TRUE;
    		}

    	}
    }
    return FALSE;


}
Example #2
0
// returns 1 on successful parsing, 0 on parsing incomplete, -1 on connection close
static int read_request(struct cs_io *cs_w) {
  const char *method, *path;
  int minor_version;
  struct phr_header headers[100];
  size_t method_len, path_len, num_headers;
  int pret;
  ssize_t rret;

  /* read the request */
  rret = recv(cs_w->io.fd, cs_w->buf + cs_w->len, sizeof cs_w->buf - cs_w->len, MSG_DONTWAIT);
  if (rret < 0) {
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return 0;
    die("recv");
  }
  if (rret == 0) {
    fprintf(stderr, "connection closed by peer, len = %d\n", sizeof cs_w->buf - cs_w->len);
    fflush(stderr);
    return -1;
  }
  cs_w->last_len = cs_w->len;
  cs_w->len += rret;
  num_headers = sizeof headers / sizeof headers[0];
  /* parse the request */
  pret = phr_parse_request(
    cs_w->buf,
    cs_w->len,
    &method,
    &method_len,
    &path,
    &path_len,
    &minor_version,
    headers,
    &num_headers,
    cs_w->last_len
  );
  // puts("finished parsing");
  if (pret > 0) {
    /* successfully parsed the request */
    cs_w->len = pret;
    setup_response(cs_w);
    // printf("response was setup: %d\n", cs_w->response_len);
    return 1;
  }
  if (pret == -1) {
    puts("parse error");
    exit(EXIT_FAILURE);
  }
  /* request is incomplete, continue the loop */
  assert(pret == -2);
  if (cs_w->len == sizeof cs_w->buf) {
    puts("request is too long");
    exit(EXIT_FAILURE);
  }
  return 0;
}
static void read_cb(picoev_loop* loop, int fd, int revents, void* cb_arg)
{
  char buf[16384];
  const char* method, * path;
  size_t method_len, path_len, num_headers;
  int minor_version, r;
  struct phr_header headers[128];
  
  /* read request */
  assert((revents & PICOEV_READ) != 0);
  r = read(fd, buf, sizeof(buf));
  if (r == 0) {
    goto CLOSE;
  } else if (r == -1) {
    if (errno == EINTR || errno == EAGAIN) {
      return;
    }
    goto CLOSE;
  }
  /* parse request, should arrive in one packat :-p */
  num_headers = sizeof(headers) / sizeof(headers[0]);
  r = phr_parse_request(buf, r, &method, &method_len, &path, &path_len,
			&minor_version, headers, &num_headers, 0);
  assert(r > 0);
  
#define RES "HTTP\1.0 200 OK\r\n" \
    "Connection: keep-alive\r\n" \
    "Content-Length: 13\r\n" \
    "Content-Type: text/plain\r\n" \
    "\r\n" \
    "hello world!\n"
  r = write(fd, RES, sizeof(RES) - 1);
  assert(r == sizeof(RES) - 1);
#undef RES
  
  return;
  
 CLOSE:
  picoev_del(loop, fd);
  close(fd);
}
Example #4
0
static void
on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
  if (nread < 0) {
    if (buf->base)
      free(buf->base);
    /* FIXME
    uv_shutdown_t* shutdown_req = (uv_shutdown_t*) malloc(sizeof(uv_shutdown_t));
    if (shutdown_req == NULL) {
      fprintf(stderr, "Allocate error\n");
      uv_close((uv_handle_t*) stream, on_close);
      return;
    }
    uv_shutdown(shutdown_req, stream, on_shutdown);
    */
    uv_close((uv_handle_t*) stream, on_close);
    return;
  }

  if (nread == 0) {
    free(buf->base);
    return;
  }

  http_request* request = calloc(1, sizeof(http_request));
  if (request == NULL) {
    free(buf->base);
    fprintf(stderr, "Allocate error: %s\n", strerror(errno));
    uv_close((uv_handle_t*) stream, on_close);
    return;
  }
  stream->data = request;

  request->handle = (uv_handle_t*) stream;

  request->num_headers = sizeof(request->headers) / sizeof(request->headers[0]);
  int nparsed = phr_parse_request(
          buf->base,
          buf->len,
          &request->method,
          &request->method_len,
          &request->path,
          &request->path_len,
          &request->minor_version,
          request->headers,
          &request->num_headers,
          0);
  if (nparsed < 0) {
    free(request);
    free(buf->base);
    fprintf(stderr, "Invalid request\n");
    uv_close((uv_handle_t*) stream, on_close);
    return;
  }
  /*
  int cl = content_length(request);
  if (cl >= 0 && cl < buf->len - nparsed) {
    free(request);
    free(buf->base);
    return;
  }
  */
  /* TODO: handle reading whole payload */
  request->payload = buf->base + nparsed;
  request->payload_len = buf->len - nparsed;
  request_complete(request);
  free(buf->base);
}
Example #5
0
File: http1.c Project: ifzz/h2o
static void handle_incoming_request(struct st_h2o_http1_conn_t *conn)
{
    size_t inreqlen = conn->sock->input->size < H2O_MAX_REQLEN ? conn->sock->input->size : H2O_MAX_REQLEN;
    int reqlen, minor_version;
    struct phr_header headers[H2O_MAX_HEADERS];
    size_t num_headers = H2O_MAX_HEADERS;
    ssize_t entity_body_header_index;
    h2o_iovec_t expect;

    /* need to set request_begin_at here for keep-alive connection */
    if (conn->req.timestamps.request_begin_at.tv_sec == 0)
        conn->req.timestamps.request_begin_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);

    reqlen = phr_parse_request(conn->sock->input->bytes, inreqlen, (const char **)&conn->req.input.method.base,
                               &conn->req.input.method.len, (const char **)&conn->req.input.path.base, &conn->req.input.path.len,
                               &minor_version, headers, &num_headers, conn->_prevreqlen);
    conn->_prevreqlen = inreqlen;

    switch (reqlen) {
    default: // parse complete
        conn->_reqsize = reqlen;
        if ((entity_body_header_index = fixup_request(conn, headers, num_headers, minor_version, &expect)) != -1) {
            conn->req.timestamps.request_body_begin_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
            if (expect.base != NULL) {
                if (!h2o_lcstris(expect.base, expect.len, H2O_STRLIT("100-continue"))) {
                    set_timeout(conn, NULL, NULL);
                    h2o_socket_read_stop(conn->sock);
                    h2o_send_error(&conn->req, 417, "Expectation Failed", "unknown expectation",
                                   H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION);
                    return;
                }
                static const h2o_iovec_t res = {H2O_STRLIT("HTTP/1.1 100 Continue\r\n\r\n")};
                h2o_socket_write(conn->sock, (void *)&res, 1, on_continue_sent);
            }
            if (create_entity_reader(conn, headers + entity_body_header_index) != 0) {
                return;
            }
            if (expect.base != NULL) {
                /* processing of the incoming entity is postponed until the 100 response is sent */
                h2o_socket_read_stop(conn->sock);
                return;
            }
            conn->_req_entity_reader->handle_incoming_entity(conn);
        } else {
            set_timeout(conn, NULL, NULL);
            h2o_socket_read_stop(conn->sock);
            process_request(conn);
        }
        return;
    case -2: // incomplete
        if (inreqlen == H2O_MAX_REQLEN) {
            // request is too long (TODO notify)
            close_connection(conn, 1);
        }
        return;
    case -1: // error
        /* upgrade to HTTP/2 if the request starts with: PRI * HTTP/2 */
        if (conn->super.ctx->globalconf->http1.upgrade_to_http2) {
            /* should check up to the first octet that phr_parse_request returns an error */
            static const h2o_iovec_t HTTP2_SIG = {H2O_STRLIT("PRI * HTTP/2")};
            if (conn->sock->input->size >= HTTP2_SIG.len && memcmp(conn->sock->input->bytes, HTTP2_SIG.base, HTTP2_SIG.len) == 0) {
                h2o_accept_ctx_t accept_ctx = {conn->super.ctx, conn->super.hosts};
                h2o_socket_t *sock = conn->sock;
                struct timeval connected_at = conn->super.connected_at;
                /* destruct the connection after detatching the socket */
                conn->sock = NULL;
                close_connection(conn, 1);
                /* and accept as http2 connection */
                h2o_http2_accept(&accept_ctx, sock, connected_at);
                return;
            }
        }
        close_connection(conn, 1);
        return;
    }
}
Example #6
0
static
int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
  const char* method;
  size_t method_len;
  const char* path;
  size_t path_len;
  int minor_version;
  struct phr_header headers[MAX_HEADERS];
  size_t num_headers, question_at;
  size_t i;
  int ret;
  char tmp[MAX_HEADER_NAME_LEN + sizeof("HTTP_") - 1];
  VALUE last_value;

  num_headers = MAX_HEADERS;
  ret = phr_parse_request(buf, buf_len, &method, &method_len, &path,
                          &path_len, &minor_version, headers, &num_headers, 0);
  if (ret < 0)
    goto done;

  rb_hash_aset(env, request_method_key, rb_str_new(method,method_len));
  rb_hash_aset(env, request_uri_key, rb_str_new(path, path_len));
  rb_hash_aset(env, script_name_key, rb_str_new2(""));
  strcpy(tmp, "HTTP/1.");
  tmp[7] = 48 + ((minor_version > 1 || minor_version < 0 ) ? 0 : minor_version);
  rb_hash_aset(env, server_protocol_key, rb_str_new(tmp, sizeof("HTTP/1.0") - 1));

  /* PATH_INFO QUERY_STRING */
  path_len = find_ch(path, path_len, '#'); /* strip off all text after # after storing request_uri */
  question_at = find_ch(path, path_len, '?');
  if ( store_path_info(env, path, question_at) < 0 ) {
    rb_hash_clear(env);
    ret = -1;
    goto done;
  }
  if (question_at != path_len) ++question_at;
  rb_hash_aset(env, query_string_key, rb_str_new(path + question_at, path_len - question_at));
  last_value = Qnil;
  for (i = 0; i < num_headers; ++i) {
    if (headers[i].name != NULL) {
      const char* name;
      size_t name_len;
      VALUE slot;
      VALUE env_key;
      env_key = find_common_header(headers + i);
      if ( env_key == Qnil ) {
        const char* s;
        char* d;
        size_t n;
        if (sizeof(tmp) - 5 < headers[i].name_len) {
          rb_hash_clear(env);
          ret = -1;
          goto done;
        }
        strcpy(tmp, "HTTP_");
        for (s = headers[i].name, n = headers[i].name_len, d = tmp + 5;
          n != 0;
          s++, --n, d++) {
            *d = *s == '-' ? '_' : TOU(*s);
            name = tmp;
            name_len = headers[i].name_len + 5;
            env_key = rb_str_new(name, name_len);
        }
      }
      slot = rb_hash_aref(env, env_key);
      if ( slot != Qnil ) {
        rb_str_cat2(slot, ", ");
        rb_str_cat(slot, headers[i].value, headers[i].value_len);
      } else {
        slot = rb_str_new(headers[i].value, headers[i].value_len);
        rb_hash_aset(env, env_key, slot);
        last_value = slot;
      }
    } else {
      /* continuing lines of a mulitiline header */
      if ( last_value != Qnil )
        rb_str_cat(last_value, headers[i].value, headers[i].value_len);
    }
  }

 done:
  return ret;
}