wip, doesnt compile: start implementing read functions

This commit is contained in:
Gergely Polonkai 2019-01-13 08:01:33 +01:00
parent 505573ee03
commit 495c2a37c2
2 changed files with 210 additions and 4 deletions

View File

@ -4,6 +4,9 @@
#include "sbot.h"
#define MAX_MESSAGE_SIZE 32768
#define BOXS_MAXLEN 4096
struct _SsbScuttler {
GObject parent_instance;
@ -20,6 +23,7 @@ struct _SsbScuttler {
guchar nonce1[24];
guchar nonce2[24];
guchar rx_nonce[24];
guchar rx_buf[BOXS_MAXLEN];
gsize rx_buf_pos;
gsize rx_buf_len;
gboolean noauth;
@ -56,9 +60,6 @@ typedef enum {
SSB_STREAM_STATE_ENDED_ERROR,
} SsbStreamState;
#define MAX_MESSAGE_SIZE 32768
#define BOXS_MAXLEN 4096
G_DEFINE_QUARK(ssb_scttler_error_quark, ssb_scuttler_error);
G_DEFINE_TYPE(SsbScuttler, ssb_scuttler, G_TYPE_INITIALLY_UNOWNED);
@ -367,7 +368,7 @@ read_inbound(GSocket *socket, GIOCondition condition, SsbScuttler *scuttler)
data->read_buffer = g_malloc(MAX_MESSAGE_SIZE);
g_input_stream_read_async(stream,
data->read_buffer, MAX_MESSAGE_SIZE,
data->read_buffer, 2,
G_PRIORITY_DEFAULT,
NULL,
data_read, data);
@ -870,6 +871,206 @@ ssb_scuttler_send_packet(SsbScuttler *scuttler,
return TRUE;
}
static gboolean
bs_read_packet(SsbScuttler *scuttler, gpointer buf, gsize *lenp, GError **error)
{
guchar boxed_header[34];
gsize len;
GError *err = NULL;
if (!ssb_scuttler_read(scuttler, boxed_header, 34, &err)) {
if (err->code == G_IO_ERROR_BROKEN_PIPE) {
g_propagate_error(error, err);
} else {
g_set_error(error,
SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_READ,
"Failed to read boxed packet header");
}
return FALSE;
}
BoxsHeader header;
if (crypto_secretbox_open_easy((guchar *
)&header, boxed_header, 34, scuttler->rx_nonce, scuttler->decrypt_key) < 0) {
g_set_error(error,
SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_DECRYPT,
"Failed to unbox packet header");
return FALSE;
}
increment_nonce(scuttler->rx_nonce);
if ((header.len == 0) && !memcmp(header.mac, zeros, 16)) {
g_set_error(error,
G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
"Broken pipe");
return FALSE;
}
len = g_ntohs(header.len);
if (len > BOXS_MAXLEN) {
g_set_error(error,
SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_RESPONSE_TOO_LARGE,
"Received boxed packet too large");
return FALSE;
}
guchar boxed_data[len + 16];
if (!ssb_scuttler_read(scuttler, boxed_data + 16, len, &err)) {
g_propagate_error(error, err);
return FALSE;
}
memcpy(boxed_data, header.mac, 16);
if (crypto_secretbox_open_easy(buf, boxed_data, len + 16, scuttler->rx_nonce, scuttler->decrypt_key) < 0) {
g_set_error(error,
SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_CRYPT,
"Failed to unbx packet data");
return FALSE;
}
increment_nonce(scuttler->rx_nonce);
if (lenp) {
*lenp = len;
}
return TRUE;
}
static gboolean
bs_read(SsbScuttler *scuttler, gpointer buf, gsize len)
{
size_t remaining;
GError *err = NULL;
while (len > 0) {
remaining = (scuttler->rx_buf_len > len) ? len : scuttler->rx_buf_len;
if (buf) {
memcpy(buf, scuttler->rx_buf + scuttler->rx_buf_pos, remaining);
}
scuttler->rx_buf_len -= remaining;
scuttler->rx_buf_pos += remaining;
len -= remaining;
buf += remaining;
if (len == 0) {
return TRUE;
}
if (bs_read_packet(scuttler, scuttler->rx_buf, &(scuttler->rx_buf_len), &err) < 0) {
return FALSE;
}
scuttler->rx_buf_pos = 0;
}
return TRUE;
}
static gboolean
ps_read_header(SsbScuttler *scuttler, gsize *len, guint32 *req_id, SsbPacketFlags *flags)
{
char buf[9];
PacketHeader header;
if (!bs_read(scuttler, buf, sizeof(buf))) {
return FALSE;
}
memcpy(&header, buf + 1, 8);
if (len) {
*len = g_ntohl(header.len);
}
if (req_id) {
*req_id = g_ntohl(header.request_id);
}
if (flags) {
*flags = buf[0];
}
return TRUE;
}
static gboolean
ps_reject(SsbScuttler *scuttler, gsize len, guint32 req, SsbPacketFlags flags, GError **error)
{
g_debug("Ignoring packet");
if (bs_read_out(scuttler, len) < 0) {
g_set_error(error,
SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_READ,
"bs_read_out");
return FALSE;
}
}
static gboolean
ssb_scuttler_read_async(SsbScuttler *scuttler, guint32 req_id, GError **error)
{
guint32 req;
gsize len;
SsbPacketFlags flags;
while (TRUE) {
if (!ps_read_header(scuttler, &len, &req, &flags)) {
g_set_error(error, SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_READ, "ps_read_header");
return FALSE;
}
if (req == -req_id) {
break;
}
if ((req == 0) && (len == 0)) {
g_set_error(error, SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_STREAM_END, "Unexpected end of parent stream");
return FALSE;
}
ps_reject(scuttler, len, req, flags);
}
if (flags & SSB_PACKET_FLAGS_END) {
gint rc;
if ((rc = ps_read_error(scuttler, flags, len)) < 0) {
g_set_error(error, SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_READ, "bs_read_error");
return FALSE;
}
if (rc == 1) {
return 2; // TODO: What is this for?
}
return 1;
}
if (bs_read_out(bs, buffer, len) < 0) {
g_set_error(error, SSB_SCUTTLER_ERROR, SSB_SCUTTLER_ERROR_READ, "bs_read_out");
return FALSE;
}
}
// was: muxrpc_call
/**
* ssb_scuttler_muxrpc_call:

View File

@ -15,6 +15,11 @@ typedef enum {
SSB_SCUTTLER_ERROR_REQUEST_TOO_LARGE,
SSB_SCUTTLER_ERROR_SEND,
SSB_SCUTTLER_ERROR_NOTCONNECTED,
SSB_SCUTTLER_ERROR_READ,
SSB_SCUTTLER_ERROR_CRYPT,
SSB_SCUTTLER_ERROR_DECRYPT,
SSB_SCUTTLER_ERROR_RESPONSE_TOO_LARGE,
SSB_SCUTTLER_ERROR_STREAM_END,
} SsbScuttlerError;
G_BEGIN_DECLS