1 /*
2  * This software is Copyright (c) 2016 Denis Burykin
3  * [denis_burykin yahoo com], [denis-burykin2014 yandex ru]
4  * and it is hereby released to the general public under the following terms:
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted.
7  *
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <sys/time.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <stdint.h>
18 
19 #include "pkt_comm.h"
20 
21 
pkt_error(const char * s,...)22 void pkt_error(const char *s, ...) {
23 	va_list ap;
24 	va_start(ap, s);
25 	vfprintf(stderr, s, ap);
26 	va_end(ap);
27 }
28 
29 int total_pkt_count=0;
get_pkt_count(void)30 int get_pkt_count(void)
31 {
32 	return total_pkt_count;
33 }
34 
pkt_new(int type,char * data,int data_len)35 struct pkt *pkt_new(int type, char *data, int data_len)
36 {
37 	if (data_len > PKT_MAX_DATA_LEN) {
38 		pkt_error("pkt_new(type %d): data_len(%d) exceeds %d bytes\n",
39 				type, data_len, PKT_MAX_DATA_LEN);
40 		exit(-1);
41 		return NULL;
42 	}
43 
44 	struct pkt *pkt = malloc(sizeof(struct pkt));
45 	if (!pkt) {
46 		pkt_error("pkt_new(type %d): unable to allocate %d bytes\n",
47 				type, sizeof(struct pkt));
48 		return NULL;
49 	}
50 
51 	pkt->version = PKT_COMM_VERSION;
52 	pkt->type = type;
53 	pkt->data_len = data_len;
54 	pkt->id = 0;
55 
56 	pkt->data = data;
57 	pkt->header_ok = 0;
58 	pkt->partial_header_len = 0;
59 	pkt->partial_data_len = 0;
60 	pkt->header = NULL;
61 
62 	total_pkt_count++;
63 	return pkt;
64 }
65 
pkt_get_id(struct pkt * pkt)66 unsigned int pkt_get_id(struct pkt *pkt)
67 {
68 	return pkt->id;
69 }
70 
pkt_delete(struct pkt * pkt)71 void pkt_delete(struct pkt *pkt)
72 {
73 	if (pkt->data)
74 		free(pkt->data);
75 	if (pkt->partial_header_len && pkt->header)
76 		free(pkt->header);
77 	free(pkt);
78 	total_pkt_count--;
79 }
80 
81 //
82 // Create binary packet header in the area pointed to by *header
83 //
pkt_create_header(struct pkt * pkt,unsigned char * header)84 void pkt_create_header(struct pkt *pkt, unsigned char *header)
85 {
86 	pkt->header = header;
87 
88 	pkt->header[0] = pkt->version;
89 	pkt->header[1] = pkt->type;
90 	//pkt->header[2] = 0;
91 	//pkt->header[3] = 0;
92 	pkt->header[4] = pkt->data_len;
93 	pkt->header[5] = pkt->data_len >> 8;
94 	pkt->header[6] = pkt->data_len >> 16;
95 	//pkt->header[7] = 0;
96 	pkt->header[8] = pkt->id;
97 	pkt->header[9] = pkt->id >> 8;
98 }
99 
100 // Read checksum pointed to by 'src' and convert to integer type
101 //
pkt_checksum_read(unsigned char * src)102 PKT_CHECKSUM_TYPE pkt_checksum_read(unsigned char *src)
103 {
104 	return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
105 }
106 
107 //
108 // Calculate checksum of 'data' of length 'len'
109 // If 'dst' is not NULL, place checksum there
110 //
pkt_checksum(unsigned char * dst,unsigned char * data,int len)111 PKT_CHECKSUM_TYPE pkt_checksum(unsigned char *dst, unsigned char *data, int len)
112 {
113 	PKT_CHECKSUM_TYPE checksum = 0;
114 
115 	PKT_CHECKSUM_TYPE checksum_tmp = 0;
116 	int checksum_byte_count = 0;
117 
118 	int i;
119 	for (i = 0; i < len; i++) {
120 		checksum_tmp |= data[i] << 8 * checksum_byte_count;
121 		if (++checksum_byte_count == PKT_CHECKSUM_LEN) {
122 			checksum += checksum_tmp;
123 			checksum_tmp = 0;
124 			checksum_byte_count = 0;
125 		}
126 	}
127 	checksum += checksum_tmp;
128 
129 	checksum = ~checksum;
130 
131 	for (i = 0; i < PKT_CHECKSUM_LEN; i++) {
132 		if (dst)
133 			dst[i] = checksum >> 8 * i;
134 	}
135 	return checksum;
136 }
137 
138 //
139 // Convert binary packet header into human-readable string
140 // (for debug purposes)
141 //
pkt_header2str(struct pkt * pkt,unsigned char * header,char * str)142 void pkt_header2str(struct pkt *pkt, unsigned char *header, char *str)
143 {
144 	char tmp_str[16];
145 	int i;
146 	strcpy(str, "[ ");
147 	for (i=0; i < PKT_HEADER_LEN; i++) {
148 		if (i && !(i % 4))
149 			strcat(str, ". ");
150 		sprintf(tmp_str, "%d ", header[i]);
151 		strcat(str, tmp_str);
152 	}
153 	strcat(str, "]");
154 }
155 
156 //
157 // Process input packet header in the area pointed to by *header
158 // including checksum
159 // Return < 0 on error
160 //
pkt_process_header(struct pkt * pkt,unsigned char * header)161 int pkt_process_header(struct pkt *pkt, unsigned char *header)
162 {
163 	char str[256];
164 
165 	PKT_CHECKSUM_TYPE checksum = pkt_checksum(NULL, header, PKT_HEADER_LEN);
166 	PKT_CHECKSUM_TYPE checksum_got = pkt_checksum_read(header + PKT_HEADER_LEN);
167 	if (checksum_got != checksum) {
168 		pkt_error("pkt_process_header: bad checksum: got 0x%x, must be 0x%x\n",
169 			checksum_got, checksum);
170 		return -1;
171 	}
172 
173 	pkt->version = header[0];
174 	if (pkt->version != PKT_COMM_VERSION) {
175 		pkt_header2str(pkt, header, str);
176 		pkt_error("pkt_process_header: wrong version %d, must be %d, header: %s\n",
177 				pkt->version, PKT_COMM_VERSION, str);
178 		return -1;
179 	}
180 	pkt->type = header[1];
181 	if (!pkt->type) {
182 		pkt_header2str(pkt, header, str);
183 		pkt_error("pkt_process_header: empty packet type, header: %s\n", str);
184 		return -1;
185 	}
186 
187 	pkt->data_len = (unsigned)(header[4] | (header[5] << 8) | (header[6] << 16));
188 	if (!pkt->data_len || pkt->data_len > PKT_MAX_DATA_LEN) {
189 		pkt_header2str(pkt, header, str);
190 		pkt_error("pkt_process_header: bad data_len %d, header: %s\n",
191 				pkt->data_len, str);
192 		return -1;
193 	}
194 	pkt->id = header[8] | (header[9] << 8);
195 
196 	pkt->partial_header_len = 0;
197 	pkt->header_ok = 1;
198 	return 0;
199 }
200 
201 // ****************************************************************
202 
pkt_queue_new()203 struct pkt_queue *pkt_queue_new()
204 {
205 	struct pkt_queue *queue = malloc(sizeof(struct pkt_queue));
206 	if (!queue) {
207 		pkt_error("pkt_queue_new(): unable to allocate %d bytes\n",
208 				sizeof(struct pkt_queue));
209 		return NULL;
210 	}
211 	queue->count = 0;
212 	queue->empty_slot_idx = 0;
213 	queue->first_pkt_idx = 0;
214 
215 	int i;
216 	for (i = 0; i < PKT_QUEUE_MAX; i++)
217 		queue->pkt[i] = NULL;
218 
219 	return queue;
220 }
221 
pkt_queue_delete(struct pkt_queue * queue)222 void pkt_queue_delete(struct pkt_queue *queue)
223 {
224 	if (!queue) {
225 		pkt_error("pkt_queue_delete(): NULL argument\n");
226 		return;
227 	}
228 
229 	int i;
230 	for (i = 0; i < PKT_QUEUE_MAX; i++) {
231 		if (queue->pkt[i])
232 			pkt_delete(queue->pkt[i]);
233 	}
234 	free(queue);
235 }
236 
pkt_queue_push(struct pkt_queue * queue,struct pkt * pkt)237 int pkt_queue_push(struct pkt_queue *queue, struct pkt *pkt)
238 {
239 	if (queue->count == PKT_QUEUE_MAX)
240 		return -1;
241 
242 	queue->pkt[queue->empty_slot_idx] = pkt;
243 	if (++queue->empty_slot_idx == PKT_QUEUE_MAX)
244 		queue->empty_slot_idx = 0;
245 
246 	queue->count++;
247 	return 0;
248 }
249 
pkt_queue_full(struct pkt_queue * queue,int num)250 int pkt_queue_full(struct pkt_queue *queue, int num)
251 {
252 	return queue->count + num > PKT_QUEUE_MAX ? 1 : 0;
253 }
254 
pkt_queue_fetch(struct pkt_queue * queue)255 struct pkt *pkt_queue_fetch(struct pkt_queue *queue)
256 {
257 	if (!queue->count)
258 		return NULL;
259 
260 	struct pkt *pkt = queue->pkt[queue->first_pkt_idx];
261 	queue->pkt[queue->first_pkt_idx] = NULL;
262 	queue->count--;
263 
264 	if (++queue->first_pkt_idx == PKT_QUEUE_MAX)
265 		queue->first_pkt_idx = 0;
266 
267 	return pkt;
268 }
269 
270 // Get total size (including headers and checksums) of all packets in queue
pkt_queue_get_total_size(struct pkt_queue * queue)271 int pkt_queue_get_total_size(struct pkt_queue *queue)
272 {
273 	int total_size = 0;
274 
275 	int i;
276 	for (i = 0; i < PKT_QUEUE_MAX; i++)
277 		if (queue->pkt[i]) {
278 			total_size += queue->pkt[i]->data_len + PKT_HEADER_LEN;
279 			total_size += 2 * PKT_CHECKSUM_LEN;
280 		}
281 
282 	return total_size;
283 }
284 
285 // ****************************************************************
286 
pkt_comm_new(struct pkt_comm_params * params)287 struct pkt_comm *pkt_comm_new(struct pkt_comm_params *params)
288 {
289 	if (params->output_max_len <= 0 || params->input_max_len <= 0
290 			|| params->alignment < 0 || params->alignment > 256) {
291 		pkt_error("pkt_comm_new(): wrong pkt_comm_params\n");
292 		return NULL;
293 	}
294 
295 	struct pkt_comm *comm = malloc(sizeof(struct pkt_comm));
296 	if (!comm) {
297 		pkt_error("pkt_comm_new(): unable to allocate %d bytes\n",
298 				sizeof(struct pkt_comm));
299 		return NULL;
300 	}
301 	comm->params = params;
302 
303 	comm->output_queue = pkt_queue_new();
304 	if (!comm->output_queue) {
305 		free(comm);
306 		return NULL;
307 	}
308 	comm->output_buf = NULL;
309 
310 	comm->input_queue = pkt_queue_new();
311 	if (!comm->input_queue) {
312 		free(comm);
313 		return NULL;
314 	}
315 	comm->input_buf = malloc(params->input_max_len);
316 	if (!comm->input_buf) {
317 		pkt_error("pkt_comm_new(): unable to allocate %d bytes\n",
318 				params->input_max_len);
319 		free(comm);
320 		return NULL;
321 	}
322 	comm->input_buf_len = 0;
323 	comm->input_pkt = NULL;
324 
325 	comm->error = 0;
326 	return comm;
327 }
328 
pkt_comm_delete(struct pkt_comm * comm)329 void pkt_comm_delete(struct pkt_comm *comm)
330 {
331 	if (!comm) {
332 		pkt_error("pkt_comm_delete(): NULL argument\n");
333 		return;
334 	}
335 
336 	pkt_queue_delete(comm->input_queue);
337 	pkt_queue_delete(comm->output_queue);
338 	free(comm->input_buf);
339 	if (comm->output_buf)
340 		free(comm->output_buf);
341 	if (comm->input_pkt)
342 		pkt_delete(comm->input_pkt);
343 }
344 
345 
346 // ******************************************************************
347 //
348 // pkt_comm output over link layer
349 //
350 // ******************************************************************
351 
352 // allocates output buffer
353 // fetches all packets from output queue and puts them into output buffer
354 // calculates checksums
355 // deals with alignment issues
356 //
pkt_comm_create_output_buf(struct pkt_comm * comm)357 int pkt_comm_create_output_buf(struct pkt_comm *comm)
358 {
359 	// there's already output buffer
360 	if (comm->output_buf) {
361 		pkt_error("pkt_comm_create_output_buf(): buffer already created\n");
362 		return -1;
363 	}
364 
365 	// output queue empty, output buffer not created
366 	if (!comm->output_queue->count)
367 		return 0;
368 
369 	int size = pkt_queue_get_total_size(comm->output_queue);
370 	if (!size)
371 		return 0;
372 
373 	// alignment issue; pad with 0's
374 	int align = comm->params->alignment;
375 	int extra_zeroes = align && size % align ? align - size % align : 0;
376 	size += extra_zeroes;
377 
378 	comm->output_buf = malloc(size);
379 	if (!comm->output_buf) {
380 		pkt_error("pkt_comm_create_output_buf(): unable to allocate %d bytes\n", size);
381 		return 0;
382 	}
383 	comm->output_buf_size = size;
384 	comm->output_buf_offset = 0;
385 
386 	int i;
387 	for (i = 0; i < extra_zeroes; i++)
388 		comm->output_buf[size - i - 1] = 0;
389 
390 	// fetch all packets from output queue and put them into output buffer
391 	int offset = 0;
392 	struct pkt *pkt;
393 	while ( (pkt = pkt_queue_fetch(comm->output_queue)) ) {
394 
395 		pkt_create_header(pkt, comm->output_buf + offset);
396 		pkt_checksum(comm->output_buf + offset + PKT_HEADER_LEN,
397 				comm->output_buf + offset, PKT_HEADER_LEN);
398 		offset += PKT_HEADER_LEN + PKT_CHECKSUM_LEN;
399 
400 		memcpy(comm->output_buf + offset, pkt->data, pkt->data_len);
401 		pkt_checksum(comm->output_buf + offset + pkt->data_len,
402 				comm->output_buf + offset, pkt->data_len);
403 		offset += pkt->data_len + PKT_CHECKSUM_LEN;
404 
405 		pkt_delete(pkt);
406 	}
407 
408 	return size;
409 }
410 
411 /*
412 // Not tested
413 int pkt_comm_has_output_data(struct pkt_comm *comm)
414 {
415 	// There's data in output buffer
416 	if (comm->output_buf) {
417 		if (comm->output_buf_offset >= comm->output_buf_size
418 				|| !comm->output_buf_size) {
419 			// Looks like internal error
420 			pkt_error("pkt_comm_has_output_data: %d, %d\n",
421 				comm->output_buf_offset, comm->output_buf_size);
422 			return 0;
423 		}
424 		return 1;
425 	}
426 
427 	// There's data in output queue
428 	if (!comm->output_queue->count)
429 		return 1;
430 
431 	return 0;
432 }
433 */
434 
pkt_comm_get_output_data(struct pkt_comm * comm,int * len)435 unsigned char *pkt_comm_get_output_data(struct pkt_comm *comm, int *len)
436 {
437 	if (!comm->output_buf) {
438 		if (!pkt_comm_create_output_buf(comm)) {
439 			// No output data
440 			*len = 0;
441 			return NULL;
442 		}
443 	}
444 
445 	int size = comm->output_buf_size;
446 	int offset = comm->output_buf_offset;
447 	//printf("pkt: size %d off %d\n",size,offset);
448 	if (size - offset <= comm->params->output_max_len) {
449 		// TODO: check if there's data in output queue, add-up to buffer
450 		// if remeining size is less than max.transfer size over link layer
451 		*len = size - offset;
452 	} else {
453 		*len = comm->params->output_max_len;
454 	}
455 
456 	return comm->output_buf + offset;
457 }
458 
459 
pkt_comm_output_completed(struct pkt_comm * comm,int len,int error)460 void pkt_comm_output_completed(struct pkt_comm *comm, int len, int error)
461 {
462 	comm->error = error;
463 	if (error)
464 		return;
465 
466 	comm->output_buf_offset += len;
467 	if (comm->output_buf_offset >= comm->output_buf_size) {
468 		free(comm->output_buf);
469 		comm->output_buf = NULL;
470 	}
471 }
472 
473 // ******************************************************************
474 //
475 // pkt_comm input over link layer
476 //
477 // ******************************************************************
478 
pkt_comm_input_process_zeroes(struct pkt_comm * comm)479 int pkt_comm_input_process_zeroes(struct pkt_comm *comm)
480 {
481 	int count = 0;
482 	while (comm->input_buf[comm->input_buf_offset] == 0) {
483 		if (++comm->input_buf_offset >= comm->input_buf_len) {
484 			comm->input_buf_len = 0;
485 			return 0;
486 		}
487 		if (++count > 256) {
488 			pkt_error("pkt_comm_process_input_buf: too many padding 0's\n");
489 			return -1;
490 		}
491 	}
492 	return 0;
493 }
494 
495 // process packet header from input buffer
496 // including checksum after the header
497 //
pkt_comm_process_input_header(struct pkt_comm * comm)498 int pkt_comm_process_input_header(struct pkt_comm *comm)
499 {
500 	struct pkt *pkt = comm->input_pkt;
501 	unsigned char *buf = comm->input_buf;
502 	int offset = comm->input_buf_offset;
503 	//printf("process input header: off %d, input_pkt(y/n): %d\n", offset, !!pkt);
504 
505 	// nothing in input buffer
506 	if (!comm->input_buf_len)
507 		return 0;
508 
509 	// There's already input packet with partial header
510 	if (pkt && pkt->partial_header_len) {
511 		//printf("process input header: partial header len %d\n",pkt->partial_header_len);
512 
513 		// packet header is split over 3+ link layer transfers - should not happen
514 		if (offset + PKT_HEADER_LEN + PKT_CHECKSUM_LEN - pkt->partial_header_len
515 				> comm->input_buf_len) {
516 			pkt_error("pkt_comm_process_input_buf: splitted partial header, buf_len %d, off %d\n",
517 					comm->input_buf_len, offset);
518 			return -1;
519 		}
520 
521 		memcpy(pkt->header + pkt->partial_header_len, buf + offset,
522 				PKT_HEADER_LEN + PKT_CHECKSUM_LEN - pkt->partial_header_len);
523 		comm->input_buf_offset += PKT_HEADER_LEN + PKT_CHECKSUM_LEN - pkt->partial_header_len;
524 
525 		if (pkt_process_header(pkt, pkt->header) < 0)
526 			return -1;
527 		free(pkt->header);
528 		pkt->header = NULL;
529 		return 0;
530 	}
531 
532 	// Partial header of a new input packet
533 	if (offset + PKT_HEADER_LEN + PKT_CHECKSUM_LEN > comm->input_buf_len) {
534 		pkt->header = malloc(PKT_HEADER_LEN + PKT_CHECKSUM_LEN);
535 		if (!pkt->header) {
536 			pkt_error("pkt_comm_process_input_header: unable to allocate %d bytes\n",
537 				PKT_HEADER_LEN + PKT_CHECKSUM_LEN);
538 			return -1;
539 		}
540 		pkt->partial_header_len = comm->input_buf_len - offset;
541 		memcpy(pkt->header, buf + offset, pkt->partial_header_len);
542 		comm->input_buf_len = 0;
543 		//printf("partial header: off %d len %d\n", offset, pkt->partial_header_len);
544 		return 0;
545 	}
546 	// Full header of a new input packet
547 	else {
548 		if (pkt_process_header(pkt, buf + offset) < 0)
549 			return -1;
550 		comm->input_buf_offset += PKT_HEADER_LEN + PKT_CHECKSUM_LEN;
551 		if (comm->input_buf_offset == comm->input_buf_len)
552 			comm->input_buf_len = 0;
553 	}
554 
555 	return 0;
556 }
557 
558 // process packet data from input buffer
559 // including checksum
560 //
pkt_comm_process_input_packet_data(struct pkt_comm * comm)561 int pkt_comm_process_input_packet_data(struct pkt_comm *comm)
562 {
563 	struct pkt *pkt = comm->input_pkt;
564 	if (!pkt || !pkt->data_len) {
565 		pkt_error("pkt_comm_process_input_packet_data: bad input packet\n");
566 		return -1;
567 	}
568 
569 	// nothing in input buffer
570 	if (!comm->input_buf_len)
571 		return 0;
572 
573 	// no data in packet
574 	if (!pkt->data) {
575 		// allocate memory for packet data
576 		pkt->data = malloc(pkt->data_len + PKT_CHECKSUM_LEN);
577 		if (!pkt->data) {
578 			pkt_error("pkt_comm_process_input_packet_data: unable to allocate %d bytes\n",
579 				pkt->data_len + PKT_CHECKSUM_LEN);
580 			return -1;
581 		}
582 	}
583 	// ok, packet already has partial data
584 	else if (pkt->data && pkt->partial_data_len
585 			&& pkt->partial_data_len < pkt->data_len + PKT_CHECKSUM_LEN) {
586 		//printf("PARTIAL DATA: %d\n", pkt->partial_data_len);
587 	}
588 	else {
589 		pkt_error("pkt_comm_process_input_packet_data: bad partial packet\n");
590 		return -1;
591 	}
592 
593 	int offset = comm->input_buf_offset;
594 	int remains = pkt->data_len + PKT_CHECKSUM_LEN - pkt->partial_data_len ;
595 
596 	// packet completed
597 	if (remains <= comm->input_buf_len - offset) {
598 		memcpy(pkt->data + pkt->partial_data_len, comm->input_buf + offset, remains);
599 		pkt->partial_data_len = 0;
600 
601 		PKT_CHECKSUM_TYPE checksum = pkt_checksum(NULL, (unsigned char *)pkt->data, pkt->data_len);
602 		PKT_CHECKSUM_TYPE checksum_got = pkt_checksum_read((unsigned char *)pkt->data + pkt->data_len);
603 		if (checksum_got != checksum) {
604 			pkt_error("pkt_comm_process_input_packet_data: bad checksum: got 0x%x, must be 0x%x\n",
605 				checksum_got, checksum);
606 			return -1;
607 		}
608 
609 		// input buffer is empty
610 		if (remains == comm->input_buf_len - offset) {
611 			comm->input_buf_len = 0;
612 		}
613 		// input buffer is not empty
614 		else {
615 			comm->input_buf_offset += remains;
616 		}
617 	}
618 	// partial packet data, input buffer is empty
619 	else {
620 		memcpy(pkt->data + pkt->partial_data_len, comm->input_buf + offset,
621 				comm->input_buf_len - offset);
622 		pkt->partial_data_len += comm->input_buf_len - offset;
623 		comm->input_buf_len = 0;
624 	}
625 
626 	return 0;
627 }
628 
629 // Process input buffer, store full packets in input queue
630 // store partially received packet in comm->input_pkt
631 // return < 0 on error
632 //
pkt_comm_process_input_buf(struct pkt_comm * comm)633 int pkt_comm_process_input_buf(struct pkt_comm *comm)
634 {
635 	//printf("pkt_comm_process_input_buf: off %d\n", comm->input_buf_offset);
636 	struct pkt *pkt = comm->input_pkt;
637 
638 	//if (pkt) printf("process_input_buf: h_ok %d part_head %d data %d part_data %d\n",
639 	//	pkt->header_ok, pkt->partial_header_len, !!pkt->data, pkt->partial_data_len);
640 	//else printf("process_input_buf: no input_pkt\n");
641 	while(1) {
642 		// there's input packet with no header or partial header
643 		if (pkt && !pkt->header_ok) {
644 			if (pkt_comm_process_input_header(comm) < 0)
645 				return -1;
646 		}
647 
648 		// there's full header and no data or partial data
649 		if (pkt && pkt->header_ok && (!pkt->data || pkt->partial_data_len)) {
650 			if (pkt_comm_process_input_packet_data(comm) < 0)
651 				return -1;
652 		}
653 
654 		// there's already a complete input packet
655 		if (pkt && pkt->header_ok && pkt->data && !pkt->partial_data_len) {
656 			//printf("pkt_comm_process_input_buf: header_ok:%d data:%d partial_data_len:%d\n",
657 			//	!!pkt->header_ok, !!pkt->data, pkt->partial_data_len);
658 			if (pkt_queue_full(comm->input_queue, 1))
659 				return 0;
660 			// push packet into input queue
661 			pkt_queue_push(comm->input_queue, pkt);
662 			comm->input_pkt = NULL;
663 		}
664 
665 		// input buffer is empty - finish processing
666 		if (!comm->input_buf_len)
667 			return 0;
668 
669 		// skip padding zeroes
670 		/*
671 		 * OK - the device creates aligned packets only
672 		 *
673 		if (pkt_comm_input_process_zeroes(comm) < 0)
674 			return -1;
675 		if (!comm->input_buf_len)
676 			return 0;
677 		*/
678 
679 		// expecting new input packet
680 		pkt = pkt_new(0, NULL, 0);
681 		comm->input_pkt = pkt;
682 
683 	} // while(1) - process incoming packets
684 }
685 
pkt_comm_input_get_buf(struct pkt_comm * comm)686 unsigned char *pkt_comm_input_get_buf(struct pkt_comm *comm)
687 {
688 	// input queue full
689 	if (pkt_queue_full(comm->input_queue, 1))
690 		return NULL;
691 
692 	// input buffer not empty
693 	// that's probably because input queue was full
694 	// at time of processing
695 	if (comm->input_buf_len) {
696 		// try to process and empty it
697 		if (pkt_comm_process_input_buf(comm) < 0) {
698 			comm->error = 1;
699 			return NULL;
700 		}
701 
702 		// still not empty
703 		if (comm->input_buf_len)
704 			return NULL;
705 	}
706 
707 	comm->input_buf_offset = 0;
708 	return comm->input_buf;
709 }
710 
pkt_comm_input_completed(struct pkt_comm * comm,int len,int error)711 int pkt_comm_input_completed(struct pkt_comm *comm, int len, int error)
712 {
713 	//printf("input_completed %d %d\n", len, error);
714 	comm->error = error;
715 	if (error)
716 		return -1;
717 
718 	if (!len)
719 		return -1;
720 	if (len > comm->params->input_max_len) {
721 		pkt_error("pkt_comm_input_completed: len %d exceeds input_max_len(%d)\n",
722 				len, comm->params->input_max_len);
723 		return -1;
724 	}
725 	comm->input_buf_len = len;
726 
727 	if (pkt_comm_process_input_buf(comm) < 0) {
728 		comm->error = 1;
729 		return -1;
730 	}
731 	return 0;
732 }
733 
734