Exemplo n.º 1
0
static void
set_last_chunked_data(write_bucket *bucket)
{
    set2bucket(bucket, "0", 1);
    set2bucket(bucket, CRLF, 2);
    set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 2
0
inline void
add_content_length(http_connection *con, char *value, size_t value_len)
{
    data_bucket *bucket = con->bucket;
    set2bucket(bucket, CONTENT_LENGTH, LEN(CONTENT_LENGTH));
    set2bucket(bucket, value, value_len);
    set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 3
0
static void
set_chunked_data(write_bucket *bucket, char *lendata, size_t lenlen, char *data, size_t datalen)
{
    set2bucket(bucket, lendata, lenlen);
    set2bucket(bucket, CRLF, 2);
    set2bucket(bucket, data, datalen);
    set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 4
0
static void
add_header(write_bucket *bucket, char *key, size_t keylen, char *val, size_t vallen)
{
  set2bucket(bucket, key, keylen);
  set2bucket(bucket, DELIM, 2);
  set2bucket(bucket, val, vallen);
  set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 5
0
inline void
add_kt_xt(http_connection *con, char *value, size_t value_len)
{
    data_bucket *bucket = con->bucket;
    set2bucket(bucket, X_KT_XT, LEN(X_KT_XT));
    set2bucket(bucket, value, value_len);
    set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 6
0
inline void
add_header(http_connection *con, char *name, size_t name_len, char *value, size_t value_len)
{
    data_bucket *bucket = con->bucket;
    set2bucket(bucket, name, name_len);
    set2bucket(bucket, DELIM, 2);
    set2bucket(bucket, value, value_len);
    set2bucket(bucket, CRLF, 2);
}
Exemplo n.º 7
0
inline void
set_request_path(http_connection *con, char *method, size_t method_len, char *path, size_t path_len)
{
    data_bucket *bucket = con->bucket;
    
    //DEBUG("request URL %s", path);
    set2bucket(bucket, method, method_len);
    set2bucket(bucket, path, path_len);
    set2bucket(bucket, HTTP_11, LEN(HTTP_11));
    set2bucket(bucket, CONNECTION_KEEP_ALIVE, LEN(CONNECTION_KEEP_ALIVE));
}
Exemplo n.º 8
0
inline void
add_body(http_connection *con, char *value, size_t value_len)
{
    //DEBUG("HTTP BODY \n%.*s", value_len, value);
    data_bucket *bucket = con->bucket;
    set2bucket(bucket, value, value_len);
}
Exemplo n.º 9
0
static int
processs_write(client_t *client)
{
  VALUE iterator;
  VALUE v_body;
  VALUE item;
  char *buf;
  size_t buflen;
  write_bucket *bucket;
  int ret;

  // body
  iterator = client->response_iter;

  if(iterator != Qnil){
    if (TYPE(iterator) != T_ARRAY || RARRAY_LEN(iterator) != 3){
      return -1;
    }

    v_body = rb_ary_entry(iterator, 2);

    if(!rb_respond_to(v_body, i_each)){
      return -1;
    }

    VALUE v_body_str = rb_str_new2("");
    rb_block_call(v_body, i_each, 0, NULL, collect_body, v_body_str);
    if(rb_respond_to(v_body, i_close)) {
      rb_funcall(v_body, i_close, 0);
    }

    buf = StringValuePtr(v_body_str);
    buflen = RSTRING_LEN(v_body_str);

    bucket = new_write_bucket(client->fd, 1);
    set2bucket(bucket, buf, buflen);
    ret = writev_bucket(bucket);
    if(ret <= 0){
      return ret;
    }
    //mark
    client->write_bytes += buflen;
    //check write_bytes/content_length
    if(client->content_length_set){
      if(client->content_length <= client->write_bytes){
	// all done
	/* break; */
      }
    }
    close_response(client);
  }
  return 1;
}
Exemplo n.º 10
0
static void
set_first_body_data(client_t *client, char *data, size_t datalen)
{
    write_bucket *bucket = client->bucket;
    if(data){
        if(client->chunked_response){
            char *lendata  = NULL;
            Py_ssize_t len = 0;

            PyObject *chunk_data = get_chunk_data(datalen);
            //TODO CHECK ERROR
            PyBytes_AsStringAndSize(chunk_data, &lendata, &len);
            set_chunked_data(bucket, lendata, len, data, datalen);
            bucket->chunk_data = chunk_data;
        }else{
            set2bucket(bucket, data, datalen);
        }
    }
}
Exemplo n.º 11
0
inline void
set_rest_request_path(http_connection *con, PyObject *dbObj, char *method, size_t method_len, char *path, size_t path_len)
{
    data_bucket *bucket = con->bucket;
    
    //DEBUG("request URL %s", path);
    set2bucket(bucket, method, method_len);
    if(dbObj){
        char *db;
        Py_ssize_t db_len;
        PyString_AsStringAndSize(dbObj, &db, &db_len);
        set2bucket(bucket, "/", 1);
        set2bucket(bucket, db, db_len);
    }
    set2bucket(bucket, "/", 1);
    set2bucket(bucket, path, path_len);
    set2bucket(bucket, HTTP_11, LEN(HTTP_11));
    set2bucket(bucket, CONNECTION_KEEP_ALIVE, LEN(CONNECTION_KEEP_ALIVE));

}
Exemplo n.º 12
0
static int
add_status_line(write_bucket *bucket, client_t *client)
{
    PyObject *object;
    char *value = NULL;
    Py_ssize_t valuelen;

    object = client->http_status;
    //TODO ERROR CHECK
    if(object){
        DEBUG("add_status_line client %p", client);
        PyBytes_AsStringAndSize(object, &value, &valuelen);

        //write status code
        set2bucket(bucket, value, valuelen);

        add_header(bucket, "Server", 6,  SERVER, sizeof(SERVER) -1);
        //cache_time_update();
        add_header(bucket, "Date", 4, (char *)http_time, 29);
    }else{
        DEBUG("missing status_line %p", client);
    }
    return 1;
}
Exemplo n.º 13
0
static int
write_headers(client_t *client)
{
  if(client->header_done){
    return 1;
  }
  write_bucket *bucket;
  uint32_t i = 0, hlen = 0;

  VALUE arr;
  VALUE object;
  char *name = NULL;
  ssize_t namelen;
  char *value = NULL;
  long valuelen;

  if(client->headers){
    if (TYPE(client->headers) != T_HASH) {
      return -1;
    }
    arr = rb_funcall(client->headers, i_keys, 0);
    hlen = RARRAY_LEN(arr);
  }
  bucket = new_write_bucket(client->fd, ( hlen * 4 * 2) + 32 );
  
  object = client->http_status;

  if(TYPE(object) != T_STRING){
    return -1;
  }

  if(object){
    value = StringValuePtr(object);
    valuelen = RSTRING_LEN(object);
    //write status code
    set2bucket(bucket, value, valuelen);

    add_header(bucket, "Server", 6,  SERVER, sizeof(SERVER) -1);
    cache_time_update();
    add_header(bucket, "Date", 4, (char *)http_time, 29);
    if(client->keep_alive == 1){
      // Keep-Alive
      add_header(bucket, "Connection", 10, "Keep-Alive", 10);
    } else {
      add_header(bucket, "Connection", 10, "close", 5);
    }
  }

  VALUE object1, object2;
  
  //write header
  if(client->headers){
    for(i=0; i < hlen; i++){
      object1 = rb_ary_entry(arr, i);
      Check_Type(object1, T_STRING);

      if (TYPE(client->headers)!=T_HASH){
	goto error;
      }
      VALUE tmp = rb_funcall(client->headers, i_key, 1, object1);
      if (tmp == Qfalse){
	goto error;
      }
      object2 = rb_hash_aref(client->headers, object1);

      Check_Type(object2, T_STRING);
      
      name = StringValuePtr(object1);
      namelen = RSTRING_LEN(object1);
  
      value = StringValuePtr(object2);
      valuelen = RSTRING_LEN(object2);

      if (strchr(name, '\n') != 0 || strchr(value, '\n') != 0) {
	rb_raise(rb_eArgError, "embedded newline in response header and value");
      }
      
      if (!strcasecmp(name, "Server") || !strcasecmp(name, "Date")) {
 	continue;
      }
      
      if (!strcasecmp(name, "Content-Length")) {
	char *v = value;
	long l = 0;
	
	errno = 0;
	l = strtol(v, &v, 10);
	if (*v || errno == ERANGE || l < 0) {
	  rb_raise(rb_eArgError, "invalid content length");
	  goto error;
	}
	client->content_length_set = 1;
	client->content_length = l;
      }
    add_header(bucket, name, namelen, value, valuelen);
    }
  }
  set2bucket(bucket, CRLF, 2);

  client->bucket = bucket;
  int ret = writev_bucket(bucket);
  if(ret != 0){
    client->header_done = 1;
    // clear
    free_write_bucket(bucket);
    client->bucket = NULL;
  }
  return ret;
 error:
  /* write_error_log(__FILE__, __LINE__); */
  if(bucket){
    free_write_bucket(bucket);
    client->bucket = NULL;
  }
  return -1;
}
Exemplo n.º 14
0
inline void
add_header_oneline(http_connection *con, char *value, size_t value_len)
{
    data_bucket *bucket = con->bucket;
    set2bucket(bucket, value, value_len);
}
Exemplo n.º 15
0
inline void
add_crlf(http_connection *con)
{
    set2bucket(con->bucket, CRLF, 2);
}
Exemplo n.º 16
0
static response_status
process_write(client_t *client)
{
    PyObject *iterator = NULL;
    PyObject *item, *chunk_data = NULL;
    char *buf = NULL, *lendata = NULL;
    Py_ssize_t buflen, len;
    write_bucket *bucket = NULL;
    response_status ret;
    
    DEBUG("process_write start");
    iterator = client->response_iter;
    if(iterator != NULL){
        while((item =  PyIter_Next(iterator))){
            if(PyBytes_Check(item)){
                //TODO CHECK
                PyBytes_AsStringAndSize(item, &buf, &buflen);
                //write
                if(client->chunked_response){
                    bucket = new_write_bucket(client->fd, 4);
                    if(bucket == NULL){
                        /* write_error_log(__FILE__, __LINE__); */
                        call_error_logger();
                        Py_DECREF(item);
                        return STATUS_ERROR;
                    }
                    lendata  = NULL;
                    len = 0;

                    chunk_data = get_chunk_data(buflen);
                    //TODO CHECK ERROR
                    PyBytes_AsStringAndSize(chunk_data, &lendata, &len);
                    set_chunked_data(bucket, lendata, len, buf, buflen);
                    bucket->chunk_data = chunk_data;
                }else{
                    bucket = new_write_bucket(client->fd, 1);
                    if(bucket == NULL){
                        /* write_error_log(__FILE__, __LINE__); */
                        call_error_logger();
                        Py_DECREF(item);
                        return STATUS_ERROR;
                    }
                    set2bucket(bucket, buf, buflen);
                }
                bucket->temp1 = item;
                ret = writev_bucket(bucket);
                if(ret != STATUS_OK){
                    client->bucket = bucket;
                    /* Py_DECREF(item); */
                    return ret;
                }

                free_write_bucket(bucket);
                //mark
                client->write_bytes += buflen;
                //check write_bytes/content_length
                if(client->content_length_set){
                    if(client->content_length <= client->write_bytes){
                        // all done
                        /* Py_DECREF(item); */
                        break;
                    }
                }
                /* Py_DECREF(item); */
            }else{
                PyErr_SetString(PyExc_TypeError, "response item must be a byte string");
                Py_DECREF(item);
                if (PyErr_Occurred()){
                    /* client->bad_request_code = 500; */
                    client->status_code = 500;
                    /* write_error_log(__FILE__, __LINE__); */
                    call_error_logger();
                    return STATUS_ERROR;
                }
            }
        }
        if(PyErr_Occurred()){
            return STATUS_ERROR;
        }
        if(client->chunked_response){
            DEBUG("write last chunk");
            //last packet
            bucket = new_write_bucket(client->fd, 3);
            if(bucket == NULL){
                /* write_error_log(__FILE__, __LINE__); */
                call_error_logger();
                return STATUS_ERROR;
            }
            set_last_chunked_data(bucket);
            writev_bucket(bucket);
            free_write_bucket(bucket);
        }
        return close_response(client);
    }
    return STATUS_OK;
}
Exemplo n.º 17
0
static response_status
write_headers(client_t *client, char *data, size_t datalen, char is_file)
{
    write_bucket *bucket; 
    uint32_t hlen = 0;
    PyObject *headers = NULL, *templist = NULL;
    response_status ret;
    
    DEBUG("header write? %d", client->header_done);
    if(client->header_done){
        return STATUS_OK;
    }

    //TODO ERROR CHECK
    headers = PySequence_Fast(client->headers, "header must be list");
    hlen = PySequence_Fast_GET_SIZE(headers);

    bucket = new_write_bucket(client->fd, (hlen * 4) + 42 );

    if(bucket == NULL){
        goto error;
    }
    templist = PyList_New(hlen * 4);
    bucket->temp1 = templist;

    if(add_status_line(bucket, client) == -1){
        goto error;
    }
    //write header
    if(add_all_headers(bucket, headers, hlen, client) == -1){
        //Error
        goto error;
    }
    
    // check content_length_set
    if(data && !client->content_length_set && client->http_parser->http_minor == 1){
        //Transfer-Encoding chunked
        add_header(bucket, "Transfer-Encoding", 17, "chunked", 7);
        client->chunked_response = 1;
    }

    if (is_file && !client->content_length_set){
        if (set_file_content_length(client, bucket) == -1) {
            goto error;
        }
    }

    if(client->keep_alive == 1){
        //Keep-Alive
        add_header(bucket, "Connection", 10, "Keep-Alive", 10);
    }else{
        add_header(bucket, "Connection", 10, "close", 5);
    }
    
    set2bucket(bucket, CRLF, 2);

    //write body
    client->bucket = bucket;
    set_first_body_data(client, data, datalen);

    ret = writev_bucket(bucket);
    if(ret != STATUS_SUSPEND){
        client->header_done = 1;
        if(ret == STATUS_OK && data){
            client->write_bytes += datalen;
        }
        // clear
        free_write_bucket(bucket);
        client->bucket = NULL;
    }

    Py_DECREF(headers);
    return ret;
error:
    if (PyErr_Occurred()){
        /* write_error_log(__FILE__, __LINE__); */
        call_error_logger();
    }
    Py_XDECREF(headers);
    if(bucket){
        free_write_bucket(bucket);
        client->bucket = NULL;
    }
    return STATUS_ERROR;
}