mirror of https://gerrit.osmocom.org/libtelnet
get libtelnet compiling; more buffer work
This commit is contained in:
parent
fddf1c4731
commit
4d9444d028
89
libtelnet.c
89
libtelnet.c
|
@ -6,11 +6,23 @@
|
||||||
* all present and future rights to this code under copyright law.
|
* all present and future rights to this code under copyright law.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
#include "libtelnet.h"
|
#include "libtelnet.h"
|
||||||
|
|
||||||
|
/* buffer sizes */
|
||||||
|
static const unsigned int _buffer_sizes[] = {
|
||||||
|
0,
|
||||||
|
512,
|
||||||
|
2048,
|
||||||
|
8192,
|
||||||
|
16384,
|
||||||
|
};
|
||||||
|
static const unsigned int _buffer_sizes_count =
|
||||||
|
sizeof(_buffer_sizes) / sizeof(_buffer_sizes[0]);
|
||||||
|
|
||||||
/* initialize a telnet state tracker */
|
/* initialize a telnet state tracker */
|
||||||
void libtelnet_init(struct libtelnet_t *telnet) {
|
void libtelnet_init(struct libtelnet_t *telnet) {
|
||||||
telnet->state = LIBTELNET_TEXT;
|
telnet->state = LIBTELNET_STATE_TEXT;
|
||||||
telnet->buffer = 0;
|
telnet->buffer = 0;
|
||||||
telnet->size = 0;
|
telnet->size = 0;
|
||||||
telnet->length = 0;
|
telnet->length = 0;
|
||||||
|
@ -27,43 +39,38 @@ void libtelnet_free(struct libtelnet_t *telnet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a byte into the telnet buffer */
|
/* push a byte into the telnet buffer */
|
||||||
static enum libtelnet_error_t _libtelnet_buffer_byte(
|
static enum libtelnet_error_t _buffer_byte(
|
||||||
struct libtelnet_t *telnet, unsigned char byte, void *user_data) {
|
struct libtelnet_t *telnet, unsigned char byte, void *user_data) {
|
||||||
|
unsigned char *new_buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* check if we're out of room */
|
/* check if we're out of room */
|
||||||
if (telnet->length == telnet->size) {
|
if (telnet->length == telnet->size) {
|
||||||
/* if we already have a large buffer, we're out of space, give up */
|
/* find the next buffer size */
|
||||||
if (telnet->size == LIBTELNET_BUFFER_SIZE_LARGE) {
|
for (i = 0; i != _buffer_sizes_count; ++i) {
|
||||||
|
if (_buffer_sizes[i] == telnet->size)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* overflow -- can't grow any more */
|
||||||
|
if (i >= _buffer_sizes_count - 1) {
|
||||||
libtelnet_error_cb(telnet, LIBTELNET_ERROR_OVERFLOW, user_data);
|
libtelnet_error_cb(telnet, LIBTELNET_ERROR_OVERFLOW, user_data);
|
||||||
libtelnet_free(telnet);
|
libtelnet_free(telnet);
|
||||||
return LIBTELNET_ERROR_OVERFLOW;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (re)allocate buffer */
|
||||||
|
new_buffer = (unsigned char *)realloc(telnet->buffer,
|
||||||
|
_buffer_sizes[i + 1]);
|
||||||
|
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 = _buffer_sizes[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push the byte, all set */
|
/* push the byte, all set */
|
||||||
|
@ -82,7 +89,7 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||||
telnet->state = LIBTELNET_STATE_IAC;
|
telnet->state = LIBTELNET_STATE_IAC;
|
||||||
/* regular input byte */
|
/* regular input byte */
|
||||||
else
|
else
|
||||||
libtelnet_input_cb(telnet, byte, user_data);
|
libtelnet_input_cb(telnet, &byte, 1, user_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* IAC command */
|
/* IAC command */
|
||||||
|
@ -107,8 +114,8 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||||
break;
|
break;
|
||||||
/* IAC escaping */
|
/* IAC escaping */
|
||||||
case LIBTELNET_IAC:
|
case LIBTELNET_IAC:
|
||||||
telbet->input_cb(telnet, LIBTELNET_IAC, user_data);
|
libtelnet_input_cb(telnet, &byte, 1, user_data);
|
||||||
libtelnet->state = LIBTELNET_STATE_TEXT;
|
telnet->state = LIBTELNET_STATE_TEXT;
|
||||||
break;
|
break;
|
||||||
/* some other command */
|
/* some other command */
|
||||||
default:
|
default:
|
||||||
|
@ -141,7 +148,7 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||||
if (byte == LIBTELNET_IAC)
|
if (byte == LIBTELNET_IAC)
|
||||||
telnet->state = LIBTELNET_STATE_SB_IAC;
|
telnet->state = LIBTELNET_STATE_SB_IAC;
|
||||||
/* buffer the byte, or bail if we can't */
|
/* buffer the byte, or bail if we can't */
|
||||||
else if (_libtelnet_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
else if (_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
||||||
LIBTELNET_ERROR_OK)
|
LIBTELNET_ERROR_OK)
|
||||||
telnet->state = LIBTELNET_STATE_TEXT;
|
telnet->state = LIBTELNET_STATE_TEXT;
|
||||||
else
|
else
|
||||||
|
@ -170,7 +177,7 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||||
/* escaped IAC byte */
|
/* escaped IAC byte */
|
||||||
case LIBTELNET_IAC:
|
case LIBTELNET_IAC:
|
||||||
/* push IAC into buffer */
|
/* push IAC into buffer */
|
||||||
if (_libtelnet_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
if (_buffer_byte(telnet, LIBTELNET_IAC, user_data) !=
|
||||||
LIBTELNET_ERROR_OK)
|
LIBTELNET_ERROR_OK)
|
||||||
telnet->state = LIBTELNET_STATE_TEXT;
|
telnet->state = LIBTELNET_STATE_TEXT;
|
||||||
else
|
else
|
||||||
|
@ -188,8 +195,8 @@ void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
||||||
|
|
||||||
/* push a byte buffer into the state tracker */
|
/* push a byte buffer into the state tracker */
|
||||||
void libtelnet_push_buffer(struct libtelnet_t *telnet, unsigned char *buffer,
|
void libtelnet_push_buffer(struct libtelnet_t *telnet, unsigned char *buffer,
|
||||||
size_t size, void *user_data) {
|
unsigned int size, void *user_data) {
|
||||||
size_t i;
|
unsigned int i;
|
||||||
for (i = 0; i != size; ++i)
|
for (i = 0; i != size; ++i)
|
||||||
libtelnet_push_byte(telnet, buffer[i], user_data);
|
libtelnet_push_byte(telnet, buffer[i], user_data);
|
||||||
}
|
}
|
||||||
|
@ -210,8 +217,8 @@ void libtelnet_send_negotiate(struct libtelnet_t *telnet, unsigned char cmd,
|
||||||
|
|
||||||
/* send non-command data (escapes IAC bytes) */
|
/* send non-command data (escapes IAC bytes) */
|
||||||
void libtelnet_send_data(struct libtelnet_t *telnet, unsigned char *buffer,
|
void libtelnet_send_data(struct libtelnet_t *telnet, unsigned char *buffer,
|
||||||
size_t size, void *user_data) {
|
unsigned int size, void *user_data) {
|
||||||
size_t i, l;
|
unsigned int i, l;
|
||||||
for (l = i = 0; i != size; ++i) {
|
for (l = i = 0; i != size; ++i) {
|
||||||
/* dump prior portion of text, send escaped bytes */
|
/* dump prior portion of text, send escaped bytes */
|
||||||
if (buffer[i] == LIBTELNET_IAC) {
|
if (buffer[i] == LIBTELNET_IAC) {
|
||||||
|
@ -232,7 +239,7 @@ void libtelnet_send_data(struct libtelnet_t *telnet, unsigned char *buffer,
|
||||||
|
|
||||||
/* send sub-request */
|
/* send sub-request */
|
||||||
void libtelnet_send_subrequest(struct libtelnet_t *telnet, unsigned char type,
|
void libtelnet_send_subrequest(struct libtelnet_t *telnet, unsigned char type,
|
||||||
unsigned char *buffer, size_t size, void *user_data) {
|
unsigned char *buffer, unsigned int size, void *user_data) {
|
||||||
libtelnet_send_command(telnet, LIBTELNET_SB, user_data);
|
libtelnet_send_command(telnet, LIBTELNET_SB, user_data);
|
||||||
libtelnet_send_data(telnet, &type, 1, user_data);
|
libtelnet_send_data(telnet, &type, 1, user_data);
|
||||||
libtelnet_send_data(telnet, buffer, size, user_data);
|
libtelnet_send_data(telnet, buffer, size, user_data);
|
||||||
|
|
64
libtelnet.h
64
libtelnet.h
|
@ -9,11 +9,6 @@
|
||||||
#if !defined(LIBTELNET_INCLUDE)
|
#if !defined(LIBTELNET_INCLUDE)
|
||||||
#define LIBTELNET 1
|
#define LIBTELNET 1
|
||||||
|
|
||||||
/* 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 */
|
/* telnet special values */
|
||||||
#define LIBTELNET_IAC 255
|
#define LIBTELNET_IAC 255
|
||||||
#define LIBTELNET_DONT 254
|
#define LIBTELNET_DONT 254
|
||||||
|
@ -50,34 +45,34 @@ enum libtelnet_error_t {
|
||||||
LIBTELNET_ERROR_UNKNOWN, /* some crazy unexplainable unknown error */
|
LIBTELNET_ERROR_UNKNOWN, /* some crazy unexplainable unknown error */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* state tracker */
|
||||||
|
struct libtelnet_t {
|
||||||
|
/* sub-request buffer */
|
||||||
|
unsigned char *buffer;
|
||||||
|
/* current size of the buffer */
|
||||||
|
unsigned int size;
|
||||||
|
/* length of data in the buffer */
|
||||||
|
unsigned int length;
|
||||||
|
/* current state */
|
||||||
|
enum libtelnet_state_t state;
|
||||||
|
};
|
||||||
|
|
||||||
/* libtelnet callback declarations
|
/* libtelnet callback declarations
|
||||||
* APPLICATION MUST IMPLEMENT THESE FUNCTIONS!!
|
* APPLICATION MUST IMPLEMENT THESE FUNCTIONS!!
|
||||||
*/
|
*/
|
||||||
extern void libtelnet_input_cb(struct libtelnet_t *telnet, unsigned char
|
extern void libtelnet_input_cb(struct libtelnet_t *telnet,
|
||||||
byte, void *user_data);
|
unsigned char *buffer, unsigned int size, void *user_data);
|
||||||
extern void libtelnet_output_cb(struct libtelnet_t *telnet, unsigned char
|
extern void libtelnet_output_cb(struct libtelnet_t *telnet,
|
||||||
byte, void *user_data);
|
unsigned char *buffer, unsigned int size, void *user_data);
|
||||||
extern void libtelnet_command_cb(struct libtelnet_t *telnet, unsigned char
|
extern void libtelnet_command_cb(struct libtelnet_t *telnet,
|
||||||
cmd, void *user_data);
|
unsigned char cmd, void *user_data);
|
||||||
extern void libtelnet_negotiate_cb(struct libtelnet_t *telnet, unsigned char
|
extern void libtelnet_negotiate_cb(struct libtelnet_t *telnet,
|
||||||
cmd, unsigned char opt, void *user_data);
|
unsigned char cmd, unsigned char opt, void *user_data);
|
||||||
extern void libtelnet_subrequest_cb(struct libtelnet_t *telnet, unsigned char
|
extern void libtelnet_subrequest_cb(struct libtelnet_t *telnet,
|
||||||
cmd, unsigned char type, unsigned char *data, size_t size,
|
unsigned char type, unsigned char *data, unsigned int size,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
extern void libtelnet_error_cb(struct libtelnet_t *telnet,
|
extern void libtelnet_error_cb(struct libtelnet_t *telnet,
|
||||||
enum libtelnet_error_t error, void *user_data);
|
enum libtelnet_error_t error, void *user_data);
|
||||||
|
|
||||||
/* state tracker */
|
|
||||||
struct libtelnet_t {
|
|
||||||
/* current state */
|
|
||||||
enum libtelnet_state_t state;
|
|
||||||
/* sub-request buffer */
|
|
||||||
char *buffer;
|
|
||||||
/* current size of the buffer */
|
|
||||||
size_t size;
|
|
||||||
/* length of data in the buffer */
|
|
||||||
size_t length;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* initialize a telnet state tracker */
|
/* initialize a telnet state tracker */
|
||||||
extern void libtelnet_init(struct libtelnet_t *telnet);
|
extern void libtelnet_init(struct libtelnet_t *telnet);
|
||||||
|
@ -86,12 +81,12 @@ extern void libtelnet_init(struct libtelnet_t *telnet);
|
||||||
extern void libtelnet_free(struct libtelnet_t *telnet);
|
extern void libtelnet_free(struct libtelnet_t *telnet);
|
||||||
|
|
||||||
/* push a single byte into the state tracker */
|
/* push a single byte into the state tracker */
|
||||||
extern void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
|
extern void libtelnet_push_byte(struct libtelnet_t *telnet,
|
||||||
void *user_data);
|
unsigned char byte, void *user_data);
|
||||||
|
|
||||||
/* push a byte buffer into the state tracker */
|
/* push a byte buffer into the state tracker */
|
||||||
extern void libtelnet_push_buffer(struct libtelnet_t *telnet,
|
extern void libtelnet_push_buffer(struct libtelnet_t *telnet,
|
||||||
unsigned char *buffer, size_t size, void *user_data);
|
unsigned char *buffer, unsigned int size, void *user_data);
|
||||||
|
|
||||||
/* send an iac command */
|
/* send an iac command */
|
||||||
extern void libtelnet_send_command(struct libtelnet_t *telnet,
|
extern void libtelnet_send_command(struct libtelnet_t *telnet,
|
||||||
|
@ -103,10 +98,11 @@ extern void libtelnet_send_negotiate(struct libtelnet_t *telnet,
|
||||||
|
|
||||||
/* send non-command data (escapes IAC bytes) */
|
/* send non-command data (escapes IAC bytes) */
|
||||||
extern void libtelnet_send_data(struct libtelnet_t *telnet,
|
extern void libtelnet_send_data(struct libtelnet_t *telnet,
|
||||||
unsigned char *buffer, size_t size, void *user_data);
|
unsigned char *buffer, unsigned int size, void *user_data);
|
||||||
|
|
||||||
/* send sub-request */
|
/* send sub-request */
|
||||||
extern void libtelnet_send_subrequest(struct libtelnet_t *telnet,
|
extern void libtelnet_send_subrequest(struct libtelnet_t *telnet,
|
||||||
unsigned char type, unsigned char *buffer, size_t size, void *user_data);
|
unsigned char type, unsigned char *buffer, unsigned int size,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
#endif /* !defined(LIBTELNET_INCLUDE) */
|
#endif /* !defined(LIBTELNET_INCLUDE) */
|
||||||
|
|
Loading…
Reference in New Issue