Skip to content

Commit

Permalink
Start of blocking vs non-blocking receive call.
Browse files Browse the repository at this point in the history
This is now officially a mess :(
  • Loading branch information
voutilad committed Dec 1, 2023
1 parent 3d48d35 commit bf3c74f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 12 deletions.
9 changes: 7 additions & 2 deletions client_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ main(int argc, char **argv)
printf("sent " SSIZE_T_PARAM " bytes (header + payload)\n", len);

memset(buf, 0, sizeof(buf));
len = dumb_recv(&ws, buf, sizeof(buf));
len = 0;
do {
len = dumb_recv(&ws, buf, sizeof(buf));
} while (len == DWS_WANT_POLL);
snprintf(out, sizeof(out), "%s", buf);
printf("received payload of " SSIZE_T_PARAM " bytes:\n---\n%s\n---\n",
len, out);
Expand All @@ -93,7 +96,9 @@ main(int argc, char **argv)
printf("sent " SSIZE_T_PARAM " bytes (header + payload)\n", len);

memset(buf, 0, sizeof(buf));
len = dumb_recv(&ws, buf, sizeof(buf));
do {
len = dumb_recv(&ws, buf, sizeof(buf));
} while (len == DWS_WANT_POLL);
snprintf(out, sizeof(out), "%s", buf);
printf("received payload of " SSIZE_T_PARAM " bytes:\n---\n%s\n---\n",
len, out);
Expand Down
69 changes: 59 additions & 10 deletions dws.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static int rng_initialized = 0;
static const char B64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static ssize_t ws_read(struct websocket *, void *, size_t);
static ssize_t ws_read_all(struct websocket *, void *, size_t);
static ssize_t ws_read_txt(struct websocket *, void *, size_t);


Expand Down Expand Up @@ -183,6 +184,52 @@ ws_read(struct websocket *ws, void *buf, size_t buflen)
_buf = (char*) buf;
_buflen = (ssize_t) buflen;

while (_buflen > 0) {
if (ws->ctx) {
sz = tls_read(ws->ctx, _buf, _buflen);
if (sz == TLS_WANT_POLLIN || sz == TLS_WANT_POLLOUT) {
if (len == 0)
return DWS_WANT_POLL;
break;
} else if (sz == -1)
return -1;
} else {
sz = read(ws->s, _buf, _buflen);
if (sz == -1 && errno == EAGAIN) {
if (len == 0)
return DWS_WANT_POLL;
break;
}
else if (sz == -1)
return -1;
}

_buf += sz;
_buflen -= sz;
len += sz;
}

// TODO: figure out how we want to handle errors...
// win32 spits out a different error than posix systems, btw.

return len;
}

/*
* Read at `buflen` bytes into the given buffer, busy polling as needed.
*/
static ssize_t
ws_read_all(struct websocket *ws, void *buf, size_t buflen)
{
ssize_t _buflen, sz, len = 0;
char *_buf;

if (buflen > INT_MAX)
crap(1, "ws_read: buflen too large");

_buf = (char*) buf;
_buflen = (ssize_t) buflen;

while (_buflen > 0) {
if (ws->ctx) {
sz = tls_read(ws->ctx, _buf, _buflen);
Expand Down Expand Up @@ -642,8 +689,8 @@ dumb_recv(struct websocket *ws, void *buf, size_t buflen)

// Read first 2 bytes to figure out the framing details.
n = ws_read(ws, frame, 2);
if (n < 2)
return -1;
if (n < 0)
return n;

// Now to validate the frame...
if (!(frame[0] & 0x80)) {
Expand All @@ -655,7 +702,7 @@ dumb_recv(struct websocket *ws, void *buf, size_t buflen)
if (payload_len == 126) {
// Need the next two bytes to get the actual payload size, which
// arrives in network byte order.
n = ws_read(ws, frame + 2, 2);
n = ws_read_all(ws, frame + 2, 2);
if (n < 2)
return -1;
payload_len = frame[2] << 8;
Expand All @@ -667,7 +714,7 @@ dumb_recv(struct websocket *ws, void *buf, size_t buflen)
payload_len = MIN(payload_len, buflen);
if (payload_len == 0)
return payload_len;
n = ws_read(ws, buf, (size_t) payload_len);
n = ws_read_all(ws, buf, (size_t) payload_len);
if (n < payload_len)
return -1;

Expand Down Expand Up @@ -708,8 +755,8 @@ dumb_ping(struct websocket *ws)
memset(frame, 0, sizeof(frame));

// Read first 2 bytes.
len = ws_read(ws, frame, 2);
if (len != 2)
len = ws_read_all(ws, frame, 2);
if (len < 0)
return -2;

// We should have a PONG reply.
Expand All @@ -722,7 +769,7 @@ dumb_ping(struct websocket *ws)

// Dump the rest of the data on the floor.
if (payload_len > 0) {
len = ws_read(ws, frame + 2, MIN(payload_len, sizeof(frame) - 2));
len = ws_read_all(ws, frame + 2, MIN(payload_len, sizeof(frame) - 2));
if (len < 1)
return -3;
}
Expand Down Expand Up @@ -775,10 +822,12 @@ dumb_close(struct websocket *ws)

// A valid RFC6455 websocket server MUST send a Close frame in response
// Read first 2 bytes.
len = ws_read(ws, frame, 2);
len = ws_read_all(ws, frame, 2);
if (len != 2)
return -2;

// If we don't have a CLOSE frame...someone screwed up before calling
// dumb_close and there's still unread data!
if (frame[0] != (0x80 + CLOSE))
return -3;

Expand All @@ -788,9 +837,9 @@ dumb_close(struct websocket *ws)

// Dump the rest of the data on the floor.
if (payload_len > 0) {
len = ws_read(ws, frame + 2, MIN(payload_len, sizeof(frame) - 2));
len = ws_read_all(ws, frame + 2, MIN(payload_len, sizeof(frame) - 2));
if (len < 1)
return -3;
return -4;
}

// Now close/shutdown our socket.
Expand Down
2 changes: 2 additions & 0 deletions dws.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct websocket {
// TODO: add basic auth details?
};

#define DWS_WANT_POLL -2

int dumb_connect(struct websocket *ws, char*, char*);
int dumb_connect_tls(struct websocket *ws, char*, char*, int);
int dumb_handshake(struct websocket *s, const char*, const char*, const char*);
Expand Down

0 comments on commit bf3c74f

Please sign in to comment.