in netutils/telnetc/telnetc.c [464:645]
static void _negotiate(FAR struct telnet_s *telnet, unsigned char telopt)
{
union telnet_event_u ev;
struct telnet_rfc1143_s q;
/* In PROXY mode, just pass it through and do nothing */
if (telnet->flags & TELNET_FLAG_PROXY)
{
switch ((int)telnet->state)
{
case TELNET_STATE_WILL:
NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
break;
case TELNET_STATE_WONT:
NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
break;
case TELNET_STATE_DO:
NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
break;
case TELNET_STATE_DONT:
NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
break;
}
return;
}
/* Lookup the current state of the option */
q = _get_rfc1143(telnet, telopt);
/* Start processing... */
switch ((int)telnet->state)
{
/* Request to enable option on remote end or confirm DO */
case TELNET_STATE_WILL:
switch (Q_HIM(q))
{
case Q_NO:
if (_check_telopt(telnet, telopt, 0))
{
_set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
_send_negotiate(telnet, TELNET_DO, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
}
else
_send_negotiate(telnet, TELNET_DONT, telopt);
break;
case Q_WANTNO:
_set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
_error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
"DONT answered by WILL");
break;
case Q_WANTNO_OP:
_set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
_error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
"DONT answered by WILL");
break;
case Q_WANTYES:
_set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
break;
case Q_WANTYES_OP:
_set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
_send_negotiate(telnet, TELNET_DONT, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
break;
}
break;
/* Request to disable option on remote end, confirm DONT, reject DO */
case TELNET_STATE_WONT:
switch (Q_HIM(q))
{
case Q_YES:
_set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
_send_negotiate(telnet, TELNET_DONT, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
break;
case Q_WANTNO:
_set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
break;
case Q_WANTNO_OP:
_set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
_send_negotiate(telnet, TELNET_DO, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
break;
case Q_WANTYES:
case Q_WANTYES_OP:
_set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
break;
}
break;
/* Request to enable option on local end or confirm WILL */
case TELNET_STATE_DO:
switch (Q_US(q))
{
case Q_NO:
if (_check_telopt(telnet, telopt, 1))
{
_set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
_send_negotiate(telnet, TELNET_WILL, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
}
else
_send_negotiate(telnet, TELNET_WONT, telopt);
break;
case Q_WANTNO:
_set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
_error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
"WONT answered by DO");
break;
case Q_WANTNO_OP:
_set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
_error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
"WONT answered by DO");
break;
case Q_WANTYES:
_set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
break;
case Q_WANTYES_OP:
_set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
_send_negotiate(telnet, TELNET_WONT, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
break;
}
break;
/* Request to disable option on local end, confirm WONT, reject WILL */
case TELNET_STATE_DONT:
switch (Q_US(q))
{
case Q_YES:
_set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
_send_negotiate(telnet, TELNET_WONT, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
break;
case Q_WANTNO:
_set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
break;
case Q_WANTNO_OP:
_set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
_send_negotiate(telnet, TELNET_WILL, telopt);
NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
break;
case Q_WANTYES:
case Q_WANTYES_OP:
_set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
break;
}
break;
}
}