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 + -
显示快捷键?