make libtelnet_t private; libtelnet_init now returns a pointer instead of taking one, and libtelnet_free frees the pointer passed in

This commit is contained in:
Sean Middleditch 2009-09-19 14:35:48 -07:00
parent d08d812c30
commit d2466a01b6
5 changed files with 76 additions and 63 deletions

View File

@ -35,6 +35,36 @@
# define INLINE # define INLINE
#endif #endif
/* telnet state */
struct telnet_t {
/* user data */
void *ud;
/* telopt support table */
const telnet_telopt_t *telopts;
/* event handler */
telnet_event_handler_t eh;
#ifdef HAVE_ZLIB
/* zlib (mccp2) compression */
z_stream *z;
#endif
/* RFC1143 option negotiation states */
struct telnet_rfc1143_t *q;
/* sub-request buffer */
char *buffer;
/* current size of the buffer */
size_t buffer_size;
/* current buffer write position (also length of buffer data) */
size_t buffer_pos;
/* current state */
enum telnet_state_t state;
/* option flags */
unsigned char flags;
/* current subnegotiation telopt */
unsigned char sb_telopt;
/* length of RFC1143 queue */
unsigned char q_size;
};
/* RFC1143 option negotiation state */ /* RFC1143 option negotiation state */
typedef struct telnet_rfc1143_t { typedef struct telnet_rfc1143_t {
unsigned char telopt; unsigned char telopt;
@ -559,13 +589,20 @@ static int _subnegotiate(telnet_t *telnet) {
} }
/* initialize a telnet state tracker */ /* initialize a telnet state tracker */
void telnet_init(telnet_t *telnet, const telnet_telopt_t *telopts, telnet_t *telnet_init(const telnet_telopt_t *telopts,
telnet_event_handler_t eh, unsigned char flags, void *user_data) { telnet_event_handler_t eh, unsigned char flags, void *user_data) {
memset(telnet, 0, sizeof(telnet_t)); /* allocate structure */
struct telnet_t *telnet = (telnet_t*)calloc(1, sizeof(telnet_t));
if (telnet == 0)
return 0;
/* initialize data */
telnet->ud = user_data; telnet->ud = user_data;
telnet->telopts = telopts; telnet->telopts = telopts;
telnet->eh = eh; telnet->eh = eh;
telnet->flags = flags; telnet->flags = flags;
return telnet;
} }
/* free up any memory allocated by a state tracker */ /* free up any memory allocated by a state tracker */
@ -596,6 +633,9 @@ void telnet_free(telnet_t *telnet) {
telnet->q = 0; telnet->q = 0;
telnet->q_size = 0; telnet->q_size = 0;
} }
/* free the telnet structure itself */
free(telnet);
} }
/* push a byte into the telnet buffer */ /* push a byte into the telnet buffer */

View File

@ -186,38 +186,11 @@ struct telnet_telopt_t {
unsigned char him; /* TELNET_DO or TELNET_DONT */ unsigned char him; /* TELNET_DO or TELNET_DONT */
}; };
/* state tracker */ /* state tracker -- private data structure */
struct telnet_t { struct telnet_t;
/* user data */
void *ud;
/* telopt support table */
const telnet_telopt_t *telopts;
/* event handler */
telnet_event_handler_t eh;
#ifdef HAVE_ZLIB
/* zlib (mccp2) compression */
z_stream *z;
#endif
/* RFC1143 option negotiation states */
struct telnet_rfc1143_t *q;
/* sub-request buffer */
char *buffer;
/* current size of the buffer */
size_t buffer_size;
/* current buffer write position (also length of buffer data) */
size_t buffer_pos;
/* current state */
enum telnet_state_t state;
/* option flags */
unsigned char flags;
/* current subnegotiation telopt */
unsigned char sb_telopt;
/* length of RFC1143 queue */
unsigned char q_size;
};
/* initialize a telnet state tracker */ /* initialize a telnet state tracker */
extern void telnet_init(telnet_t *telnet, const telnet_telopt_t *telopts, extern telnet_t* telnet_init(const telnet_telopt_t *telopts,
telnet_event_handler_t eh, unsigned char flags, void *user_data); telnet_event_handler_t eh, unsigned char flags, void *user_data);
/* free up any memory allocated by a state tracker */ /* free up any memory allocated by a state tracker */

