aura  0.1
 All Data Structures Functions Variables Modules Pages
packetizer.c
1 #include <aura/aura.h>
2 #include <aura/private.h>
3 #include <aura/crc.h>
4 #include <aura/packetizer.h>
5 
6 
7 /*
8  *
9  * SEARCH -> READ_HEADER -> READ_DATA
10  *
11  */
12 enum packetizer_state {
13  STATE_SEARCH_START=0,
14  STATE_READ_HEADER,
15  STATE_READ_DATA
16 };
17 
18 int aura_packetizer_max_overhead()
19 {
20  return sizeof(struct aura_packet8);
21 }
22 
23 struct aura_packetizer *aura_packetizer_create(struct aura_node *node)
24 {
25  struct aura_packetizer *pkt = malloc(sizeof(*pkt));
26 
27  if (!pkt) {
28  BUG(node, "packetizer allocation failed");
29  return NULL;
30  }
31  pkt->node = node;
32  pkt->endian = -1; /* Not yet determined */
33  pkt->recvcb = NULL;
34  pkt->curbuf = NULL;
35  pkt->cont = 0;
36  pkt->copied = 0;
37  return pkt;
38 }
39 
40 void aura_packetizer_destroy(struct aura_packetizer *pkt)
41 {
42  if (pkt->curbuf)
43  aura_buffer_release(pkt->curbuf);
44  free(pkt);
45 }
46 
47 void aura_packetizer_set_receive_cb(
48  struct aura_packetizer *pkt,
49  void (*recvcb)(struct aura_buffer *buf, void *arg),
50  void *arg)
51 {
52  pkt->recvcb = recvcb;
53  pkt->recvarg = arg;
54 }
55 
56 int aura_packetizer_verify_header(struct aura_packetizer *pkt, struct aura_packet8 *packet)
57 {
58  if (packet->start != PACKET_START)
59  return -1;
60  if (packet->datalen != ((~packet->invdatalen) & 0xff))
61  return -2;
62  if (packet->cont != pkt->expect_cont)
63  return -3;
64  return 0;
65 }
66 
67 int aura_packetizer_verify_data(struct aura_packetizer *pkt, struct aura_packet8 *packet)
68 {
69  uint8_t crc = crc8(0, (unsigned char *)packet->data, packet->datalen);
70  return !(packet->crc8 == crc);
71 }
72 
73 void aura_packetizer_encapsulate(struct aura_packetizer * pkt,
74  struct aura_packet8 * packet,
75  size_t len)
76 {
77  if (len > 255)
78  BUG(pkt->node, "Packet is too big");
79 
80  packet->start = PACKET_START;
81  packet->cont = (pkt->cont++ & 0xff);
82  pkt->expect_cont = packet->cont;
83  packet->datalen = len;
84  packet->invdatalen = ~packet->datalen;
85  packet->crc8 = crc8(0, (unsigned char *)packet->data, packet->datalen);
86 }
87 
88 void aura_packetizer_reset(struct aura_packetizer *pkt)
89 {
90  pkt->state = STATE_SEARCH_START;
91  pkt->copied = 0;
92  if (pkt->curbuf) {
93  aura_buffer_release(pkt->curbuf);
94  pkt->curbuf = NULL;
95  }
96 }
97 
98 static void packetizer_dispatch_packet(struct aura_packetizer *pkt)
99 {
100  slog(4, SLOG_DEBUG, "packetizer: dispatching packet");
101  aura_buffer_rewind(pkt->curbuf);
102  if (pkt->recvcb)
103  pkt->recvcb(pkt->curbuf, pkt->recvarg);
104  else /* No callback? Free the buffer */
105  aura_buffer_release(pkt->curbuf);
106  pkt->curbuf = NULL;
107  aura_packetizer_reset(pkt);
108 }
109 
117 int aura_packetizer_feed_once(struct aura_packetizer *pkt, const char *data, size_t len)
118 {
119  int pos = 0;
120  int ret;
121  struct aura_packet8 *hdr = &pkt->headerbuf;
122  switch (pkt->state) {
123  case STATE_SEARCH_START:
124  while ((pos < len) && data[pos] != PACKET_START)
125  pos++;
126  if (pos < len) {
127  pkt->state = STATE_READ_HEADER;
128  pkt->copied = 0;
129  slog(4, SLOG_DEBUG, "packetizer: Found start at %d", pos);
130  }
131  break;
132  case STATE_READ_HEADER:
133  {
134  int tocopy = min_t(int, sizeof(struct aura_packet8) - pkt->copied, len);
135  char *dest = (char *)&pkt->headerbuf;
136  memmove(&dest[pkt->copied], &data[pos], tocopy);
137  pkt->copied += tocopy;
138  pos += tocopy;
139  if ((sizeof(struct aura_packet8) == pkt->copied)) {
140  ret = aura_packetizer_verify_header(pkt, &pkt->headerbuf);
141  if (0 == ret) {
142  pkt->state = STATE_READ_DATA;
143  pkt->copied = 0;
144  if (pkt->curbuf)
145  BUG(pkt->node, "Internal packetizer bug");
146  pkt->curbuf = aura_buffer_request(pkt->node, hdr->datalen);
147  if (!pkt->curbuf)
148  BUG(pkt->node, "Packetizer failed to alloc buffer");
149  memcpy(
150  pkt->curbuf->data,
151  &pkt->headerbuf,
152  sizeof(pkt->headerbuf)
153  );
154  } else {
155  aura_packetizer_reset(pkt);
156  aura_packetizer_feed(pkt, &dest[1],
157  sizeof(struct aura_packet8) - 1);
158  }
159  }
160  break;
161  }
162  case STATE_READ_DATA:
163  {
164  int tocopy = min_t(int, hdr->datalen - pkt->copied, len);
165  aura_buffer_put_bin(pkt->curbuf, &data[pos], tocopy);
166  pos += tocopy;
167  pkt->copied += tocopy;
168  if (pkt->copied == hdr->datalen) {
169  aura_hexdump("out", pkt->curbuf->data, pkt->curbuf->pos);;
170  ret = aura_packetizer_verify_data(pkt,
171  (struct aura_packet8 *) pkt->curbuf->data);
172  if (ret == 0) {
173  packetizer_dispatch_packet(pkt);
174  } else {
175  struct aura_buffer *tmp = pkt->curbuf;
176  int torefeed = pkt->copied;
177  pkt->curbuf = NULL;
178  aura_buffer_rewind(tmp);
179  aura_packetizer_reset(pkt);
180  aura_packetizer_feed(pkt, aura_buffer_get_bin(tmp, torefeed),
181  torefeed);
182  aura_buffer_release(tmp);
183  }
184  }
185  break;
186  }
187  }
188  return pos;
189 }
197 void aura_packetizer_feed(struct aura_packetizer *pkt, const char *data, size_t len)
198 {
199  int pos=0;
200  while (pos < len)
201  pos+= aura_packetizer_feed_once(pkt, &data[pos], len-pos);
202 }
struct aura_buffer * aura_buffer_request(struct aura_node *nd, int size)
Definition: buffer.c:40
void aura_buffer_put_bin(struct aura_buffer *buf, const void *data, int len)
Copy data of len bytes to aura buffer from a buffer pointed by data.
Definition: retparse.c:71
int pos
Definition: aura.h:339
static void aura_buffer_rewind(struct aura_buffer *buf)
Definition: inlines.h:93
const void * aura_buffer_get_bin(struct aura_buffer *buf, int len)
Get a pointer to the binary data block within buffer and advance internal pointer by len bytes...
Definition: retparse.c:60
void aura_buffer_release(struct aura_buffer *buf)
Definition: buffer.c:80