diff options
author | Nathan Straz <nstraz@redhat.com> | 2013-08-01 00:43:15 -0400 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2013-09-11 17:33:04 -0400 |
commit | 063f117b1dbe3868bcfe1933967d2a665b3de0db (patch) | |
tree | 8daf922d778dcdc6f96497c08d2131de12fb709b /sockutil.c | |
parent | 441a1f8e1eb63464540a8852b246120284fefc11 (diff) | |
download | qarsh-063f117b1dbe3868bcfe1933967d2a665b3de0db.tar.gz qarsh-063f117b1dbe3868bcfe1933967d2a665b3de0db.tar.xz qarsh-063f117b1dbe3868bcfe1933967d2a665b3de0db.zip |
Start by adding a packet size to the existing protocol
Diffstat (limited to 'sockutil.c')
-rw-r--r-- | sockutil.c | 63 |
1 files changed, 54 insertions, 9 deletions
@@ -19,6 +19,7 @@ */ #include <sys/types.h> #include <sys/socket.h> +#include <sys/uio.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> @@ -196,22 +197,58 @@ connect_to_peer(struct sockaddr_storage *peer, int port) return sd; } +/* + * All incoming and outgoing packets go through this function. + * Caller should make sure the fd is ready to read. + */ +typedef struct { + char buf[QARSH_MAX_PACKET_SIZE]; + int start; + int end; +} Buffer; struct qa_packet * recv_packet(int fd) { - char *packetbuf; - int packetsize; + static Buffer pb = { "", 0, 0 }; + uint32_t packetsize; struct qa_packet *qp = NULL; + int ret; - packetbuf = malloc(QARSH_MAX_PACKET_SIZE); - memset(packetbuf, 0, QARSH_MAX_PACKET_SIZE); + if (pb.start == pb.end && pb.start) + pb.start = pb.end = 0; + +recv_read: + ret = read(fd, pb.buf, QARSH_MAX_PACKET_SIZE - pb.start); + if (ret > 0) { + pb.end = pb.start + ret; + /* get packet size from the packet */ + packetsize = ntohl(*(uint32_t *)(pb.buf+pb.start)); + if (packetsize > QARSH_MAX_PACKET_SIZE) { + printf("Packet size too large, %d > %d\n", packetsize, QARSH_MAX_PACKET_SIZE); + return NULL; + } else if (packetsize <= (ret - sizeof packetsize)) { + pb.start += sizeof packetsize; + qp = parse_packets(pb.buf + pb.start, pb.end - pb.start); + } else { /* packetsize > what we read, we need to read more */ + printf("Compacting buffer to fit rest of packet, %d read, %d left\n", ret, packetsize - ret); + memmove(pb.buf, pb.buf + pb.start, pb.end - pb.start); + pb.end -= pb.start; + pb.start = 0; + goto recv_read; + } - packetsize = read(fd, packetbuf, QARSH_MAX_PACKET_SIZE); - if (packetsize > 0) { - qp = parse_packets(packetbuf, packetsize); + /* Get the packet buffer ready for the next call */ + if (packetsize == (ret - sizeof packetsize)) { /* The read was a complete packet */ + pb.start = pb.end = 0; + printf("Complete read used\n"); + } else { + pb.start += packetsize; + memmove(pb.buf, pb.buf + pb.start, pb.end - pb.start); + pb.end -= pb.start; + pb.start = 0; + } } - free(packetbuf); return qp; } @@ -220,11 +257,19 @@ send_packet(int fd, struct qa_packet *qp) { char *packetbuf; int packetsize; + uint32_t netsize; ssize_t ret; + struct iovec iovs[2]; packetbuf = qptostr(qp, &packetbuf, &packetsize); - ret = write(fd, packetbuf, packetsize); + netsize = htonl(packetsize); + iovs[0].iov_base = &netsize; + iovs[0].iov_len = sizeof netsize; + iovs[1].iov_base = packetbuf; + iovs[1].iov_len = packetsize; + + ret = writev(fd, iovs, 2); free(packetbuf); return ret; } |