libslip-c

C SLIP-encoding library
git clone https://git.sinitax.com/sinitax/libslip-c
Log | Files | Refs | LICENSE | sfeed.txt

slip.c (3551B)


      1#include "slip.h"
      2
      3#include <errno.h>
      4
      5enum {
      6	SLIPDEC_START_STATE,
      7	SLIPDEC_IN_FRAME_STATE,
      8	SLIPDEC_ESC_STATE
      9};
     10
     11static int slip_decode_start(struct slip *slip, uint8_t rx_byte);
     12static int slip_decode_inframe(struct slip *slip, uint8_t rx_byte);
     13static int slip_decode_escseq(struct slip *slip, uint8_t rx_byte);
     14
     15static inline void
     16store(uint8_t **cur, uint8_t *end, uint8_t byte)
     17{
     18	if (*cur < end) *(*cur)++ = byte;
     19}
     20
     21int
     22slip_decode_start(struct slip *slip, uint8_t rx_byte)
     23{
     24	/* wait for packet start */
     25	if (rx_byte == slip->start) {
     26		slip->rx_index = 0;
     27		slip->rx_state = SLIPDEC_IN_FRAME_STATE;
     28	}
     29
     30	return 0;
     31}
     32
     33int
     34slip_decode_inframe(struct slip *slip, uint8_t rx_byte)
     35{
     36	int rc;
     37
     38	if (rx_byte == slip->end) {
     39		/* end of packet */
     40		slip->rx_packet(slip, slip->rx_buf, slip->rx_index,
     41				slip->rx_packet_userdata);
     42		slip->rx_state = SLIPDEC_START_STATE;
     43	} else if (rx_byte == slip->start) {
     44		/* malformed packet */
     45		if (slip->rx_restart)
     46			slip->rx_restart(slip, rx_byte);
     47		slip->rx_index = 0;
     48		slip->rx_state = SLIPDEC_START_STATE;
     49	} else if (rx_byte == slip->esc) {
     50		/* escape sequence */
     51		slip->rx_state = SLIPDEC_ESC_STATE;
     52	} else {
     53		/* data byte */
     54		rc = slip_decode_store(slip, rx_byte);
     55		if (rc) return rc;
     56	}
     57
     58	return 0;
     59}
     60
     61int
     62slip_decode_escseq(struct slip *slip, uint8_t rx_byte)
     63{
     64	uint8_t dec;
     65	int rc;
     66
     67	dec = slip->esc_dec[rx_byte];
     68	if (slip->esc_active[dec]) {
     69		rc = slip_decode_store(slip, dec);
     70		if (rc) return rc;
     71		slip->rx_state = SLIPDEC_IN_FRAME_STATE;
     72	} else {
     73		/* invalid contents */
     74		if (slip->rx_restart)
     75			slip->rx_restart(slip, rx_byte);
     76		slip->rx_state = SLIPDEC_START_STATE;
     77		slip->rx_index = 0;
     78	}
     79
     80	return 0;
     81}
     82
     83int
     84slip_init(struct slip *slip)
     85{
     86	int i;
     87
     88	slip->rx_state = SLIPDEC_START_STATE;
     89
     90	slip->rx_index = 0;
     91	slip->rx_buflen = 0;
     92	slip->rx_buf = NULL;
     93
     94	if (!slip->rx_packet) return -EINVAL;
     95	if (!slip->realloc) return -EINVAL;
     96	if (slip->esc == slip->start) return -EINVAL;
     97	if (slip->esc == slip->end) return -EINVAL;
     98
     99	/* build decode table */
    100	for (i = 0; i < 256; i++)
    101		slip->esc_dec[slip->esc_enc[i]] = (uint8_t) i;
    102
    103	return 0;
    104}
    105
    106void
    107slip_deinit(struct slip *slip)
    108{
    109	free(slip->rx_buf);
    110}
    111
    112int
    113slip_decode_store(struct slip *slip, uint8_t byte)
    114{
    115	int rc;
    116
    117	if (slip->rx_index >= slip->rx_buflen) {
    118		if (!slip->rx_buflen)
    119			slip->rx_buflen = 256;
    120		else
    121			slip->rx_buflen *= 2;
    122		rc = slip->realloc((void **)&slip->rx_buf, slip->rx_buflen);
    123		if (rc) return rc;
    124	}
    125	slip->rx_buf[slip->rx_index++] = byte;
    126
    127	return 0;
    128}
    129
    130int
    131slip_decode(struct slip *slip, uint8_t* data, size_t size)
    132{
    133	uint8_t rx_byte;
    134	size_t i;
    135	int rc;
    136
    137	for (i = 0; i < size; i++) {
    138		rx_byte = data[i];
    139		switch (slip->rx_state) {
    140		case SLIPDEC_START_STATE:
    141			rc = slip_decode_start(slip, rx_byte);
    142			break;
    143		case SLIPDEC_IN_FRAME_STATE:
    144			rc = slip_decode_inframe(slip, rx_byte);
    145			break;
    146		case SLIPDEC_ESC_STATE:
    147			rc = slip_decode_escseq(slip, rx_byte);
    148			break;
    149		default:
    150			rc = -EINVAL;
    151			break;
    152		}
    153		if (rc) return rc;
    154	}
    155
    156	return 0;
    157}
    158
    159int
    160slip_encode(struct slip *slip, uint8_t* out, size_t *outlen, size_t outcap,
    161	uint8_t* in, size_t inlen)
    162{
    163	uint8_t *pos, *end;
    164	size_t i;
    165
    166	pos = out;
    167	end = out + outcap;
    168
    169	store(&pos, end, slip->start);
    170
    171	for (i = 0; i < inlen && pos < end; i++) {
    172		if (slip->esc_active[in[i]]) {
    173			store(&pos, end, slip->esc);
    174			store(&pos, end, slip->esc_enc[in[i]]);
    175		} else {
    176			store(&pos, end, in[i]);
    177		}
    178	}
    179
    180	store(&pos, end, slip->end);
    181
    182	if (pos >= end) return -ENOBUFS;
    183
    184	*outlen = (size_t) (pos - out);
    185
    186	return 0;
    187}