arbitrary number of packets over the connection before closing it.
To exchange data, the transport protocol is segmented into byte sequences.
-Each byte sequence is prefixed by a 16-bit length header in network order,
-followed by the data. The maximum segment length is 65535 bytes, and the length
-field contains the length of the data only, not including the length field
-itself.
+Each byte sequence is prefixed by a 32-bit length header in network order,
+followed by the data. The maximum segment length is currently limited to 512KB
+of data, and the length field contains the length of the data only, not
+including the length field itself.
The order of byte sequences must be strict, byte sequences must arrive in the
same order as sent.
#include "libvici.h"
#include "vici_builder.h"
#include "vici_dispatcher.h"
+#include "vici_socket.h"
#include <library.h>
#include <threading/mutex.h>
/**
* Handle a command response message
*/
-static bool handle_response(vici_conn_t *conn, u_int16_t len)
+static bool handle_response(vici_conn_t *conn, u_int32_t len)
{
chunk_t buf;
/**
* Dispatch received event message
*/
-static bool handle_event(vici_conn_t *conn, u_int16_t len)
+static bool handle_event(vici_conn_t *conn, u_int32_t len)
{
vici_message_t *message;
event_t *event;
CALLBACK(on_read, bool,
vici_conn_t *conn, stream_t *stream)
{
- u_int16_t len;
+ u_int32_t len;
u_int8_t op;
ssize_t hlen;
}
}
- len = ntohs(len);
+ len = ntohl(len);
+ if (len > VICI_MESSAGE_SIZE_MAX)
+ {
+ return read_error(conn, EBADMSG);
+ }
if (len-- < sizeof(op))
{
return read_error(conn, EBADMSG);
vici_message_t *message;
vici_res_t *res;
chunk_t data;
- u_int16_t len;
+ u_int32_t len;
u_int8_t namelen, op;
message = req->b->finalize(req->b);
op = VICI_CMD_REQUEST;
namelen = strlen(req->name);
data = message->get_encoding(message);
- len = htons(sizeof(op) + sizeof(namelen) + namelen + data.len);
+ len = htonl(sizeof(op) + sizeof(namelen) + namelen + data.len);
if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
!conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
{
event_t *event;
- u_int16_t len;
+ u_int32_t len;
u_int8_t namelen, op;
int ret = 1;
op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
namelen = strlen(name);
- len = htons(sizeof(op) + sizeof(namelen) + namelen);
+ len = htonl(sizeof(op) + sizeof(namelen) + namelen);
if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
!conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
!conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
ck_assert_int_eq(data->id, id);
/* count number of bytes, including the header */
- data->bytes += buf.len + sizeof(u_int16_t);
+ data->bytes += buf.len + sizeof(u_int32_t);
/* echo back data chunk */
data->s->send(data->s, id, chunk_clone(buf));
}
stream_t *c;
test_data_t data = {};
chunk_t x, m = chunk_from_chars(
- 0x00,0x00,
- 0x00,0x01, 0x01,
- 0x00,0x05, 0x11,0x12,0x13,0x14,0x15,
- 0x00,0x0A, 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02A,
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01, 0x01,
+ 0x00,0x00,0x00,0x05, 0x11,0x12,0x13,0x14,0x15,
+ 0x00,0x00,0x00,0x0A, 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02A,
);
char buf[m.len];
- u_int16_t len;
+ u_int32_t len;
lib->processor->set_threads(lib->processor, 4);
/** bytes of length header sent/received */
u_char hdrlen;
/** bytes of length header */
- char hdr[sizeof(u_int16_t)];
+ char hdr[sizeof(u_int32_t)];
/** send/receive buffer on heap */
chunk_t buf;
/** bytes sent/received in buffer */
- u_int16_t done;
+ u_int32_t done;
} msg_buf_t;
/**
static bool do_read(private_vici_socket_t *this, entry_t *entry,
stream_t *stream)
{
+ u_int32_t msglen;
ssize_t len;
/* assemble the length header first */
entry->in.hdrlen += len;
if (entry->in.hdrlen == sizeof(entry->in.hdr))
{
+ msglen = untoh32(entry->in.hdr);
+ if (msglen > VICI_MESSAGE_SIZE_MAX)
+ {
+ DBG1(DBG_CFG, "vici message length %u exceeds %u bytes limit, "
+ "ignored", msglen, VICI_MESSAGE_SIZE_MAX);
+ return FALSE;
+ }
/* header complete, continue with data */
- entry->in.buf = chunk_alloc(untoh16(entry->in.hdr));
+ entry->in.buf = chunk_alloc(msglen);
}
}
METHOD(vici_socket_t, send_, void,
private_vici_socket_t *this, u_int id, chunk_t msg)
{
- if (msg.len <= (u_int16_t)~0)
+ if (msg.len <= VICI_MESSAGE_SIZE_MAX)
{
entry_selector_t *sel;
msg_buf_t *out;
INIT(out,
.buf = msg,
);
- htoun16(out->hdr, msg.len);
+ htoun32(out->hdr, msg.len);
array_insert(entry->out, ARRAY_TAIL, out);
if (array_count(entry->out) == 1)
}
else
{
- DBG1(DBG_CFG, "vici message exceeds maximum size, discarded");
+ DBG1(DBG_CFG, "vici message size %zu exceeds maximum size of %u, "
+ "discarded", msg.len, VICI_MESSAGE_SIZE_MAX);
chunk_clear(&msg);
}
}
#include <library.h>
+/**
+ * Maximum size of a single message exchanged.
+ */
+#define VICI_MESSAGE_SIZE_MAX (512 * 1024)
+
typedef struct vici_socket_t vici_socket_t;
/**