/
connection.c
65 lines (63 loc) · 1.26 KB
/
connection.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <bglibs/sysdeps.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <bglibs/str.h>
#include <bglibs/unix.h>
#include "bcron.h"
void connection_init(struct connection* c, int fd, void* data)
{
memset(c, 0, sizeof *c);
c->fd = fd;
c->state = LENGTH;
c->data = data;
nonblock_on(fd);
}
int connection_read(struct connection* c,
void (*handler)(struct connection*))
{
static char buf[512];
long rd;
long i;
if ((rd = read(c->fd, buf, sizeof buf)) <= 0)
return rd;
for (i = 0; i < rd; ) {
/* Optimize packet appends */
if (c->state == DATA) {
long todo = rd - i;
if (c->packet.len + todo >= c->length) {
todo = c->length - c->packet.len;
c->state = COMMA;
}
str_catb(&c->packet, buf + i, todo);
i += todo;
}
else {
const char ch = buf[i++];
switch (c->state) {
case LENGTH:
if (ch == ':') {
if (!str_ready(&c->packet, c->length)) {
errno = ENOMEM;
return -1;
}
c->packet.len = 0;
c->state = DATA;
}
else if (isdigit(ch))
c->length = c->length * 10 + ch - '0';
break;
case COMMA:
if (ch == ',') {
c->state = LENGTH;
handler(c);
c->length = 0;
}
break;
case DATA: ;
}
}
}
return rd;
}