X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=http_send.c;h=8ebbbc9c8a676d52f7b78348af10333ed6ec9dea;hp=63bfec03c9d1cd17ac4b34a7609c32c28c218ead;hb=9902762e74e41165dfa18606411cef86ac7afd5d;hpb=69bc5e6d0f3e1535c04555928e016141a71d4619 diff --git a/http_send.c b/http_send.c index 63bfec03..8ebbbc9c 100644 --- a/http_send.c +++ b/http_send.c @@ -29,9 +29,8 @@ /** Message sent to clients that do not send a valid get request. */ #define HTTP_ERR_MSG "HTTP/1.0 400 Bad Request\n" - /** The possible states of a client from the server's POV. */ -enum http_status { +enum http_client_status { /** We accepted the connection on the tcp socket. */ HTTP_CONNECTED, /** Successfully received the get request. */ @@ -42,25 +41,18 @@ enum http_status { HTTP_INVALID_GET_REQUEST }; -/** Clients will be kicked if there are more than that many bytes pending. */ -#define MAX_BACKLOG 400000 -/** The list of connected clients. */ -static struct list_head clients; -/** The whitelist/blacklist. */ -static struct list_head http_acl; - -static int listen_fd = -1, numclients; - struct private_http_sender_data { - enum http_status status; + enum http_client_status status; }; +static struct sender_status http_sender_status, *hss = &http_sender_status; + static int http_send_msg(struct sender_client *sc, const char *msg) { int ret = send_buffer(sc->fd, msg); if (ret < 0) - shutdown_client(sc); + shutdown_client(sc, hss); return ret; } @@ -78,33 +70,32 @@ static int http_send_err_msg(struct sender_client *sc) static void http_shutdown_clients(void) { - struct sender_client *sc, *tmp; - list_for_each_entry_safe(sc, tmp, &clients, node) - shutdown_client(sc); + shutdown_clients(hss); } static void http_send(long unsigned current_chunk, - __a_unused long unsigned chunks_sent, const char *buf, size_t len) + __a_unused long unsigned chunks_sent, const char *buf, size_t len, + const char *header_buf, size_t header_len) { struct sender_client *sc, *tmp; - list_for_each_entry_safe(sc, tmp, &clients, node) { + list_for_each_entry_safe(sc, tmp, &hss->client_list, node) { struct private_http_sender_data *phsd = sc->private_data; if (phsd->status != HTTP_STREAMING) continue; - send_chunk(sc, 0, current_chunk, buf, len); + send_chunk(sc, hss, 0, current_chunk, buf, len, header_buf, + header_len); } } static void http_post_select(fd_set *rfds, __a_unused fd_set *wfds) { - int ret, fd, match; struct sender_client *sc, *tmp; struct private_http_sender_data *phsd; - if (listen_fd < 0) + if (hss->listen_fd < 0) return; - list_for_each_entry_safe(sc, tmp, &clients, node) { + list_for_each_entry_safe(sc, tmp, &hss->client_list, node) { phsd = sc->private_data; switch (phsd->status) { case HTTP_STREAMING: /* nothing to do */ @@ -116,8 +107,7 @@ static void http_post_select(fd_set *rfds, __a_unused fd_set *wfds) phsd->status = HTTP_INVALID_GET_REQUEST; } else { phsd->status = HTTP_GOT_GET_REQUEST; - PARA_INFO_LOG("%s", - "received get request\n"); + PARA_INFO_LOG("received get request\n"); } } break; @@ -127,59 +117,28 @@ static void http_post_select(fd_set *rfds, __a_unused fd_set *wfds) break; case HTTP_INVALID_GET_REQUEST: /* need to send err msg */ if (http_send_err_msg(sc) >= 0) - shutdown_client(sc); + shutdown_client(sc, hss); break; } } - if (!FD_ISSET(listen_fd, rfds)) + if (!FD_ISSET(hss->listen_fd, rfds)) return; - ret = para_accept(listen_fd, NULL, 0); - if (ret < 0) { - PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + sc = accept_sender_client(hss); + if (!sc) return; - } - fd = ret; - ret = -E_MAX_CLIENTS; - if (conf.http_max_clients_arg > 0 && numclients >= - conf.http_max_clients_arg) { - goto err_out; - } - ret = mark_fd_nonblocking(fd); - if (ret < 0) - goto err_out; - match = acl_lookup(fd, &http_acl); - PARA_DEBUG_LOG("acl lookup returned %d\n", match); - ret = -E_ACL_PERM; - if ((match && !conf.http_default_deny_given) || - (!match && conf.http_default_deny_given)) - goto err_out; - numclients++; - sc = para_calloc(sizeof(*sc)); - sc->fd = fd; - sc->name = make_message("%s", remote_name(fd)); - PARA_NOTICE_LOG("connection from %s (fd %d)\n", sc->name, fd); phsd = para_malloc(sizeof(*phsd)); sc->private_data = phsd; phsd->status = HTTP_CONNECTED; - sc->cq = cq_new(MAX_BACKLOG); - PARA_INFO_LOG("accepted client #%d: %s (fd %d)\n", numclients, - sc->name, fd); - para_list_add(&sc->node, &clients); - add_close_on_fork_list(fd); - return; -err_out: - PARA_WARNING_LOG("%s\n", para_strerror(-ret)); - close(fd); } static void http_pre_select(int *max_fileno, fd_set *rfds, __a_unused fd_set *wfds) { struct sender_client *sc, *tmp; - if (listen_fd < 0) + if (hss->listen_fd < 0) return; - para_fd_set(listen_fd, rfds, max_fileno); - list_for_each_entry_safe(sc, tmp, &clients, node) { + para_fd_set(hss->listen_fd, rfds, max_fileno); + list_for_each_entry_safe(sc, tmp, &hss->client_list, node) { struct private_http_sender_data *phsd = sc->private_data; if (phsd->status == HTTP_CONNECTED) /* need to recv get request */ para_fd_set(sc->fd, rfds, max_fileno); @@ -188,80 +147,30 @@ static void http_pre_select(int *max_fileno, fd_set *rfds, __a_unused fd_set *wf static int http_com_on(__a_unused struct sender_command_data *scd) { - if (listen_fd >= 0) - return 1; - return open_sender(IPPROTO_TCP, conf.http_port_arg); + return generic_com_on(hss, IPPROTO_TCP); } static int http_com_off(__a_unused struct sender_command_data *scd) { - if (listen_fd < 0) - return 1; - PARA_NOTICE_LOG("closing http port %d\n", conf.http_port_arg); - close(listen_fd); - del_close_on_fork_list(listen_fd); - http_shutdown_clients(); - listen_fd = -1; + generic_com_off(hss); return 1; } static int http_com_deny(struct sender_command_data *scd) { - if (conf.http_default_deny_given) - acl_del_entry(&http_acl, scd->addr, scd->netmask); - else - acl_add_entry(&http_acl, scd->addr, scd->netmask); + generic_com_deny(scd, hss); return 1; } static int http_com_allow(struct sender_command_data *scd) { - if (conf.http_default_deny_given) - acl_add_entry(&http_acl, scd->addr, scd->netmask); - else - acl_del_entry(&http_acl, scd->addr, scd->netmask); + generic_com_allow(scd, hss); return 1; } static char *http_info(void) { - char *clnts = NULL, *ret; - struct sender_client *sc, *tmp_sc; - - char *acl_contents = acl_get_contents(&http_acl); - list_for_each_entry_safe(sc, tmp_sc, &clients, node) { - char *tmp = make_message("%s%s ", clnts? clnts : "", sc->name); - free(clnts); - clnts = tmp; - } - ret = make_message( - "http status: %s\n" - "http tcp port: %d\n" - "http clients: %d\n" - "http maximal number of clients: %d%s\n" - "http connected clients: %s\n" - "http access %s list: %s\n", - (listen_fd >= 0)? "on" : "off", - conf.http_port_arg, - numclients, - conf.http_max_clients_arg, - conf.http_max_clients_arg > 0? "" : " (unlimited)", - clnts? clnts : "(none)", - conf.http_default_deny_given? "allow" : "deny", - acl_contents? acl_contents : "(none)" - ); - free(acl_contents); - free(clnts); - return ret; -} - -static char *http_help(void) -{ - return make_message( - "usage: {on|off}\n" - "usage: {allow|deny} IP mask\n" - "example: allow 127.0.0.1 32\n" - ); + return get_sender_info(hss, "http"); } /** @@ -275,25 +184,25 @@ static char *http_help(void) void http_send_init(struct sender *s) { int ret; - INIT_LIST_HEAD(&clients); s->info = http_info; s->send = http_send; s->pre_select = http_pre_select; s->post_select = http_post_select; s->shutdown_clients = http_shutdown_clients; - s->help = http_help; + s->help = generic_sender_help; s->client_cmds[SENDER_ON] = http_com_on; s->client_cmds[SENDER_OFF] = http_com_off; s->client_cmds[SENDER_DENY] = http_com_deny; s->client_cmds[SENDER_ALLOW] = http_com_allow; s->client_cmds[SENDER_ADD] = NULL; s->client_cmds[SENDER_DELETE] = NULL; - acl_init(&http_acl, conf.http_access_arg, conf.http_access_given); + + init_sender_status(hss, conf.http_access_arg, conf.http_access_given, + conf.http_port_arg, conf.http_max_clients_arg, + conf.http_default_deny_given); if (conf.http_no_autostart_given) return; - ret = open_sender(IPPROTO_TCP, conf.http_port_arg); + ret = generic_com_on(hss, IPPROTO_TCP); if (ret < 0) PARA_ERROR_LOG("%s\n", para_strerror(-ret)); - else - listen_fd = ret; }