| @@ -40,8 +40,9 @@ | |||||
| #include "cucul.h" | #include "cucul.h" | ||||
| #include "cucul_internals.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 */ | /* Following vars are static */ | ||||
| #define INIT_PREFIX \ | #define INIT_PREFIX \ | ||||
| @@ -68,7 +69,9 @@ struct client | |||||
| { | { | ||||
| int fd; | int fd; | ||||
| int ready; | int ready; | ||||
| char buffer[BACKBUFFER]; | |||||
| uint8_t inbuf[INBUFFER]; | |||||
| int inbytes; | |||||
| uint8_t outbuf[OUTBUFFER]; | |||||
| int start, stop; | int start, stop; | ||||
| }; | }; | ||||
| @@ -93,7 +96,7 @@ struct driver_private | |||||
| static void manage_connections(caca_t *kk); | static void manage_connections(caca_t *kk); | ||||
| static int send_data(caca_t *kk, struct client *c); | 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) | static int network_init_graphics(caca_t *kk) | ||||
| { | { | ||||
| @@ -172,6 +175,9 @@ static int network_init_graphics(caca_t *kk) | |||||
| /* Ignore SIGPIPE */ | /* Ignore SIGPIPE */ | ||||
| kk->drv.p->sigpipe_handler = signal(SIGPIPE, SIG_IGN); | kk->drv.p->sigpipe_handler = signal(SIGPIPE, SIG_IGN); | ||||
| fprintf(stderr, "initialised network, listening on port %i\n", | |||||
| kk->drv.p->port); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -224,7 +230,12 @@ static void network_display(caca_t *kk) | |||||
| continue; | continue; | ||||
| if(send_data(kk, &kk->drv.p->clients[i])) | 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; | kk->drv.p->clients[i].fd = -1; | ||||
| } | |||||
| } | } | ||||
| manage_connections(kk); | manage_connections(kk); | ||||
| @@ -259,6 +270,9 @@ static void manage_connections(caca_t *kk) | |||||
| if(fd == -1) | if(fd == -1) | ||||
| return; | return; | ||||
| fprintf(stderr, "client %i connected from %s\n", | |||||
| fd, inet_ntoa(remote_addr.sin_addr)); | |||||
| /* Non blocking socket */ | /* Non blocking socket */ | ||||
| flags = fcntl(fd, F_SETFL, 0); | flags = fcntl(fd, F_SETFL, 0); | ||||
| fcntl(fd, F_SETFL, flags | O_NONBLOCK); | 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].fd = fd; | ||||
| kk->drv.p->clients[kk->drv.p->client_count].ready = 0; | 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].start = 0; | ||||
| kk->drv.p->clients[kk->drv.p->client_count].stop = 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 */ | /* 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++; | kk->drv.p->client_count++; | ||||
| } | } | ||||
| @@ -294,15 +315,45 @@ static int send_data(caca_t *kk, struct client *c) | |||||
| if(c->fd < 0) | if(c->fd < 0) | ||||
| return -1; | return -1; | ||||
| /* Debug: show incoming data */ | |||||
| /* Listen to incoming data */ | |||||
| for(;;) | for(;;) | ||||
| { | { | ||||
| unsigned char in; | |||||
| ret = read(c->fd, &in, 1); | |||||
| ret = read(c->fd, c->inbuf + c->inbytes, 1); | |||||
| if(ret <= 0) | if(ret <= 0) | ||||
| break; | 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 */ | /* 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 we have backlog, send the backlog */ | ||||
| if(c->stop) | 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) | if(ret == -1) | ||||
| { | { | ||||
| @@ -345,26 +396,26 @@ static int send_data(caca_t *kk, struct client *c) | |||||
| c->start += ret; | c->start += ret; | ||||
| if(c->stop - c->start + strlen(ANSI_PREFIX) + kk->drv.p->size | if(c->stop - c->start + strlen(ANSI_PREFIX) + kk->drv.p->size | ||||
| > BACKBUFFER) | |||||
| > OUTBUFFER) | |||||
| { | { | ||||
| /* Overflow! Empty buffer and start again */ | /* 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->start = 0; | ||||
| c->stop = strlen(ANSI_RESET); | c->stop = strlen(ANSI_RESET); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* Need to move? */ | /* 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->stop -= c->start; | ||||
| c->start = 0; | 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); | 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; | c->stop += kk->drv.p->size; | ||||
| return 0; | return 0; | ||||
| @@ -385,18 +436,18 @@ static int send_data(caca_t *kk, struct client *c) | |||||
| if(ret < (ssize_t)strlen(ANSI_PREFIX)) | 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 */ | /* 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->start = 0; | ||||
| c->stop = strlen(ANSI_RESET); | c->stop = strlen(ANSI_RESET); | ||||
| return 0; | 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; | 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; | c->stop += kk->drv.p->size; | ||||
| return 0; | return 0; | ||||
| @@ -414,16 +465,16 @@ static int send_data(caca_t *kk, struct client *c) | |||||
| if(ret < kk->drv.p->size) | if(ret < kk->drv.p->size) | ||||
| { | { | ||||
| if(kk->drv.p->size > BACKBUFFER) | |||||
| if(kk->drv.p->size > OUTBUFFER) | |||||
| { | { | ||||
| /* Overflow! Empty buffer and start again */ | /* 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->start = 0; | ||||
| c->stop = strlen(ANSI_RESET); | c->stop = strlen(ANSI_RESET); | ||||
| return 0; | 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; | c->stop = kk->drv.p->size - ret; | ||||
| return 0; | return 0; | ||||
| @@ -432,7 +483,7 @@ static int send_data(caca_t *kk, struct client *c) | |||||
| return 0; | 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; | size_t total = 0; | ||||
| ssize_t ret; | ssize_t ret; | ||||
| @@ -451,7 +502,7 @@ ssize_t nonblock_write(int fd, char *buf, size_t len) | |||||
| return total; | return total; | ||||
| total += len; | total += len; | ||||
| buf += len; | |||||
| buf = (void *)((uintptr_t)buf + len); | |||||
| } | } | ||||
| return total; | return total; | ||||