diff --git a/connection.c b/connection.c index 7b96901..7035a29 100644 --- a/connection.c +++ b/connection.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "event.h" #include "httpd.h" @@ -29,6 +30,8 @@ struct client_con { int chunk_total; int chunk_avail; int chunk_have; + + long completed; }; static void free_client(struct client_con *con) @@ -80,15 +83,50 @@ static int data_cb(int fd, void *privdata) } linebuffer_freeline(con->lbuf); } + + /* move completed clients to top of the list, ordered by their timestamp */ + if (con->chunk_have == con->chunk_total && con->chunk_total != 0 && con->completed == 0) { + con->completed = time(NULL); + + list_del(&con->list); + + struct client_con *search; + list_for_each_entry(search, &client_list, list) { + if (search->completed == 0) + break; + + if (search->completed > con->completed) + break; + } + list_add_tail(&con->list, &search->list); + return 0; + } return 0; } int ctcs_trigger_status(void *privdata) { + int delete = 0; + long timeout = time(NULL) - 300; + struct client_con *con; - list_for_each_entry(con, &client_list, list) + list_for_each_entry(con, &client_list, list) { write(event_get_fd(con->event), "SENDSTATUS\n", 11); + delete += (con->completed == 0) ? -1 : 1; + } + + /* delete holds the number of clients to quit */ + list_for_each_entry(con, &client_list, list) { + if (delete <= 0) + break; + + if (con->completed == 0 || con->completed > timeout) + continue; + + write(event_get_fd(con->event), "CTQUIT\n", 7); + delete--; + } return 0; } @@ -120,7 +158,7 @@ int ctcs_accept_handler(int fd, void *privdata) con->event = event_add_readfd(NULL, sockfd, data_cb, con); - list_add(&con->list, &client_list); + list_add_tail(&con->list, &client_list); return 0; } @@ -132,20 +170,21 @@ int ctcs_httpd_handler(struct httpd_con *con, void *privdata) return -1; } - linebuffer_printf(lbuf, "

ctorrent stats

\n\n"); - linebuffer_printf(lbuf, "\n"); + linebuffer_printf(lbuf, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n"); + linebuffer_printf(lbuf, "

ctorrent stats

\n
Client IP:PortChunks (have/total/avail)Download total(current)Upload total(current)
\n"); + linebuffer_printf(lbuf, "\n"); struct client_con *tmp; list_for_each_entry(tmp, &client_list, list) { - linebuffer_printf(lbuf, "\n", + linebuffer_printf(lbuf, "\n", get_sockaddr_buf(&tmp->addr), (double)tmp->chunk_have / (double)tmp->chunk_total * 100.0, tmp->chunk_have, tmp->chunk_total, tmp->chunk_avail, - tmp->total_dn, tmp->bw_dn, tmp->total_up, tmp->bw_up); + tmp->total_dn, tmp->bw_dn, tmp->total_up, tmp->bw_up, + (tmp->completed != 0) ? ctime(&tmp->completed) : "-"); } linebuffer_printf(lbuf, "
Client IP:PortChunks (have/total/avail)Download total(current)Upload total(current)Completed since
%s%3.2lf%% (%d/%d/%d)%llu (%d)%llu (%d)
%s%3.2lf%% (%d/%d/%d)%llu (%d)%llu (%d)%s
\n\n"); - httpd_send_header(con, "200 OK", "text/html"); linebuffer_writefd(lbuf, con->fd); linebuffer_free(lbuf); return 0;