mirror of https://gerrit.osmocom.org/libtelnet
dont use a separate event for ZMP
This commit is contained in:
parent
53a86613c6
commit
b10946c96d
26
README
26
README
|
@ -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().
|
||||
|
|
52
libtelnet.c
52
libtelnet.c
|
@ -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
|
||||
case TELNET_TELOPT_COMPRESS2:
|
||||
if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) {
|
||||
if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
|
||||
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 */
|
||||
_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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -224,14 +224,33 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
|
|||
break;
|
||||
/* 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,
|
||||
get_opt(ev->telopt));
|
||||
if (ev->size > 0) {
|
||||
printf(" [%zi]: ", ev->size);
|
||||
printf(" [%zi bytes]: ", ev->size);
|
||||
print_buffer(ev->buffer, ev->size);
|
||||
}
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue