3 #include <sys/socket.h>
4 #include <netinet/in.h>
7 #include "global_statistics.h"
10 #include "web_client.h"
12 #define INITIAL_WEB_DATA_LENGTH 65536
14 struct web_client *web_clients = NULL;
15 unsigned long long web_clients_count = 0;
17 struct web_client *web_client_create(int listener)
21 w = calloc(1, sizeof(struct web_client));
23 error("Cannot allocate new web_client memory.");
27 w->id = ++web_clients_count;
28 w->mode = WEB_CLIENT_MODE_NORMAL;
31 struct sockaddr *sadr;
34 sadr = (struct sockaddr*) &w->clientaddr;
35 addrlen = sizeof(w->clientaddr);
37 w->ifd = accept(listener, sadr, &addrlen);
39 error("%llu: Cannot accept new incoming connection.", w->id);
45 if(getnameinfo(sadr, addrlen, w->client_ip, NI_MAXHOST, w->client_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
46 error("Cannot getnameinfo() on received client connection.");
47 strncpy(w->client_ip, "UNKNOWN", NI_MAXHOST);
48 strncpy(w->client_port, "UNKNOWN", NI_MAXSERV);
50 w->client_ip[NI_MAXHOST] = '\0';
51 w->client_port[NI_MAXSERV] = '\0';
53 switch(sadr->sa_family) {
55 debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
58 if(strncmp(w->client_ip, "::ffff:", 7) == 0) {
59 strcpy(w->client_ip, &w->client_ip[7]);
60 debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
62 debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv6 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
65 debug(D_WEB_CLIENT_ACCESS, "%llu: New UNKNOWN web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
70 if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0) error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
73 w->data = web_buffer_create(INITIAL_WEB_DATA_LENGTH);
82 if(web_clients) web_clients->prev = w;
83 w->next = web_clients;
86 global_statistics.connected_clients++;
91 struct web_client *web_client_free(struct web_client *w)
93 struct web_client *n = w->next;
95 debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
97 if(w->prev) w->prev->next = w->next;
98 if(w->next) w->next->prev = w->prev;
100 if(w == web_clients) web_clients = w->next;
102 if(w->data) web_buffer_free(w->data);
104 if(w->ofd != w->ifd) close(w->ofd);
107 global_statistics.connected_clients--;