mirror of https://gerrit.osmocom.org/libtelnet
work on buffer handling
This commit is contained in:
parent
b9e4864539
commit
51ad679e47
83
libtelnet.c
83
libtelnet.c
|
@ -9,28 +9,68 @@
|
|||
#include "libtelnet.h"
|
||||
|
||||
/* initialize a telnet state tracker */
|
||||
libtelnet_error_t libtelnet_init(struct libtelnet_t *telnet) {
|
||||
void libtelnet_init(struct libtelnet_t *telnet) {
|
||||
telnet->state = LIBTELNET_TEXT;
|
||||
telnet->buffer = 0;
|
||||
telnet->size = 0;
|
||||
telnet->length = 0;
|
||||
|
||||
/* attempt to allocate default buffer */
|
||||
telnet->buffer = (unsigned char *)malloc(LIBTELNET_BUFFER_SIZE);
|
||||
if (telnet->buffer == 0)
|
||||
return LIBTELNET_ERROR_NOMEM;
|
||||
|
||||
return LIBTELNET_ERROR_OK;
|
||||
}
|
||||
|
||||
/* free up any memory allocated by a state tracker */
|
||||
void libtelnet_close(struct libtelnet_t *telnet) {
|
||||
if (telnet->buffer) {
|
||||
void libtelnet_free(struct libtelnet_t *telnet) {
|
||||
if (telnet->buffer != 0) {
|
||||
free(telnet->buffer);
|
||||
telnet->buffer = 0;
|
||||
telnet->size = 0;
|
||||
telnet->length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* push a byte into the telnet buffer */
|
||||
static enum libtelnet_error_t _libtelnet_buffer_byte(
|
||||
struct libtelnet_t *telnet, unsigned char byte, void *user_data) {
|
||||
/* check if we're out of room */
|
||||
if (telnet->length == telnet->size) {
|
||||
/* if we already have a large buffer, we're out of space, give up */
|
||||
if (telnet->size == LIBTELNET_BUFFER_SIZE_LARGE) {
|
||||
libtelnet_error_cb(telnet, LIBTELNET_ERROR_OVERFLOW, user_data);
|
||||
libtelnet_free(telnet);
|
||||
return LIBTELNET_ERROR_OVERFLOW;
|
||||
|
||||
/* if we have a small buffer, try to resize to a larger one */
|
||||
} else if (telnet->size == LIBTELNET_BUFFER_SIZE_SMALL) {
|
||||
unsigned char *new_buffer = (unsigned char *)realloc(
|
||||
telnet->buffer, LIBTELNET_BUFFER_SIZE_LARGE);
|
||||
if (new_buffer == 0) {
|
||||
libtelnet_error_cb(telnet, LIBTELNET_ERROR_NOMEM,
|
||||
user_data);
|
||||
libtelnet_free(telnet);
|
||||
return LIBTELNET_ERROR_NOMEM;
|
||||
}
|
||||
|
||||
telnet->buffer = new_buffer;
|
||||
telnet->size = LIBTELNET_BUFFER_SIZE_LARGE;
|
||||
|
||||
/* we have no buffer at all, so allocate one */
|
||||
} else {
|
||||
telnet->buffer = (unsigned char *)realloc(
|
||||
telnet->buffer, LIBTELNET_BUFFER_SIZE_SMALL);
|
||||
if (telnet->buffer == 0) {
|
||||
libtelnet_error_cb(telnet, LIBTELNET_ERROR_NOMEM,
|
||||
user_data);
|
||||
libtelnet_free(telnet);
|
||||
return LIBTELNET_ERROR_NOMEM;
|
||||
}
|
||||
|
||||
telnet->size = LIBTELNET_BUFFER_SIZE_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
/* push the byte, all set */
|
||||
telnet->buffer[telnet->length++] = byte;
|
||||
return LIBTELNET_ERROR_OK;
|
||||
}
|
||||
|
||||
/* push a single byte into the state tracker */
|
||||
void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||
void *user_data) {
|
||||
|
@ -94,11 +134,14 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
|||
/* subrequest -- buffer bytes until end request */
|
||||
case LIBTELNET_STATE_SB:
|
||||
/* IAC command in subrequest -- either IAC SE or IAC IAC */
|
||||
if (byte == LIBTELNET_IAC) {
|
||||
if (byte == LIBTELNET_IAC)
|
||||
telnet->state = LIBTELNET_STATE_SB_IAC;
|
||||
} else {
|
||||
/* FIXME: buffer byte */
|
||||
}
|
||||
/* buffer the byte, or bail if we can't */
|
||||
else if (_libtelnet_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
||||
LIBTELNET_ERROR_OK)
|
||||
telnet->state = LIBTELNET_STATE_TEXT;
|
||||
else
|
||||
telnet->state = LIBTELNET_STATE_SB;
|
||||
break;
|
||||
/* IAC escaping inside a subrequest */
|
||||
case LIBTELNET_STATE_SB_IAC:
|
||||
|
@ -113,10 +156,6 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
|||
} else {
|
||||
libtelnet_subrequest_cb(telnet, telnet->buffer[0],
|
||||
telnet->buffer + 1, telnet->length - 1, user_data);
|
||||
|
||||
/* unallocate free buffer */
|
||||
free(telnet->buffer);
|
||||
telnet->size = 0;
|
||||
telnet->length = 0;
|
||||
}
|
||||
|
||||
|
@ -125,8 +164,12 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
|||
break;
|
||||
/* escaped IAC byte */
|
||||
case LIBTELNET_IAC:
|
||||
/* FIXME: buffer byte */
|
||||
telnet->state = LIBTELNET_STATE_SB;
|
||||
/* push IAC into buffer */
|
||||
if (_libtelnet_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
||||
LIBTELNET_ERROR_OK)
|
||||
telnet->state = LIBTELNET_STATE_TEXT;
|
||||
else
|
||||
telnet->state = LIBTELNET_STATE_SB;
|
||||
break;
|
||||
/* something else -- protocol error */
|
||||
default:
|
||||
|
|
10
libtelnet.h
10
libtelnet.h
|
@ -9,10 +9,10 @@
|
|||
#if !defined(LIBTELNET_INCLUDE)
|
||||
#define LIBTELNET 1
|
||||
|
||||
/* sub request buffer size increment (defualt 4K) */
|
||||
#define LIBTELNET_BUFFER_SIZE (4 * 1024)
|
||||
/* sub request buffer size (default 16K) */
|
||||
#define LIBTELNET_BUFFER_SIZE_MAX (16 * 1024)
|
||||
/* sub request buffer size, normal (defualt 1K) */
|
||||
#define LIBTELNET_BUFFER_SIZE_SMALL (1 * 1024)
|
||||
/* sub request buffer size, enlarged (default 16K) */
|
||||
#define LIBTELNET_BUFFER_SIZE_LARGE (16 * 1024)
|
||||
|
||||
/* telnet special values */
|
||||
#define LIBTELNET_IAC 255
|
||||
|
@ -83,7 +83,7 @@ struct libtelnet_t {
|
|||
extern void libtelnet_init(struct libtelnet_t *telnet);
|
||||
|
||||
/* free up any memory allocated by a state tracker */
|
||||
extern void libtelnet_close(struct libtelnet_t *telnet);
|
||||
extern void libtelnet_free(struct libtelnet_t *telnet);
|
||||
|
||||
/* push a single byte into the state tracker */
|
||||
extern void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||
|
|
Loading…
Reference in New Issue