View File

@ -37,7 +37,7 @@ const telnet_telopt_t telopts[] = {
struct user_t { struct user_t {
char *name; char *name;
int sock; int sock;
telnet_t telnet; telnet_t *telnet;
char linebuf[256]; char linebuf[256];
int linepos; int linepos;
}; };
@ -79,7 +79,7 @@ static void _message(const char *from, const char *msg) {
int i; int i;
for (i = 0; i != MAX_USERS; ++i) { for (i = 0; i != MAX_USERS; ++i) {
if (users[i].sock != -1) { if (users[i].sock != -1) {
telnet_printf(&users[i].telnet, "%s: %s\n", from, msg); telnet_printf(users[i].telnet, "%s: %s\n", from, msg);
} }
} }
} }
@ -120,21 +120,21 @@ static void _online(const char *line, int overflow, void *ud) {
if (user->name == 0) { if (user->name == 0) {
/* must not be empty, must be at least 32 chars */ /* must not be empty, must be at least 32 chars */
if (strlen(line) == 0 || strlen(line) > 32) { if (strlen(line) == 0 || strlen(line) > 32) {
telnet_printf(&user->telnet, "Invalid name.\nEnter name: "); telnet_printf(user->telnet, "Invalid name.\nEnter name: ");
return; return;
} }
/* must not already be in use */ /* must not already be in use */
for (i = 0; i != MAX_USERS; ++i) { for (i = 0; i != MAX_USERS; ++i) {
if (users[i].name != 0 && strcmp(users[i].name, line) == 0) { if (users[i].name != 0 && strcmp(users[i].name, line) == 0) {
telnet_printf(&user->telnet, "Name in use.\nEnter name: "); telnet_printf(user->telnet, "Name in use.\nEnter name: ");
return; return;
} }
} }
/* keep name */ /* keep name */
user->name = strdup(line); user->name = strdup(line);
telnet_printf(&user->telnet, "Welcome, %s!\n", line); telnet_printf(user->telnet, "Welcome, %s!\n", line);
return; return;
} }
@ -187,7 +187,7 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
free(user->name); free(user->name);
user->name = 0; user->name = 0;
} }
telnet_free(&user->telnet); telnet_free(user->telnet);
break; break;
default: default:
/* ignore */ /* ignore */
@ -296,11 +296,11 @@ int main(int argc, char **argv) {
/* init, welcome */ /* init, welcome */
users[i].sock = rs; users[i].sock = rs;
telnet_init(&users[i].telnet, telopts, _event_handler, 0, users[i].telnet = telnet_init(telopts, _event_handler, 0,
&users[i]); &users[i]);
telnet_negotiate(&users[i].telnet, TELNET_WILL, telnet_negotiate(users[i].telnet, TELNET_WILL,
TELNET_TELOPT_COMPRESS2); TELNET_TELOPT_COMPRESS2);
telnet_printf(&users[i].telnet, "Enter name: "); telnet_printf(users[i].telnet, "Enter name: ");
} }
/* read from client */ /* read from client */
@ -311,7 +311,7 @@ int main(int argc, char **argv) {
if (pfd[i].revents & POLLIN) { if (pfd[i].revents & POLLIN) {
if ((rs = recv(users[i].sock, buffer, sizeof(buffer), 0)) > 0) { if ((rs = recv(users[i].sock, buffer, sizeof(buffer), 0)) > 0) {
telnet_recv(&users[i].telnet, buffer, rs); telnet_recv(users[i].telnet, buffer, rs);
} else if (rs == 0) { } else if (rs == 0) {
printf("Connection closed.\n"); printf("Connection closed.\n");
close(users[i].sock); close(users[i].sock);
@ -320,7 +320,7 @@ int main(int argc, char **argv) {
free(users[i].name); free(users[i].name);
users[i].name = 0; users[i].name = 0;
} }
telnet_free(&users[i].telnet); telnet_free(users[i].telnet);
users[i].sock = -1; users[i].sock = -1;
break; break;
} else if (errno != EINTR) { } else if (errno != EINTR) {

View File

@ -29,7 +29,7 @@
#include "libtelnet.h" #include "libtelnet.h"
static struct termios orig_tios; static struct termios orig_tios;
static telnet_t telnet; static telnet_t *telnet;
static int do_echo; static int do_echo;
static const telnet_telopt_t telopts[] = { static const telnet_telopt_t telopts[] = {
@ -56,11 +56,11 @@ static void _input(char *buffer, int size) {
if (buffer[i] == '\r' || buffer[i] == '\n') { if (buffer[i] == '\r' || buffer[i] == '\n') {
if (do_echo) if (do_echo)
printf("\r\n"); printf("\r\n");
telnet_send(&telnet, crlf, 2); telnet_send(telnet, crlf, 2);
} else { } else {
if (do_echo) if (do_echo)
putchar(buffer[i]); putchar(buffer[i]);
telnet_send(&telnet, buffer + i, 1); telnet_send(telnet, buffer + i, 1);
} }
} }
fflush(stdout); fflush(stdout);
@ -197,7 +197,7 @@ int main(int argc, char **argv) {
do_echo = 1; do_echo = 1;
/* initialize telnet box */ /* initialize telnet box */
telnet_init(&telnet, telopts, _event_handler, 0, &sock); telnet = telnet_init(telopts, _event_handler, 0, &sock);
/* initialize poll descriptors */ /* initialize poll descriptors */
memset(pfd, 0, sizeof(pfd)); memset(pfd, 0, sizeof(pfd));
@ -224,7 +224,7 @@ int main(int argc, char **argv) {
/* read from client */ /* read from client */
if (pfd[1].revents & POLLIN) { if (pfd[1].revents & POLLIN) {
if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) {
telnet_recv(&telnet, buffer, rs); telnet_recv(telnet, buffer, rs);
} else if (rs == 0) { } else if (rs == 0) {
break; break;
} else { } else {
@ -236,7 +236,7 @@ int main(int argc, char **argv) {
} }
/* clean up */ /* clean up */
telnet_free(&telnet); telnet_free(telnet);
close(sock); close(sock);
return 0; return 0;

View File

@ -44,7 +44,7 @@
struct conn_t { struct conn_t {
const char *name; const char *name;
int sock; int sock;
telnet_t telnet; telnet_t *telnet;
struct conn_t *remote; struct conn_t *remote;
}; };
@ -176,7 +176,7 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
print_buffer(ev->buffer, ev->size); print_buffer(ev->buffer, ev->size);
printf(COLOR_NORMAL "\n"); printf(COLOR_NORMAL "\n");
telnet_send(&conn->remote->telnet, ev->buffer, ev->size); telnet_send(conn->remote->telnet, ev->buffer, ev->size);
break; break;
/* data must be sent */ /* data must be sent */
case TELNET_EV_SEND: case TELNET_EV_SEND:
@ -193,33 +193,33 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
printf("%s IAC %s" COLOR_NORMAL "\n", conn->name, printf("%s IAC %s" COLOR_NORMAL "\n", conn->name,
get_cmd(ev->command)); get_cmd(ev->command));
telnet_iac(&conn->remote->telnet, ev->command); telnet_iac(conn->remote->telnet, ev->command);
break; break;
/* negotiation, WILL */ /* negotiation, WILL */
case TELNET_EV_WILL: case TELNET_EV_WILL:
printf("%s IAC WILL %d (%s)" COLOR_NORMAL "\n", conn->name, printf("%s IAC WILL %d (%s)" COLOR_NORMAL "\n", conn->name,
(int)ev->telopt, get_opt(ev->telopt)); (int)ev->telopt, get_opt(ev->telopt));
telnet_negotiate(&conn->remote->telnet, TELNET_WILL, telnet_negotiate(conn->remote->telnet, TELNET_WILL,
ev->telopt); ev->telopt);
break; break;
/* negotiation, WONT */ /* negotiation, WONT */
case TELNET_EV_WONT: case TELNET_EV_WONT:
printf("%s IAC WONT %d (%s)" COLOR_NORMAL "\n", conn->name, printf("%s IAC WONT %d (%s)" COLOR_NORMAL "\n", conn->name,
(int)ev->telopt, get_opt(ev->telopt)); (int)ev->telopt, get_opt(ev->telopt));
telnet_negotiate(&conn->remote->telnet, TELNET_WONT, telnet_negotiate(conn->remote->telnet, TELNET_WONT,
ev->telopt); ev->telopt);
break; break;
/* negotiation, DO */ /* negotiation, DO */
case TELNET_EV_DO: case TELNET_EV_DO:
printf("%s IAC DO %d (%s)" COLOR_NORMAL "\n", conn->name, printf("%s IAC DO %d (%s)" COLOR_NORMAL "\n", conn->name,
(int)ev->telopt, get_opt(ev->telopt)); (int)ev->telopt, get_opt(ev->telopt));
telnet_negotiate(&conn->remote->telnet, TELNET_DO, telnet_negotiate(conn->remote->telnet, TELNET_DO,
ev->telopt); ev->telopt);
break; break;
case TELNET_EV_DONT: case TELNET_EV_DONT:
printf("%s IAC DONT %d (%s)" COLOR_NORMAL "\n", conn->name, printf("%s IAC DONT %d (%s)" COLOR_NORMAL "\n", conn->name,
(int)ev->telopt, get_opt(ev->telopt)); (int)ev->telopt, get_opt(ev->telopt));
telnet_negotiate(&conn->remote->telnet, TELNET_DONT, telnet_negotiate(conn->remote->telnet, TELNET_DONT,
ev->telopt); ev->telopt);
break; break;
/* subnegotiation */ /* subnegotiation */
@ -264,7 +264,7 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
} }
/* forward */ /* forward */
telnet_subnegotiation(&conn->remote->telnet, ev->telopt, telnet_subnegotiation(conn->remote->telnet, ev->telopt,
ev->buffer, ev->size); ev->buffer, ev->size);
break; break;
/* compression notification */ /* compression notification */
@ -389,9 +389,9 @@ int main(int argc, char **argv) {
client.remote = &server; client.remote = &server;
/* initialize telnet boxes */ /* initialize telnet boxes */
telnet_init(&server.telnet, 0, _event_handler, TELNET_FLAG_PROXY, server.telnet = telnet_init(0, _event_handler, TELNET_FLAG_PROXY,
&server); &server);
telnet_init(&client.telnet, 0, _event_handler, TELNET_FLAG_PROXY, client.telnet = telnet_init(0, _event_handler, TELNET_FLAG_PROXY,
&client); &client);
/* initialize poll descriptors */ /* initialize poll descriptors */
@ -406,7 +406,7 @@ int main(int argc, char **argv) {
/* read from server */ /* read from server */
if (pfd[0].revents & POLLIN) { if (pfd[0].revents & POLLIN) {
if ((rs = recv(server.sock, buffer, sizeof(buffer), 0)) > 0) { if ((rs = recv(server.sock, buffer, sizeof(buffer), 0)) > 0) {
telnet_recv(&server.telnet, buffer, rs); telnet_recv(server.telnet, buffer, rs);
} else if (rs == 0) { } else if (rs == 0) {
printf("%s DISCONNECTED" COLOR_NORMAL "\n", server.name); printf("%s DISCONNECTED" COLOR_NORMAL "\n", server.name);
break; break;
@ -422,7 +422,7 @@ int main(int argc, char **argv) {
/* read from client */ /* read from client */
if (pfd[1].revents & POLLIN) { if (pfd[1].revents & POLLIN) {
if ((rs = recv(client.sock, buffer, sizeof(buffer), 0)) > 0) { if ((rs = recv(client.sock, buffer, sizeof(buffer), 0)) > 0) {
telnet_recv(&client.telnet, buffer, rs); telnet_recv(client.telnet, buffer, rs);
} else if (rs == 0) { } else if (rs == 0) {
printf("%s DISCONNECTED" COLOR_NORMAL "\n", client.name); printf("%s DISCONNECTED" COLOR_NORMAL "\n", client.name);
break; break;
@ -437,8 +437,8 @@ int main(int argc, char **argv) {
} }
/* clean up */ /* clean up */
telnet_free(&server.telnet); telnet_free(server.telnet);
telnet_free(&client.telnet); telnet_free(client.telnet);
close(server.sock); close(server.sock);
close(client.sock); close(client.sock);