summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Straz <nstraz@redhat.com>2013-08-01 00:43:15 -0400
committerNathan Straz <nstraz@redhat.com>2013-09-11 17:33:04 -0400
commit063f117b1dbe3868bcfe1933967d2a665b3de0db (patch)
tree8daf922d778dcdc6f96497c08d2131de12fb709b
parent441a1f8e1eb63464540a8852b246120284fefc11 (diff)
Start by adding a packet size to the existing protocol
-rw-r--r--qarsh_packet.c11
-rw-r--r--sockutil.c63
2 files changed, 64 insertions, 10 deletions
diff --git a/qarsh_packet.c b/qarsh_packet.c
index e5018ed..0000a31 100644
--- a/qarsh_packet.c
+++ b/qarsh_packet.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2005-2008 Red Hat, Inc. All rights reserved.
+ * Copyright © 2005-2013 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions of the
@@ -16,6 +16,15 @@
*
* Red Hat Author(s): Nathan Straz <nstraz@redhat.com>
* Dean Jansa <djansa@redhat.com>
+ *
+ * New packet format (modeled after SSH)
+ *
+ * uint32 packet size
+ * uint32 sequence number
+ * byte packet type
+ * payload
+ * - strings are sent as uint32 length + chars
+ *
*/
#include <string.h>
diff --git a/sockutil.c b/sockutil.c
index 14a058d..4ccca03 100644
--- a/sockutil.c
+++ b/sockutil.c
@@ -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;
}