mirror of https://gerrit.osmocom.org/libtelnet
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:
parent
d08d812c30
commit
d2466a01b6
44
libtelnet.c
44
libtelnet.c
|
@ -35,6 +35,36 @@
|
|||
# define INLINE
|
||||
#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 */
|
||||
typedef struct telnet_rfc1143_t {
|
||||
unsigned char telopt;
|
||||
|
@ -559,13 +589,20 @@ static int _subnegotiate(telnet_t *telnet) {
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
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->telopts = telopts;
|
||||
telnet->eh = eh;
|
||||
telnet->flags = flags;
|
||||
|
||||
return telnet;
|
||||
}
|
||||
|
||||
/* free up any memory allocated by a state tracker */
|
||||
|
@ -596,6 +633,9 @@ void telnet_free(telnet_t *telnet) {
|
|||
telnet->q = 0;
|
||||
telnet->q_size = 0;
|
||||
}
|
||||
|
||||
/* free the telnet structure itself */
|
||||
free(telnet);
|
||||
}
|
||||
|
||||
/* push a byte into the telnet buffer */
|
||||
|
|
33
libtelnet.h
33
libtelnet.h
|
@ -186,38 +186,11 @@ struct telnet_telopt_t {
|
|||
unsigned char him; /* TELNET_DO or TELNET_DONT */
|
||||
};
|
||||
|
||||
/* state tracker */
|
||||
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;
|
||||
};
|
||||
/* state tracker -- private data structure */
|
||||
struct telnet_t;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* free up any memory allocated by a state tracker */
|
||||
|
|
|
@ -37,7 +37,7 @@ const telnet_telopt_t telopts[] = {
|
|||
struct user_t {
|
||||
char *name;
|
||||
int sock;
|
||||
telnet_t telnet;
|
||||
telnet_t *telnet;
|
||||
char linebuf[256];
|
||||
int linepos;
|
||||
};
|
||||
|
@ -79,7 +79,7 @@ static void _message(const char *from, const char *msg) {
|
|||
int i;
|
||||
for (i = 0; i != MAX_USERS; ++i) {
|
||||
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) {
|
||||
/* must not be empty, must be at least 32 chars */
|
||||
if (strlen(line) == 0 || strlen(line) > 32) {
|
||||
telnet_printf(&user->telnet, "Invalid name.\nEnter name: ");
|
||||
telnet_printf(user->telnet, "Invalid name.\nEnter name: ");
|
||||
return;
|
||||
}
|
||||
|
||||
/* must not already be in use */
|
||||
for (i = 0; i != MAX_USERS; ++i) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* keep name */
|
||||
user->name = strdup(line);
|
||||
telnet_printf(&user->telnet, "Welcome, %s!\n", line);
|
||||
telnet_printf(user->telnet, "Welcome, %s!\n", line);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
|
|||
free(user->name);
|
||||
user->name = 0;
|
||||
}
|
||||
telnet_free(&user->telnet);
|
||||
telnet_free(user->telnet);
|
||||
break;
|
||||
default:
|
||||
/* ignore */
|
||||
|
@ -296,11 +296,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* init, welcome */
|
||||
users[i].sock = rs;
|
||||
telnet_init(&users[i].telnet, telopts, _event_handler, 0,
|
||||
users[i].telnet = telnet_init(telopts, _event_handler, 0,
|
||||
&users[i]);
|
||||
telnet_negotiate(&users[i].telnet, TELNET_WILL,
|
||||
telnet_negotiate(users[i].telnet, TELNET_WILL,
|
||||
TELNET_TELOPT_COMPRESS2);
|
||||
telnet_printf(&users[i].telnet, "Enter name: ");
|
||||
telnet_printf(users[i].telnet, "Enter name: ");
|
||||
}
|
||||
|
||||
/* read from client */
|
||||
|
@ -311,7 +311,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (pfd[i].revents & POLLIN) {
|
||||
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) {
|
||||
printf("Connection closed.\n");
|
||||
close(users[i].sock);
|
||||
|
@ -320,7 +320,7 @@ int main(int argc, char **argv) {
|
|||
free(users[i].name);
|
||||
users[i].name = 0;
|
||||
}
|
||||
telnet_free(&users[i].telnet);
|
||||
telnet_free(users[i].telnet);
|
||||
users[i].sock = -1;
|
||||
break;
|
||||
} else if (errno != EINTR) {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "libtelnet.h"
|
||||
|
||||
static struct termios orig_tios;
|
||||
static telnet_t telnet;
|
||||
static telnet_t *telnet;
|
||||
static int do_echo;
|
||||
|
||||
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 (do_echo)
|
||||
printf("\r\n");
|
||||
telnet_send(&telnet, crlf, 2);
|
||||
telnet_send(telnet, crlf, 2);
|
||||
} else {
|
||||
if (do_echo)
|
||||
putchar(buffer[i]);
|
||||
telnet_send(&telnet, buffer + i, 1);
|
||||
telnet_send(telnet, buffer + i, 1);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
@ -197,7 +197,7 @@ int main(int argc, char **argv) {
|
|||
do_echo = 1;
|
||||
|
||||
/* initialize telnet box */
|
||||
telnet_init(&telnet, telopts, _event_handler, 0, &sock);
|
||||
telnet = telnet_init(telopts, _event_handler, 0, &sock);
|
||||
|
||||
/* initialize poll descriptors */
|
||||
memset(pfd, 0, sizeof(pfd));
|
||||
|
@ -224,7 +224,7 @@ int main(int argc, char **argv) {
|
|||
/* read from client */
|
||||
if (pfd[1].revents & POLLIN) {
|
||||
if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) {
|
||||
telnet_recv(&telnet, buffer, rs);
|
||||
telnet_recv(telnet, buffer, rs);
|
||||
} else if (rs == 0) {
|
||||
break;
|
||||
} else {
|
||||
|
@ -236,7 +236,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* clean up */
|
||||
telnet_free(&telnet);
|
||||
telnet_free(telnet);
|
||||
close(sock);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
struct conn_t {
|
||||
const char *name;
|
||||
int sock;
|
||||
telnet_t telnet;
|
||||
telnet_t *telnet;
|
||||
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);
|
||||
printf(COLOR_NORMAL "\n");
|
||||
|
||||
telnet_send(&conn->remote->telnet, ev->buffer, ev->size);
|
||||
telnet_send(conn->remote->telnet, ev->buffer, ev->size);
|
||||
break;
|
||||
/* data must be sent */
|
||||
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,
|
||||
get_cmd(ev->command));
|
||||
|
||||
telnet_iac(&conn->remote->telnet, ev->command);
|
||||
telnet_iac(conn->remote->telnet, ev->command);
|
||||
break;
|
||||
/* negotiation, WILL */
|
||||
case TELNET_EV_WILL:
|
||||
printf("%s IAC WILL %d (%s)" COLOR_NORMAL "\n", conn->name,
|
||||
(int)ev->telopt, get_opt(ev->telopt));
|
||||
telnet_negotiate(&conn->remote->telnet, TELNET_WILL,
|
||||
telnet_negotiate(conn->remote->telnet, TELNET_WILL,
|
||||
ev->telopt);
|
||||
break;
|
||||
/* negotiation, WONT */
|
||||
case TELNET_EV_WONT:
|
||||
printf("%s IAC WONT %d (%s)" COLOR_NORMAL "\n", conn->name,
|
||||
(int)ev->telopt, get_opt(ev->telopt));
|
||||
telnet_negotiate(&conn->remote->telnet, TELNET_WONT,
|
||||
telnet_negotiate(conn->remote->telnet, TELNET_WONT,
|
||||
ev->telopt);
|
||||
break;
|
||||
/* negotiation, DO */
|
||||
case TELNET_EV_DO:
|
||||
printf("%s IAC DO %d (%s)" COLOR_NORMAL "\n", conn->name,
|
||||
(int)ev->telopt, get_opt(ev->telopt));
|
||||
telnet_negotiate(&conn->remote->telnet, TELNET_DO,
|
||||
telnet_negotiate(conn->remote->telnet, TELNET_DO,
|
||||
ev->telopt);
|
||||
break;
|
||||
case TELNET_EV_DONT:
|
||||
printf("%s IAC DONT %d (%s)" COLOR_NORMAL "\n", conn->name,
|
||||
(int)ev->telopt, get_opt(ev->telopt));
|
||||
telnet_negotiate(&conn->remote->telnet, TELNET_DONT,
|
||||
telnet_negotiate(conn->remote->telnet, TELNET_DONT,
|
||||
ev->telopt);
|
||||
break;
|
||||
/* subnegotiation */
|
||||
|
@ -264,7 +264,7 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
|
|||
}
|
||||
|
||||
/* forward */
|
||||
telnet_subnegotiation(&conn->remote->telnet, ev->telopt,
|
||||
telnet_subnegotiation(conn->remote->telnet, ev->telopt,
|
||||
ev->buffer, ev->size);
|
||||
break;
|
||||
/* compression notification */
|
||||
|
@ -389,9 +389,9 @@ int main(int argc, char **argv) {
|
|||
client.remote = &server;
|
||||
|
||||
/* initialize telnet boxes */
|
||||
telnet_init(&server.telnet, 0, _event_handler, TELNET_FLAG_PROXY,
|
||||
server.telnet = telnet_init(0, _event_handler, TELNET_FLAG_PROXY,
|
||||
&server);
|
||||
telnet_init(&client.telnet, 0, _event_handler, TELNET_FLAG_PROXY,
|
||||
client.telnet = telnet_init(0, _event_handler, TELNET_FLAG_PROXY,
|
||||
&client);
|
||||
|
||||
/* initialize poll descriptors */
|
||||
|
@ -406,7 +406,7 @@ int main(int argc, char **argv) {
|
|||
/* read from server */
|
||||
if (pfd[0].revents & POLLIN) {
|
||||
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) {
|
||||
printf("%s DISCONNECTED" COLOR_NORMAL "\n", server.name);
|
||||
break;
|
||||
|
@ -422,7 +422,7 @@ int main(int argc, char **argv) {
|
|||
/* read from client */
|
||||
if (pfd[1].revents & POLLIN) {
|
||||
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) {
|
||||
printf("%s DISCONNECTED" COLOR_NORMAL "\n", client.name);
|
||||
break;
|
||||
|
@ -437,8 +437,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* clean up */
|
||||
telnet_free(&server.telnet);
|
||||
telnet_free(&client.telnet);
|
||||
telnet_free(server.telnet);
|
||||
telnet_free(client.telnet);
|
||||
close(server.sock);
|
||||
close(client.sock);
|
||||
|
||||
|
|
Loading…
Reference in New Issue