| @@ -40,8 +40,9 @@ | |||
| #include "cucul.h" | |||
| #include "cucul_internals.h" | |||
| #define BACKLOG 1337 /* Number of pending connections */ | |||
| #define BACKBUFFER 300000 /* Size of per-client buffer */ | |||
| #define BACKLOG 1337 /* Number of pending connections */ | |||
| #define INBUFFER 32 /* Size of per-client input buffer */ | |||
| #define OUTBUFFER 300000 /* Size of per-client output buffer */ | |||
| /* Following vars are static */ | |||
| #define INIT_PREFIX \ | |||
| @@ -68,7 +69,9 @@ struct client | |||
| { | |||
| int fd; | |||
| int ready; | |||
| char buffer[BACKBUFFER]; | |||
| uint8_t inbuf[INBUFFER]; | |||
| int inbytes; | |||
| uint8_t outbuf[OUTBUFFER]; | |||
| int start, stop; | |||
| }; | |||
| @@ -93,7 +96,7 @@ struct driver_private | |||
| static void manage_connections(caca_t *kk); | |||
| static int send_data(caca_t *kk, struct client *c); | |||
| ssize_t nonblock_write(int fd, char *buf, size_t len); | |||
| ssize_t nonblock_write(int fd, void *buf, size_t len); | |||
| static int network_init_graphics(caca_t *kk) | |||
| { | |||
| @@ -172,6 +175,9 @@ static int network_init_graphics(caca_t *kk) | |||
| /* Ignore SIGPIPE */ | |||
| kk->drv.p->sigpipe_handler = signal(SIGPIPE, SIG_IGN); | |||
| fprintf(stderr, "initialised network, listening on port %i\n", | |||
| kk->drv.p->port); | |||
| return 0; | |||
| } | |||
| @@ -224,7 +230,12 @@ static void network_display(caca_t *kk) | |||
| continue; | |||
| if(send_data(kk, &kk->drv.p->clients[i])) | |||
| { | |||
| fprintf(stderr, "client %i dropped connection\n", | |||
| kk->drv.p->clients[i].fd); | |||
| close(kk->drv.p->clients[i].fd); | |||
| kk->drv.p->clients[i].fd = -1; | |||
| } | |||
| } | |||
| manage_connections(kk); | |||
| @@ -259,6 +270,9 @@ static void manage_connections(caca_t *kk) | |||
| if(fd == -1) | |||
| return; | |||
| fprintf(stderr, "client %i connected from %s\n", | |||
| fd, inet_ntoa(remote_addr.sin_addr)); | |||
| /* Non blocking socket */ | |||
| flags = fcntl(fd, F_SETFL, 0); | |||
| fcntl(fd, F_SETFL, flags | O_NONBLOCK); | |||
| @@ -277,11 +291,18 @@ static void manage_connections(caca_t *kk) | |||
| kk->drv.p->clients[kk->drv.p->client_count].fd = fd; | |||
| kk->drv.p->clients[kk->drv.p->client_count].ready = 0; | |||
| kk->drv.p->clients[kk->drv.p->client_count].inbytes = 0; | |||
| kk->drv.p->clients[kk->drv.p->client_count].start = 0; | |||
| kk->drv.p->clients[kk->drv.p->client_count].stop = 0; | |||
| /* If we already have data to send, send it to the new client */ | |||
| send_data(kk, &kk->drv.p->clients[kk->drv.p->client_count]); | |||
| if(send_data(kk, &kk->drv.p->clients[kk->drv.p->client_count])) | |||
| { | |||
| fprintf(stderr, "client %i dropped connection\n", fd); | |||
| close(fd); | |||
| kk->drv.p->clients[kk->drv.p->client_count].fd = -1; | |||
| return; | |||
| } | |||
| kk->drv.p->client_count++; | |||
| } | |||
| @@ -294,15 +315,45 @@ static int send_data(caca_t *kk, struct client *c) | |||
| if(c->fd < 0) | |||
| return -1; | |||
| /* Debug: show incoming data */ | |||
| /* Listen to incoming data */ | |||
| for(;;) | |||
| { | |||
| unsigned char in; | |||
| ret = read(c->fd, &in, 1); | |||
| ret = read(c->fd, c->inbuf + c->inbytes, 1); | |||
| if(ret <= 0) | |||
| break; | |||
| fprintf(stderr, "client %i said \\x%.02x\n", c->fd, in); | |||
| c->inbytes++; | |||
| /* Check for telnet sequences */ | |||
| if(c->inbuf[0] == 0xff) | |||
| { | |||
| if(c->inbytes == 1) | |||
| { | |||
| ; | |||
| } | |||
| else if(c->inbuf[1] == 0xfd || c->inbuf[1] == 0xfc) | |||
| { | |||
| if(c->inbytes == 3) | |||
| { | |||
| fprintf(stderr, "client %i said: %.02x %.02x %.02x\n", | |||
| c->fd, c->inbuf[0], c->inbuf[1], c->inbuf[2]); | |||
| /* Just ignore, lol */ | |||
| c->inbytes = 0; | |||
| } | |||
| } | |||
| else | |||
| c->inbytes = 0; | |||
| } | |||
| else if(c->inbytes == 1) | |||
| { | |||
| if(c->inbuf[0] == 0x03) | |||
| { | |||
| fprintf(stderr, "client %i pressed C-c\n", c->fd); | |||
| return -1; /* User requested to quit */ | |||
| } | |||
| c->inbytes = 0; | |||
| } | |||
| } | |||
| /* Send the telnet initialisation commands */ | |||
| @@ -325,7 +376,7 @@ static int send_data(caca_t *kk, struct client *c) | |||
| /* If we have backlog, send the backlog */ | |||
| if(c->stop) | |||
| { | |||
| ret = nonblock_write(c->fd, c->buffer + c->start, c->stop - c->start); | |||
| ret = nonblock_write(c->fd, c->outbuf + c->start, c->stop - c->start); | |||
| if(ret == -1) | |||
| { | |||
| @@ -345,26 +396,26 @@ static int send_data(caca_t *kk, struct client *c) | |||
| c->start += ret; | |||
| if(c->stop - c->start + strlen(ANSI_PREFIX) + kk->drv.p->size | |||
| > BACKBUFFER) | |||
| > OUTBUFFER) | |||
| { | |||
| /* Overflow! Empty buffer and start again */ | |||
| memcpy(c->buffer, ANSI_RESET, strlen(ANSI_RESET)); | |||
| memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET)); | |||
| c->start = 0; | |||
| c->stop = strlen(ANSI_RESET); | |||
| return 0; | |||
| } | |||
| /* Need to move? */ | |||
| if(c->stop + strlen(ANSI_PREFIX) + kk->drv.p->size > BACKBUFFER) | |||
| if(c->stop + strlen(ANSI_PREFIX) + kk->drv.p->size > OUTBUFFER) | |||
| { | |||
| memmove(c->buffer, c->buffer + c->start, c->stop - c->start); | |||
| memmove(c->outbuf, c->outbuf + c->start, c->stop - c->start); | |||
| c->stop -= c->start; | |||
| c->start = 0; | |||
| } | |||
| memcpy(c->buffer + c->stop, ANSI_PREFIX, strlen(ANSI_PREFIX)); | |||
| memcpy(c->outbuf + c->stop, ANSI_PREFIX, strlen(ANSI_PREFIX)); | |||
| c->stop += strlen(ANSI_PREFIX); | |||
| memcpy(c->buffer + c->stop, kk->drv.p->buffer, kk->drv.p->size); | |||
| memcpy(c->outbuf + c->stop, kk->drv.p->buffer, kk->drv.p->size); | |||
| c->stop += kk->drv.p->size; | |||
| return 0; | |||
| @@ -385,18 +436,18 @@ static int send_data(caca_t *kk, struct client *c) | |||
| if(ret < (ssize_t)strlen(ANSI_PREFIX)) | |||
| { | |||
| if(strlen(ANSI_PREFIX) + kk->drv.p->size > BACKBUFFER) | |||
| if(strlen(ANSI_PREFIX) + kk->drv.p->size > OUTBUFFER) | |||
| { | |||
| /* Overflow! Empty buffer and start again */ | |||
| memcpy(c->buffer, ANSI_RESET, strlen(ANSI_RESET)); | |||
| memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET)); | |||
| c->start = 0; | |||
| c->stop = strlen(ANSI_RESET); | |||
| return 0; | |||
| } | |||
| memcpy(c->buffer, ANSI_PREFIX, strlen(ANSI_PREFIX) - ret); | |||
| memcpy(c->outbuf, ANSI_PREFIX, strlen(ANSI_PREFIX) - ret); | |||
| c->stop = strlen(ANSI_PREFIX) - ret; | |||
| memcpy(c->buffer + c->stop, kk->drv.p->buffer, kk->drv.p->size); | |||
| memcpy(c->outbuf + c->stop, kk->drv.p->buffer, kk->drv.p->size); | |||
| c->stop += kk->drv.p->size; | |||
| return 0; | |||
| @@ -414,16 +465,16 @@ static int send_data(caca_t *kk, struct client *c) | |||
| if(ret < kk->drv.p->size) | |||
| { | |||
| if(kk->drv.p->size > BACKBUFFER) | |||
| if(kk->drv.p->size > OUTBUFFER) | |||
| { | |||
| /* Overflow! Empty buffer and start again */ | |||
| memcpy(c->buffer, ANSI_RESET, strlen(ANSI_RESET)); | |||
| memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET)); | |||
| c->start = 0; | |||
| c->stop = strlen(ANSI_RESET); | |||
| return 0; | |||
| } | |||
| memcpy(c->buffer, kk->drv.p->buffer, kk->drv.p->size - ret); | |||
| memcpy(c->outbuf, kk->drv.p->buffer, kk->drv.p->size - ret); | |||
| c->stop = kk->drv.p->size - ret; | |||
| return 0; | |||
| @@ -432,7 +483,7 @@ static int send_data(caca_t *kk, struct client *c) | |||
| return 0; | |||
| } | |||
| ssize_t nonblock_write(int fd, char *buf, size_t len) | |||
| ssize_t nonblock_write(int fd, void *buf, size_t len) | |||
| { | |||
| size_t total = 0; | |||
| ssize_t ret; | |||
| @@ -451,7 +502,7 @@ ssize_t nonblock_write(int fd, char *buf, size_t len) | |||
| return total; | |||
| total += len; | |||
| buf += len; | |||
| buf = (void *)((uintptr_t)buf + len); | |||
| } | |||
| return total; | |||