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
|
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().
|
||||||
|
|
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
|
* 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;
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue