remove per-tracker callbacks, just use functions user must implement
diff --git a/libtelnet.c b/libtelnet.c
index b148d8e..f55b59a 100644
--- a/libtelnet.c
+++ b/libtelnet.c
@@ -1,11 +1,18 @@
#include "libtelnet.h"
/* initialize a telnet state tracker */
-void libtelnet_init(struct libtelnet_t *telnet) {
+libtelnet_error_t 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 */
@@ -27,7 +34,7 @@
telnet->state = LIBTELNET_STATE_IAC;
/* regular input byte */
else
- telnet->input_cb(telnet, byte, user_data);
+ libtelnet_input_cb(telnet, byte, user_data);
break;
case LIBTELNET_STATE_IAC:
switch (byte) {
@@ -55,25 +62,25 @@
break;
/* some other command */
default:
- telnet->command_cb(telnet, byte, user_data);
+ libtelnet_command_cb(telnet, byte, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
}
break;
/* DO negotiation */
case LIBTELNET_STATE_DO:
- telnet->negotiate_cb(telnet, LIBTELNET_DO, byte, user_data);
+ libtelnet_negotiate_cb(telnet, LIBTELNET_DO, byte, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
break;
case LIBTELNET_STATE_DONT:
- telnet->negotiate_cb(telnet, LIBTELNET_DONT, byte, user_data);
+ libtelnet_negotiate_cb(telnet, LIBTELNET_DONT, byte, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
break;
case LIBTELNET_STATE_WILL:
- telnet->negotiate_cb(telnet, LIBTELNET_WILL, byte, user_data);
+ libtelnet_negotiate_cb(telnet, LIBTELNET_WILL, byte, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
break;
case LIBTELNET_STATE_WONT:
- telnet->negotiate_cb(telnet, LIBTELNET_WONT, byte, user_data);
+ libtelnet_negotiate_cb(telnet, LIBTELNET_WONT, byte, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
break;
/* subrequest -- buffer bytes until end request */
@@ -90,7 +97,22 @@
switch (byte) {
/* end subrequest */
case LIBTELNET_SE:
- /* FIXME: process */
+ /* zero-size buffer is a protocol error */
+ if (telnet->length == 0) {
+ libtelnet_error_cb(telnet, LIBTELNET_ERROR_PROTOCOL,
+ user_data);
+ /* process */
+ } 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;
+ }
+
+ /* return to default state */
telnet->state = LIBTELNET_STATE_TEXT;
break;
/* escaped IAC byte */
@@ -100,7 +122,7 @@
break;
/* something else -- protocol error */
default:
- telnet->error_cb(telnet, LIBTELNET_ERROR_PROTOCOL, user_data);
+ libtelnet_error_cb(telnet, LIBTELNET_ERROR_PROTOCOL, user_data);
telnet->state = LIBTELNET_STATE_TEXT;
break;
}
@@ -120,14 +142,14 @@
void libtelnet_send_command(struct libtelnet_t *telnet, unsigned char cmd,
void *user_data) {
unsigned char bytes[2] = { IAC, cmd };
- telnet->output_cb(telnet, bytes, 2, user_data);
+ libtelnet_output_cb(telnet, bytes, 2, user_data);
}
/* send negotiation */
void libtelnet_send_negotiate(struct libtelnet_t *telnet, unsigned char cmd,
unsigned char opt, void *user_data) {
unsigned char bytes[3] = { IAC, cmd, opt };
- telnet->output_cb(telnet, bytes, 3, user_data);
+ libtelnet_output_cb(telnet, bytes, 3, user_data);
}
/* send non-command data (escapes IAC bytes) */
@@ -139,7 +161,7 @@
if (buffer[i] == LIBTELNET_IAC) {
/* dump prior text if any */
if (i != l)
- telnet->output_cb(telnet, buffer + l, i - l, user_data);
+ libtelnet_output_cb(telnet, buffer + l, i - l, user_data);
l = i + 1;
/* send escape */
@@ -149,7 +171,7 @@
/* send whatever portion of buffer is left */
if (i != l)
- telnet->output_cb(telnet, buffer + l, i - l, user_data);
+ libtelnet_output_cb(telnet, buffer + l, i - l, user_data);
}
/* send sub-request */
diff --git a/libtelnet.h b/libtelnet.h
index a3cba24..e518601 100644
--- a/libtelnet.h
+++ b/libtelnet.h
@@ -41,24 +41,27 @@
/* error codes */
enum libtelnet_error_t {
LIBTELNET_ERROR_OK = 0,
+ LIBTELNET_ERROR_NOMEM, /* memory allocation failure */
LIBTELNET_ERROR_OVERFLOW, /* input exceeds buffer size */
LIBTELNET_ERROR_PROTOCOL, /* invalid sequence of special bytes */
LIBTELNET_ERROR_UNKNOWN, /* some crazy unexplainable unknown error */
};
-/* callback prototypes */
-typedef (void)(*libtelnet_input)(struct libtelnet_t *telnet, unsigned char
+/* libtelnet callback declarations
+ * APPLICATION MUST IMPLEMENT THESE FUNCTIONS!!
+ */
+extern void libtelnet_input_cb(struct libtelnet_t *telnet, unsigned char
byte, void *user_data);
-typedef (void)(*libtelnet_output)(struct libtelnet_t *telnet, unsigned char
+extern void libtelnet_output_cb(struct libtelnet_t *telnet, unsigned char
byte, void *user_data);
-typedef (void)(*libtelnet_command)(struct libtelnet_t *telnet, unsigned char
+extern void libtelnet_command_cb(struct libtelnet_t *telnet, unsigned char
cmd, void *user_data);
-typedef (void)(*libtelnet_negotiate)(struct libtelnet_t *telnet, unsigned char
+extern void libtelnet_negotiate_cb(struct libtelnet_t *telnet, unsigned char
cmd, unsigned char opt, void *user_data);
-typedef (void)(*libtelnet_subrequest)(struct libtelnet_t *telnet, unsigned char
+extern void libtelnet_subrequest_cb(struct libtelnet_t *telnet, unsigned char
cmd, unsigned char type, unsigned char *data, size_t size,
void *user_data);
-typedef (void)(*libtelnet_error)(struct libtelnet_t *telnet,
+extern void libtelnet_error_cb(struct libtelnet_t *telnet,
enum libtelnet_error_t error, void *user_data);
/* state tracker */
@@ -71,41 +74,34 @@
size_t size;
/* length of data in the buffer */
size_t length;
-
- /* callbacks */
- libtelnet_input input_cb;
- libtelnet_output output_cb;
- libtelnet_command command_cb;
- libtelnet_negotiate negotiate_cb;
- libtelnet_subrequest subrequest_cb;
};
/* initialize a telnet state tracker */
-void libtelnet_init(struct libtelnet_t *telnet);
+extern void libtelnet_init(struct libtelnet_t *telnet);
/* free up any memory allocated by a state tracker */
-void libtelnet_close(struct libtelnet_t *telnet);
+extern void libtelnet_close(struct libtelnet_t *telnet);
/* push a single byte into the state tracker */
-void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
+extern void libtelnet_push_byte(struct libtelnet_t *telnet, unsigned char byte,
void *user_data);
/* push a byte buffer into the state tracker */
-void libtelnet_push_buffer(struct libtelnet_t *telnet, unsigned char *buffer,
- size_t size, void *user_data);
+extern void libtelnet_push_buffer(struct libtelnet_t *telnet,
+ unsigned char *buffer, size_t size, void *user_data);
/* send an iac command */
-void libtelnet_send_command(struct libtelnet_t *telnet, unsigned char cmd,
- void *user_data);
+extern void libtelnet_send_command(struct libtelnet_t *telnet,
+ unsigned char cmd, void *user_data);
/* send negotiation */
-void libtelnet_send_negotiate(struct libtelnet_t *telnet, unsigned char cmd,
- unsigned char opt, void *user_data);
+extern void libtelnet_send_negotiate(struct libtelnet_t *telnet,
+ unsigned char cmd, unsigned char opt, void *user_data);
/* send non-command data (escapes IAC bytes) */
-void libtelnet_send_data(struct libtelnet_t *telnet, unsigned char *buffer,
- size_t size, void *user_data);
+extern void libtelnet_send_data(struct libtelnet_t *telnet,
+ unsigned char *buffer, size_t size, void *user_data);
/* send sub-request */
-void libtelnet_send_subrequest(struct libtelnet_t *telnet, unsigned char type,
- unsigned char *buffer, size_t size, void *user_data);
+extern void libtelnet_send_subrequest(struct libtelnet_t *telnet,
+ unsigned char type, unsigned char *buffer, size_t size, void *user_data);