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 has been enabled through the use of the telnet negotiation
feature. 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 TELNET_EV_COMPRESS
The COMPRESS event notifies the app that COMPRESS2/MCCP2 The COMPRESS event notifies the app that COMPRESS2/MCCP2
compression has begun or ended. Only servers can send compressed 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 The event->command value will be 1 if compression has started and
will be 0 if compression has ended. 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 TELNET_EV_WARNING
The WARNING event is sent whenever something has gone wrong inside The WARNING event is sent whenever something has gone wrong inside
of libtelnet (possibly due to malformed data sent by the other 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(). attempt to negotiate ZMP directly using telnet_negotiate().
Once ZMP is enabled, any ZMP commands received will automatically be Once ZMP is enabled, any ZMP commands received will automatically be
sent to the event handler function with the TELNET_EV_ZMP event sent to the event handler function with the TELNET_EV_SUBNEGOTIATION
code. 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() To send ZMP commands to the remote end, use either telnet_send_zmp()
or telnet_send_zmpv(). 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 * must be aborted and reprocessed due to COMPRESS2 being activated
*/ */
static int _subnegotiate(telnet_t *telnet) { static int _subnegotiate(telnet_t *telnet) {
/* invoke callback */ const char **argv;
_event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt, const char *c;
telnet->buffer, telnet->buffer_pos, 0, 0); size_t i, argc;
switch (telnet->sb_telopt) {
#ifdef HAVE_ZLIB
/* received COMPRESS2 begin marker, setup our zlib box and /* received COMPRESS2 begin marker, setup our zlib box and
* start handling the compressed stream if it's not already. * start handling the compressed stream if it's not already.
*/ */
#ifdef HAVE_ZLIB case TELNET_TELOPT_COMPRESS2:
if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) { if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) {
if (_init_zlib(telnet, 0, 1) != TELNET_EOK) if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
return 0; return 0;
/* 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 */ /* notify app that compression was enabled */
_event(telnet, TELNET_EV_COMPRESS, 1, 0, 0, 0, 0, 0); _event(telnet, TELNET_EV_COMPRESS, 1, 0, 0, 0, 0, 0);
return 1; return 1;
} }
break;
#endif /* HAVE_ZLIB */ #endif /* HAVE_ZLIB */
/* ZMP command */
/* parse ZMP args */ case TELNET_TELOPT_ZMP:
if (telnet->sb_telopt == TELNET_TELOPT_ZMP) {
const char **argv;
const char *c = telnet->buffer;
size_t i, argc = 0;
/* make sure this is a valid ZMP buffer */ /* make sure this is a valid ZMP buffer */
if (telnet->buffer_pos == 0 || telnet->buffer[telnet->buffer_pos - 1] if (telnet->buffer_pos == 0 ||
!= 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; return 0;
}
/* count arguments */ /* count arguments */
while (c != telnet->buffer + telnet->buffer_pos) { for (argc = 0, c = telnet->buffer; c != telnet->buffer +
++argc; telnet->buffer_pos; ++argc)
c += strlen(c) + 1; c += strlen(c) + 1;
}
/* allocate argument array, bail on error */ /* allocate argument array, bail on error */
if ((argv = (const char **)malloc(sizeof(char *) * argc)) == 0) { if ((argv = (const char **)malloc(sizeof(char *) * argc)) == 0) {
_error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
"malloc() failed: %s", strerror(errno)); "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 */ /* populate argument array */
@ -456,11 +463,18 @@ static int _subnegotiate(telnet_t *telnet) {
c += strlen(c) + 1; c += strlen(c) + 1;
} }
/* invoke ZMP event */ /* invoke event with our arguments */
_event(telnet, TELNET_EV_ZMP, 0, 0, 0, 0, argv, argc); _event(telnet, TELNET_EV_SUBNEGOTIATION, 0, telnet->sb_telopt,
telnet->buffer, telnet->buffer_pos, argv, argc);
/* free argument array */ /* free argument array */
free(argv); 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; return 0;

View File

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

View File

@ -224,14 +224,33 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
break; break;
/* subnegotiation */ /* subnegotiation */
case TELNET_EV_SUBNEGOTIATION: case TELNET_EV_SUBNEGOTIATION:
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, printf("%s SUB %d (%s)", conn->name, (int)ev->telopt,
get_opt(ev->telopt)); get_opt(ev->telopt));
if (ev->size > 0) { if (ev->size > 0) {
printf(" [%zi]: ", ev->size); printf(" [%zi bytes]: ", ev->size);
print_buffer(ev->buffer, ev->size); print_buffer(ev->buffer, ev->size);
} }
printf(COLOR_NORMAL "\n"); printf(COLOR_NORMAL "\n");
}
/* 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;
@ -240,9 +259,6 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
printf("%s COMPRESSION %s" COLOR_NORMAL "\n", conn->name, printf("%s COMPRESSION %s" COLOR_NORMAL "\n", conn->name,
ev->command ? "ON" : "OFF"); ev->command ? "ON" : "OFF");
break; break;
/* ZMP command (ignored in PROXY mode) */
case TELNET_EV_ZMP:
break;
/* warning */ /* warning */
case TELNET_EV_WARNING: case TELNET_EV_WARNING:
printf("%s WARNING: %s" COLOR_NORMAL "\n", conn->name, ev->buffer); printf("%s WARNING: %s" COLOR_NORMAL "\n", conn->name, ev->buffer);