File: connection.c

package info (click to toggle)
bcron 0.11-8
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 728 kB
  • sloc: sh: 3,099; ansic: 2,416; makefile: 28
file content (65 lines) | stat: -rw-r--r-- 1,290 bytes parent folder | download | duplicates (4)
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;
}