http.c

来自「mms client」· C语言 代码 · 共 2,402 行 · 第 1/5 页

C
2,402
字号
        gwthread_wakeup(server_thread_id);        gwthread_join_every(server_thread);        fdset_destroy(server_fdset);        server_fdset = NULL;    }}/* * Parse CGI variables from the path given in a GET. Return a list * of HTTPCGIvar pointers. Modify the url so that the variables are * removed. */static List *parse_cgivars(Octstr *url) {    HTTPCGIVar *v;    List *list;    int query, et, equals;    Octstr *arg, *args;    query = octstr_search_char(url, '?', 0);    if (query == -1)        return list_create();    args = octstr_copy(url, query + 1, octstr_len(url));    octstr_truncate(url, query);    list = list_create();    while (octstr_len(args) > 0) {        et = octstr_search_char(args, '&', 0);        if (et == -1)            et = octstr_len(args);        arg = octstr_copy(args, 0, et);        octstr_delete(args, 0, et + 1);        equals = octstr_search_char(arg, '=', 0);        if (equals == -1)            equals = octstr_len(arg);        v = gw_malloc(sizeof(HTTPCGIVar));        v->name = octstr_copy(arg, 0, equals);        v->value = octstr_copy(arg, equals + 1, octstr_len(arg));        octstr_url_decode(v->name);        octstr_url_decode(v->value);        octstr_destroy(arg);        list_append(list, v);    }    octstr_destroy(args);    return list;}HTTPClient *http_accept_request(int port, Octstr **client_ip, Octstr **url,                                 List **headers, Octstr **body,                                 List **cgivars) {    HTTPClient *client;    client = port_get_request(port);    if (client == NULL) {        debug("gwlib.http", 0, "HTTP: No clients with requests, quitting.");        return NULL;    }    *client_ip = octstr_duplicate(client->ip);    *url = client->url;    *headers = client->request->headers;    *body = client->request->body;    *cgivars = parse_cgivars(client->url);    if (client->method != HTTP_METHOD_POST) {        octstr_destroy(*body);        *body = NULL;    }    client->persistent_conn = client_is_persistent(client->request->headers,                                                   client->use_version_1_0);    client->url = NULL;    client->request->headers = NULL;    client->request->body = NULL;    entity_destroy(client->request);    client->request = NULL;    return client;}void http_send_reply(HTTPClient *client, int status, List *headers,                      Octstr *body) {    Octstr *response;    long i;    int ret;    if (client->use_version_1_0)        response = octstr_format("HTTP/1.0 %d Foo\r\n", status);    else        response = octstr_format("HTTP/1.1 %d Foo\r\n", status);    /* identify ourselfs */    octstr_format_append(response, "Server: " GW_NAME "/%s\r\n", VERSION);    octstr_format_append(response, "Content-Length: %ld\r\n",                         octstr_len(body));    /*      * RFC2616, sec. 8.1.2.1 says that if the server chooses to close the      * connection, it *should* send a coresponding header     */    if (!client->use_version_1_0 && !client->persistent_conn)        octstr_format_append(response, "Connection: close\r\n");    for (i = 0; i < list_len(headers); ++i)        octstr_format_append(response, "%S\r\n", list_get(headers, i));    octstr_format_append(response, "\r\n");    if (body != NULL && client->method != HTTP_METHOD_HEAD)        octstr_append(response, body);    ret = conn_write(client->conn, response);    octstr_destroy(response);    if (ret == 0) { /* Sent already */        if (!client->persistent_conn)            client_destroy(client);        else {            client_reset(client);            conn_register(client->conn, server_fdset, receive_request, client);        }    } else if (ret == 1) {      /* Queued for sending, we don't want to block */        client->state = sending_reply;        conn_register(client->conn, server_fdset, receive_request, client);    } else    /* Error */        client_destroy(client);}void http_close_client(HTTPClient *client) {    client_destroy(client);}static void server_init(void) {    new_server_sockets = list_create();    list_add_producer(new_server_sockets);    closed_server_sockets = list_create();    server_thread_lock = mutex_create();}static void destroy_struct_server(void *p) {    struct server *pp;    pp = p;    (void) close(pp->fd);    gw_free(pp);}static void destroy_int_pointer(void *p) {    (void) close(*(int *) p);    gw_free(p);}static void server_shutdown(void) {    list_remove_producer(new_server_sockets);    if (server_thread_id != -1) {        gwthread_wakeup(server_thread_id);        gwthread_join_every(server_thread);    }    mutex_destroy(server_thread_lock);    fdset_destroy(server_fdset);    list_destroy(new_server_sockets, destroy_struct_server);    list_destroy(closed_server_sockets, destroy_int_pointer);}/*********************************************************************** * CGI variable manipulation. */void http_destroy_cgiargs(List *args) {    HTTPCGIVar *v;    gwlib_assert_init();    if (args == NULL)        return ;    while ((v = list_extract_first(args)) != NULL) {        octstr_destroy(v->name);        octstr_destroy(v->value);        gw_free(v);    }    list_destroy(args, NULL);}Octstr *http_cgi_variable(List *list, char *name) {    int i;    HTTPCGIVar *v;    gwlib_assert_init();    gw_assert(list != NULL);    gw_assert(name != NULL);    for (i = 0; i < list_len(list); ++i) {        v = list_get(list, i);        if (octstr_str_compare(v->name, name) == 0)            return v->value;    }    return NULL;}/*********************************************************************** * Header manipulation. */static int header_is_called(Octstr *header, char *name) {    long colon;    colon = octstr_search_char(header, ':', 0);    if (colon == -1)        return 0;    if ((long) strlen(name) != colon)        return 0;    return strncasecmp(octstr_get_cstr(header), name, colon) == 0;}List *http_create_empty_headers(void) {    gwlib_assert_init();    return list_create();}void http_destroy_headers(List *headers) {    gwlib_assert_init();    list_destroy(headers, octstr_destroy_item);}void http_header_add(List *headers, char *name, char *contents) {    gwlib_assert_init();    gw_assert(headers != NULL);    gw_assert(name != NULL);    gw_assert(contents != NULL);    list_append(headers, octstr_format("%s: %s", name, contents));}void http_header_get(List *headers, long i, Octstr **name, Octstr **value) {    Octstr *os;    long colon;    gwlib_assert_init();    gw_assert(i >= 0);    gw_assert(name != NULL);    gw_assert(value != NULL);    os = list_get(headers, i);    if (os == NULL)        colon = -1;    else        colon = octstr_search_char(os, ':', 0);    if (colon == -1) {        error(0, "HTTP: Header does not contain a colon. BAD.");        *name = octstr_create("X-Unknown");        *value = octstr_duplicate(os);    } else {        *name = octstr_copy(os, 0, colon);        *value = octstr_copy(os, colon + 1, octstr_len(os));        octstr_strip_blanks(*value);    }}Octstr *http_header_value(List *headers, Octstr *name) {    Octstr *value;    long i;    Octstr *os;    long colon;    Octstr *current_name;    gwlib_assert_init();    gw_assert(name);    value = NULL;    i = 0;    while (i < list_len(headers)) {        os = list_get(headers, i);        if (os == NULL)            colon = -1;        else            colon = octstr_search_char(os, ':', 0);        if (colon == -1) {            return NULL;              } else {            current_name = octstr_copy(os, 0, colon);        }        if (octstr_case_compare(current_name, name) == 0) {            value = octstr_copy(os, colon + 1, octstr_len(os));            octstr_strip_blanks(value);            return value;        }        ++i;    }    return value;}List *http_header_duplicate(List *headers) {    List *new;    long i;    gwlib_assert_init();    if (headers == NULL)        return NULL;    new = http_create_empty_headers();    for (i = 0; i < list_len(headers); ++i)        list_append(new, octstr_duplicate(list_get(headers, i)));    return new;}void http_header_pack(List *headers) {    gwlib_assert_init();    gw_assert(headers != NULL);    /* XXX not implemented yet. */}void http_append_headers(List *to, List *from) {    Octstr *header;    long i;    gwlib_assert_init();    gw_assert(to != NULL);    gw_assert(from != NULL);    for (i = 0; i < list_len(from); ++i) {        header = list_get(from, i);        list_append(to, octstr_duplicate(header));    }}void http_header_combine(List *old_headers, List *new_headers) {    long i;    Octstr *name;    Octstr *value;    /*     * Avoid doing this scan if old_headers is empty anyway.     */    if (list_len(old_headers) > 0) {        for (i = 0; i < list_len(new_headers); i++) {            http_header_get(new_headers, i, &name, &value);            http_header_remove_all(old_headers, octstr_get_cstr(name));            octstr_destroy(name);            octstr_destroy(value);        }    }    http_append_headers(old_headers, new_headers);}Octstr *http_header_find_first(List *headers, char *name) {    long i, name_len;    Octstr *h, *value;    gwlib_assert_init();    gw_assert(headers != NULL);    gw_assert(name != NULL);    name_len = strlen(name);    for (i = 0; i < list_len(headers); ++i) {        h = list_get(headers, i);        if (header_is_called(h, name)) {            value = octstr_copy(h, name_len + 1, octstr_len(h));            octstr_strip_blanks(value);            return value;        }    }    return NULL;}List *http_header_find_all(List *headers, char *name) {    List *list;    long i;    Octstr *h;    gwlib_assert_init();    gw_assert(headers != NULL);    gw_assert(name != NULL);    list = list_create();    for (i = 0; i < list_len(headers); ++i) {        h = list_get(headers, i);        if (header_is_called(h, name))            list_append(list, octstr_duplicate(h));    }    return list;}long http_header_remove_all(List *headers, char *name) {    long i;    Octstr *h;    long count;    gwlib_assert_init();    gw_assert(headers != NULL);    gw_assert(name != NULL);    i = 0;    count = 0;    while (i < list_len(headers)) {        h = list_get(headers, i);        if (header_is_called(h, name)) {            list_delete(headers, i, 1);            octstr_destroy(h);            count++;        } else            i++;    }    return count;}void http_remove_hop_headers(List *headers) {    Octstr *h;    List *connection_headers;    gwlib_assert_init();    gw_assert(headers != NULL);    /*     * The hop-by-hop headers are a standard list, plus those named     * in the Connection header(s).     */    connection_headers = http_header_find_all(headers, "Connection");    while ((h = list_consume(connection_headers))) {        List *hop_headers;        Octstr *e;        octstr_delete(h, 0, strlen("Connection:"));        hop_headers = http_header_split_value(h);        octstr_destroy(h);        while ((e = list_consume(hop_headers))) {            http_header_remove_all(headers, octstr_get_cstr(e));            octstr_destroy(e);        }        list_destroy(hop_headers, NULL);    }    list_destroy(connection_headers, NULL);    http_header_remove_all(headers, "Connection");    http_header_remove_all(headers, "Keep-Alive");    http_header_remove_all(headers, "Proxy-Authenticate");    http_header_remove_all(headers, "Proxy-Authorization");    http_header_remove_all(headers, "TE");    http_header_remove_all(headers,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?