abduco

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit ed4f1ecdcde57bb692dcae0185071df11d24427a
parent c14b9c91737c0de6e797bb43d754bd958b29aaba
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Wed, 26 Feb 2014 21:13:18 +0100

Use the same packet structure for both ways of the client server communiction

This is slightly less efficient than before but allows the server
to send different types of messages not only output data to the
client.

Diffstat:
abduco.c | 37+++++++++++++++++++------------------
client.c | 43+++++++++++++++++++++++++++----------------
debug.c | 19+++++++------------
server.c | 44++++++++++++++++++++++++++++++++++----------
4 files changed, 87 insertions(+), 56 deletions(-)

diff --git a/abduco.c b/abduco.c @@ -66,30 +66,23 @@ enum PacketType { MSG_REDRAW = 4, }; -/* packet sent from client to server */ typedef struct { - unsigned char type; - unsigned char len; + unsigned int type; + size_t len; union { - char msg[sizeof(struct winsize)]; + char msg[BUFSIZ]; struct winsize ws; int i; } u; -} ClientPacket; - -/* packet sent from server to all clients */ -typedef struct { - char buf[BUFSIZ]; - size_t len; -} ServerPacket; +} Packet; typedef struct { - ClientPacket pkt; + Packet pkt; size_t off; } ClientPacketState; typedef struct { - ServerPacket *pkt; + Packet *pkt; size_t off; } ServerPacketState; @@ -113,9 +106,9 @@ typedef struct { Client *clients; int client_count; int socket; - ServerPacket pty_output; + Packet pty_output; ClientPacketState pty_input; - ClientPacket queue[10]; + Packet queue[10]; unsigned int queue_count; unsigned int queue_insert; unsigned int queue_remove; @@ -139,16 +132,24 @@ static int create_socket(const char *name); static void die(const char *s); static void info(const char *str, ...); +static inline size_t packet_header_size() { + return offsetof(Packet, u); +} + +static size_t packet_size(Packet *pkt) { + return packet_header_size() + pkt->len; +} + static bool is_client_packet_complete(ClientPacketState *pkt) { - return pkt->off == sizeof pkt->pkt; + return pkt->off >= packet_header_size() && pkt->off == packet_size(&pkt->pkt); } static bool is_server_packet_complete(ServerPacketState *pkt) { - return pkt->pkt && pkt->off == pkt->pkt->len; + return pkt->pkt && pkt->off == packet_size(pkt->pkt); } static bool is_server_packet_nonempty(ServerPacketState *pkt) { - return pkt->pkt && pkt->pkt->len > 0; + return pkt->pkt && pkt->pkt->len > 0; } #include "debug.c" diff --git a/client.c b/client.c @@ -40,9 +40,10 @@ static ssize_t read_all(int fd, char *buf, size_t len) { return ret; } -static bool client_send_packet(ClientPacket *pkt) { - print_client_packet("client-send:", pkt); - if (write_all(server.socket, (char *)pkt, sizeof(ClientPacket)) != sizeof(ClientPacket)) { +static bool client_send_packet(Packet *pkt) { + print_packet("client-send:", pkt); + size_t size = packet_size(pkt); + if (write_all(server.socket, (char *)pkt, size) != size) { debug("FAILED\n"); server.running = false; return false; @@ -50,15 +51,19 @@ static bool client_send_packet(ClientPacket *pkt) { return true; } -static bool client_recv_packet(ServerPacket *pkt) { - ssize_t len = pkt->len = read_all(server.socket, pkt->buf, sizeof(pkt->buf)); - print_server_packet("client-recv:", pkt); - if (len <= 0) { - debug("FAILED\n"); - server.running = false; - return false; - } +static bool client_recv_packet(Packet *pkt) { + ssize_t len = read_all(server.socket, (char*)pkt, packet_header_size()); + if (len <= 0 || len != packet_header_size() || pkt->len == 0) + goto error; + len = read_all(server.socket, pkt->u.msg, pkt->len); + print_packet("client-recv:", pkt); + if (len <= 0 || len != pkt->len) + goto error; return true; +error: + debug("FAILED here\n"); + server.running = false; + return false; } static void client_clear_screen() { @@ -88,7 +93,7 @@ static int client_mainloop() { if (client.need_resize) { struct winsize ws; if (ioctl(0, TIOCGWINSZ, &ws) != -1) { - ClientPacket pkt = { + Packet pkt = { .type = MSG_RESIZE, .u = { .ws = ws }, .len = sizeof(ws), @@ -105,13 +110,18 @@ static int client_mainloop() { } if (FD_ISSET(server.socket, &fds)) { - ServerPacket pkt; - if (client_recv_packet(&pkt)) - write_all(STDOUT_FILENO, pkt.buf, pkt.len); + Packet pkt; + if (client_recv_packet(&pkt)) { + switch (pkt.type) { + case MSG_CONTENT: + write_all(STDOUT_FILENO, pkt.u.msg, pkt.len); + break; + } + } } if (FD_ISSET(STDIN_FILENO, &fds)) { - ClientPacket pkt = { .type = MSG_CONTENT }; + Packet pkt = { .type = MSG_CONTENT }; ssize_t len = read(STDIN_FILENO, pkt.u.msg, sizeof(pkt.u.msg)); if (len == -1 && errno != EAGAIN && errno != EINTR) die("client-stdin"); @@ -121,6 +131,7 @@ static int client_mainloop() { client.need_resize = true; } else if (pkt.u.msg[0] == KEY_DETACH) { pkt.type = MSG_DETACH; + pkt.len = 0; client_send_packet(&pkt); return -1; } else { diff --git a/debug.c b/debug.c @@ -1,8 +1,7 @@ #ifdef NDEBUG static void debug(const char *errstr, ...) { } -static void print_client_packet(const char *prefix, ClientPacket *pkt) { } +static void print_packet(const char *prefix, Packet *pkt) { } static void print_client_packet_state(const char *prefix, ClientPacketState *pkt) { } -static void print_server_packet(const char *prefix, ServerPacket *pkt) { } static void print_server_packet_state(const char *prefix, ServerPacketState *pkt) { } #else @@ -13,7 +12,7 @@ static void debug(const char *errstr, ...) { va_end(ap); } -static void print_client_packet(const char *prefix, ClientPacket *pkt) { +static void print_packet(const char *prefix, Packet *pkt) { char *s = "UNKNOWN"; switch (pkt->type) { case MSG_CONTENT: @@ -39,24 +38,20 @@ static void print_client_packet(const char *prefix, ClientPacket *pkt) { fprintf(stderr, "%c", pkt->u.msg[i]); fprintf(stderr, "\n"); } else { - fprintf(stderr, "%s %s\n", prefix, s); + fprintf(stderr, "%s %s len: %d\n", prefix, s, pkt->len); } } static void print_client_packet_state(const char *prefix, ClientPacketState *pkt) { - fprintf(stderr, "%s %d/%d\n", prefix, pkt->off, sizeof(ClientPacket)); + fprintf(stderr, "%s %d/%d\n", prefix, pkt->off, packet_size(&pkt->pkt)); if (is_client_packet_complete(pkt)) - print_client_packet(prefix, &pkt->pkt); -} - -static void print_server_packet(const char *prefix, ServerPacket *pkt) { - fprintf(stderr, "%s len: %d buf: \n\t%s\n", prefix, pkt->len, pkt->buf); + print_packet(prefix, &pkt->pkt); } static void print_server_packet_state(const char *prefix, ServerPacketState *pkt) { - fprintf(stderr, "%s %d/%d\n", prefix, pkt->off, pkt->pkt->len); + fprintf(stderr, "%s %d/%d\n", prefix, pkt->off, packet_size(pkt->pkt)); if (is_server_packet_complete(pkt)) - print_server_packet(prefix, pkt->pkt); + print_packet(prefix, pkt->pkt); } #endif /* NDEBUG */ diff --git a/server.c b/server.c @@ -42,18 +42,19 @@ static Client *server_accept_client(time_t now) { return c; } -static bool server_read_pty(ServerPacket *pkt) { - ssize_t len = read(server.pty, pkt->buf, sizeof(pkt->buf)); +static bool server_read_pty(Packet *pkt) { + pkt->type = MSG_CONTENT; + ssize_t len = read(server.pty, pkt->u.msg, sizeof(pkt->u.msg)); if (len != -1) pkt->len = len; else if (errno != EAGAIN && errno != EINTR) server.running = false; - print_server_packet("server-read-pty:", pkt); + print_packet("server-read-pty:", pkt); return len > 0; } static bool server_write_pty(ClientPacketState *pkt) { - int count = pkt->pkt.len - pkt->off; + size_t count = pkt->pkt.len - pkt->off; ssize_t len = write(server.pty, pkt->pkt.u.msg + pkt->off, count); if (len == -1) { if (errno != EAGAIN && errno != EINTR) @@ -65,16 +66,39 @@ static bool server_write_pty(ClientPacketState *pkt) { return len == count; } -static void server_place_packet(Client *c, ServerPacket *pkt) { +static void server_place_packet(Client *c, Packet *pkt) { c->output.pkt = pkt; c->output.off = 0; } +static bool server_recv_packet_header(Client *c) { + ClientPacketState *pkt = &c->input; + if (pkt->off >= packet_header_size()) + return true; + size_t count = packet_header_size() - pkt->off; + ssize_t len = recv(c->socket, ((char *)&pkt->pkt) + pkt->off, count, 0); + switch (len) { + case -1: + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { + case 0: + c->state = STATE_DISCONNECTED; + } + break; + default: + pkt->off += len; + break; + } + print_client_packet_state("server-recv:", pkt); + return len == count; +} + static bool server_recv_packet(Client *c) { ClientPacketState *pkt = &c->input; if (is_client_packet_complete(pkt)) return true; - size_t count = sizeof(ClientPacket) - pkt->off; + if (!server_recv_packet_header(c)) + return false; + size_t count = packet_size(&pkt->pkt) - pkt->off; ssize_t len = recv(c->socket, ((char *)&pkt->pkt) + pkt->off, count, 0); switch (len) { case -1: @@ -95,8 +119,8 @@ static bool server_send_packet(Client *c) { ServerPacketState *pkt = &c->output; if (is_server_packet_complete(pkt)) return true; - size_t count = pkt->pkt->len - pkt->off; - ssize_t len = send(c->socket, pkt->pkt->buf + pkt->off, count, 0); + size_t count = packet_size(pkt->pkt) - pkt->off; + ssize_t len = send(c->socket, (char*)pkt->pkt + pkt->off, count, 0); switch (len) { case -1: if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { @@ -138,7 +162,7 @@ static bool server_queue_empty() { return server.queue_count == 0; } -static bool server_queue_packet(ClientPacket *pkt) { +static bool server_queue_packet(Packet *pkt) { if (server.queue_count >= countof(server.queue)) return false; server.queue[server.queue_insert] = *pkt; @@ -148,7 +172,7 @@ static bool server_queue_packet(ClientPacket *pkt) { return true; } -static ClientPacket *server_peek_packet() { +static Packet *server_peek_packet() { return &server.queue[server.queue_remove]; }