commit - 4cd25209651f224be8c34d6006ef689963ce37d5
commit + 207b3e80d867693ff74cf99c84f7dd41386adba1
blob - 43c684fec0d931c7f6845d1a37fb8ee624a2db59
blob + 4a8befc7db5c209d20eea8e4a812b0cb8b5ee6dc
--- gmid.h
+++ gmid.h
#include "config.h"
#include <sys/socket.h>
+#include <sys/tree.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define CLIENT_CERT_REQ 60
#define CERT_NOT_AUTH 61
-#define MAX_USERS 64
-
/* maximum hostname and label length, +1 for the NUL-terminator */
#define DOMAIN_NAME_LEN (253+1)
#define LABEL_LEN (63+1)
#define IS_INTERNAL_REQUEST(x) ((x) != REQUEST_CGI && (x) != REQUEST_FCGI)
struct client {
- int id;
+ uint32_t id;
struct tls *ctx;
char *req;
struct iri iri;
struct sockaddr_storage addr;
struct vhost *host; /* host they're talking to */
size_t loc; /* location matched */
-};
-extern struct client clients[MAX_USERS];
+ SPLAY_ENTRY(client) entry;
+};
+SPLAY_HEAD(client_tree_id, client);
+extern struct client_tree_id clients;
struct cgireq {
char buf[GEMINI_URL_LEN];
struct client *try_client_by_id(int);
void loop(struct tls*, int, int, struct imsgbuf*);
+int client_tree_cmp(struct client *, struct client *);
+SPLAY_PROTOTYPE(client_tree_id, client, entry, client_tree_cmp);
+
/* dirs.c */
int scandir_fd(int, struct dirent***, int(*)(const struct dirent*),
int(*)(const struct dirent**, const struct dirent**));
blob - 66202c460bbf1104741d192306a0c680e81a48c2
blob + 4f5e4f2d0a2c7a443b18b8faf51543ed71d090e6
--- server.c
+++ server.c
int shutting_down;
-struct client clients[MAX_USERS];
-
static struct tls *ctx;
static struct event e4, e6, imsgev, siginfo, sigusr2;
[IMSG_CGI_RES] = handle_imsg_cgi_res,
[IMSG_FCGI_FD] = handle_imsg_fcgi_fd,
};
+
+static uint32_t server_client_id;
+
+struct client_tree_id clients;
static inline int
matches(const char *pattern, const char *path)
* ensure that everything is properly released once we reach
* this point.
*/
+
+ SPLAY_REMOVE(client_tree_id, &clients, c);
if (c->cgibev != NULL) {
bufferevent_disable(c->cgibev, EVBUFFER_READ|EVBUFFER_WRITE);
struct sockaddr_storage addr;
struct sockaddr *saddr;
socklen_t len;
- int i, fd;
+ int fd;
(void)et;
mark_nonblock(fd);
- for (i = 0; i < MAX_USERS; ++i) {
- c = &clients[i];
- if (c->fd == -1) {
- memset(c, 0, sizeof(*c));
- c->id = i;
- if (tls_accept_socket(ctx, &c->ctx, fd) == -1)
- break; /* goodbye fd! */
+ c = xcalloc(1, sizeof(*c));
+ c->id = ++server_client_id;
+ c->fd = fd;
+ c->pfd = -1;
+ c->addr = addr;
- c->fd = fd;
- c->pfd = -1;
- c->dir = NULL;
- c->addr = addr;
-
- event_once(c->fd, EV_READ|EV_WRITE, handle_handshake,
- c, NULL);
-
- connected_clients++;
- return;
- }
+ if (tls_accept_socket(ctx, &c->ctx, fd) == -1) {
+ log_warn(c, "failed to accept socket: %s", tls_error(c->ctx));
+ close(c->fd);
+ free(c);
+ return;
}
- close(fd);
+ SPLAY_INSERT(client_tree_id, &clients, c);
+ event_once(c->fd, EV_READ|EV_WRITE, handle_handshake, c, NULL);
+ connected_clients++;
}
static struct client *
client_by_id(int id)
{
- if ((size_t)id > sizeof(clients)/sizeof(clients[0]))
+ struct client *c;
+
+ if ((c = try_client_by_id(id)) == NULL)
fatal("in client_by_id: invalid id %d", id);
- return &clients[id];
+ return c;
}
struct client *
try_client_by_id(int id)
{
- if ((size_t)id > sizeof(clients)/sizeof(clients[0]))
- return NULL;
- return &clients[id];
+ struct client find;
+
+ find.id = id;
+ return SPLAY_FIND(client_tree_id, &clients, &find);
}
static void
void
loop(struct tls *ctx_, int sock4, int sock6, struct imsgbuf *ibuf)
{
- size_t i;
-
ctx = ctx_;
+ SPLAY_INIT(&clients);
+
event_init();
- memset(&clients, 0, sizeof(clients));
- for (i = 0; i < MAX_USERS; ++i)
- clients[i].fd = -1;
-
event_set(&e4, sock4, EV_READ | EV_PERSIST, &do_accept, NULL);
event_add(&e4, NULL);
event_dispatch();
_exit(0);
}
+
+int
+client_tree_cmp(struct client *a, struct client *b)
+{
+ if (a->id == b->id)
+ return 0;
+ else if (a->id < b->id)
+ return -1;
+ else
+ return +1;
+}
+
+SPLAY_GENERATE(client_tree_id, client, entry, client_tree_cmp)