static void _negotiate()

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;
    }
}