dont use a separate event for ZMP

This commit is contained in:
Sean Middleditch 2009-03-22 18:21:14 -04:00
parent 53a86613c6
commit b10946c96d
4 changed files with 82 additions and 45 deletions

26
README
View File

@ -403,6 +403,14 @@ IId. Event Handling
has been enabled through the use of the telnet negotiation
feature.
ZMP SUPPORT:
The event->argc field is the number of ZMP parameters, including
the command name, that have been received. The event->argv field
is an array of strings, one for each ZMP parameter. The command
name will be in event->argv[0]. If the ZMP command could not be
parsed because it was malformed, event->argc will be 0 (zero) and
event->argv will be NULL.
TELNET_EV_COMPRESS
The COMPRESS event notifies the app that COMPRESS2/MCCP2
compression has begun or ended. Only servers can send compressed
@ -411,13 +419,6 @@ IId. Event Handling
The event->command value will be 1 if compression has started and
will be 0 if compression has ended.
TELNET_EV_ZMP
The ZMP event is sent whenever a ZMP command has been received.
The event->argc field is the number of ZMP parameters, including
the command name, that have been received. The event->argv field
is an array of strings, one for each ZMP parameter. The command
name will be in event->argv[0].
TELNET_EV_WARNING
The WARNING event is sent whenever something has gone wrong inside
of libtelnet (possibly due to malformed data sent by the other
@ -529,8 +530,15 @@ enables the client to send ZMP commands. The client must never
attempt to negotiate ZMP directly using telnet_negotiate().
Once ZMP is enabled, any ZMP commands received will automatically be
sent to the event handler function with the TELNET_EV_ZMP event
code.
sent to the event handler function with the TELNET_EV_SUBNEGOTIATION
event code. The command will automatically be parsed and the ZMP
parameters will be placed in the event->argv array and the number of
parameters will be placed in the event->argc field.
NOTE: if an error occured while parsing the ZMP command because it
was malformed, the event->argc field will be equal to 0 and the
event->argv field will be NULL. You should always check for this
before attempting to access the parameter array.
To send ZMP commands to the remote end, use either telnet_send_zmp()
or telnet_send_zmpv().

View File

@ -408,46 +408,53 @@ static void _negotiate(telnet_t *telnet, unsigned char telopt) {
* must be aborted and reprocessed due to COMPRESS2 being activated
*/
static int _subnegotiate(telnet_t *telnet) {
/* invoke callback */
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, 0, 0);
const char **argv;
const char *c;
size_t i, argc;
switch (telnet->sb_telopt) {
#ifdef HAVE_ZLIB
/* received COMPRESS2 begin marker, setup our zlib box and
* start handling the compressed stream if it's not already.
*/
#ifdef HAVE_ZLIB
if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) {
if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
return 0;
case TELNET_TELOPT_COMPRESS2:
if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) {
if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
return 0;
/* notify app that compression was enabled */
_event(telnet, TELNET_EV_COMPRESS, 1, 0, 0, 0, 0, 0);
return 1;
}
/* standard SB notification */
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, 0, 0);
/* notify app that compression was enabled */
_event(telnet, TELNET_EV_COMPRESS, 1, 0, 0, 0, 0, 0);
return 1;
}
break;
#endif /* HAVE_ZLIB */
/* parse ZMP args */
if (telnet->sb_telopt == TELNET_TELOPT_ZMP) {
const char **argv;
const char *c = telnet->buffer;
size_t i, argc = 0;
/* ZMP command */
case TELNET_TELOPT_ZMP:
/* make sure this is a valid ZMP buffer */
if (telnet->buffer_pos == 0 || telnet->buffer[telnet->buffer_pos - 1]
!= 0)
if (telnet->buffer_pos == 0 ||
telnet->buffer[telnet->buffer_pos - 1] != 0) {
_error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
"incomplete ZMP frame");
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, 0, 0);
return 0;
}
/* count arguments */
while (c != telnet->buffer + telnet->buffer_pos) {
++argc;
for (argc = 0, c = telnet->buffer; c != telnet->buffer +
telnet->buffer_pos; ++argc)
c += strlen(c) + 1;
}
/* allocate argument array, bail on error */
if ((argv = (const char **)malloc(sizeof(char *) * argc)) == 0) {
_error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
"malloc() failed: %s", strerror(errno));
return 0;
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, 0, 0);
}
/* populate argument array */
@ -456,11 +463,18 @@ static int _subnegotiate(telnet_t *telnet) {
c += strlen(c) + 1;
}
/* invoke ZMP event */
_event(telnet, TELNET_EV_ZMP, 0, 0, 0, 0, argv, argc);
/* invoke event with our arguments */
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, argv, argc);
/* free argument array */
free(argv);
break;
/* other generic subnegotiation */
default:
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, 0, 0);
break;
}
return 0;

View File

@ -137,7 +137,6 @@ enum telnet_event_type_t {
TELNET_EV_DONT,
TELNET_EV_SUBNEGOTIATION,
TELNET_EV_COMPRESS,
TELNET_EV_ZMP,
TELNET_EV_WARNING,
TELNET_EV_ERROR
};

View File

@ -224,14 +224,33 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
break;
/* subnegotiation */
case TELNET_EV_SUBNEGOTIATION:
printf("%s SUB %d (%s)", conn->name, (int)ev->telopt,
get_opt(ev->telopt));
if (ev->size > 0) {
printf(" [%zi]: ", ev->size);
print_buffer(ev->buffer, ev->size);
if (ev->telopt == TELNET_TELOPT_ZMP) {
if (ev->argc != 0) {
size_t i;
printf("%s ZMP [%zi params]", conn->name, ev->argc);
for (i = 0; i != ev->argc; ++i) {
printf(" \"");
print_buffer(ev->argv[i], strlen(ev->argv[i]));
printf("\"");
}
printf(COLOR_NORMAL "\n");
} else {
printf("%s ZMP (malformed!) [%zi bytes]",
conn->name, ev->size);
print_buffer(ev->buffer, ev->size);
printf(COLOR_NORMAL "\n");
}
} else {
printf("%s SUB %d (%s)", conn->name, (int)ev->telopt,
get_opt(ev->telopt));
if (ev->size > 0) {
printf(" [%zi bytes]: ", ev->size);
print_buffer(ev->buffer, ev->size);
}
printf(COLOR_NORMAL "\n");
}
printf(COLOR_NORMAL "\n");
/* forward */
telnet_subnegotiation(&conn->remote->telnet, ev->telopt,
ev->buffer, ev->size);
break;
@ -240,9 +259,6 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
printf("%s COMPRESSION %s" COLOR_NORMAL "\n", conn->name,
ev->command ? "ON" : "OFF");
break;
/* ZMP command (ignored in PROXY mode) */
case TELNET_EV_ZMP:
break;
/* warning */
case TELNET_EV_WARNING:
printf("%s WARNING: %s" COLOR_NORMAL "\n", conn->name, ev->buffer);