Telnet Q State Option Logic RFC1143示例代码 - 解释

时间:2017-07-12 19:04:15

标签: c++ c telnet

我需要/想要在我正在编码的MUD客户端中实现符合RFC1143的Telnet子选项协商系统,但是我很难将Section 7中的方法转换为可行的C / C ++代码。正如文本建议的那样,我有两个六个状态枚举 - 我理解,如果选择了位模式,当{和1}} TelnetQStateFlag实例state实例时,选项被认为是活动的1}},state == QStateYes

    enum TelnetQStateFlag {
                                      // +-----If set then we have a queued
                                      // |     request for the opposite state
                                      // |+----If set then we want the opposite
                                      // ||+---Must be only one set for option
                                      // |||   to be active
                      QStateNo = 0x0, // 000 - No
                  QStateWantNo = 0x2, // 010 - Want No and we/he do not want to change to Yes
                 QStateWantYes = 0x3, // 011 - Want Yes and we/he do not want to change to No
                     QStateYes = 0x1, // 001 - Yes
    QStateWantYesQueueOpposite = 0x7, // 111 - Yes but we/he wants to change to no
     QStateWantNoQueueOpposite = 0x6  // 110 - No but we/he wants to change to yes
    };

    TelnetQStateFlag[256] mMyOptions;
    TelnetQStateFlag[256] mHisOptions;

默认情况下/ design / magic所有选项都默认为QStateNo但我可以看到我应该在初始化时设置一个(size_t变量optionIndex的具体值)我的结局准备好通过设置mMyOptions[optionIndex] = QStateWantYes以及我们准备从HIM接受的mHisOptions[optionIndex] = QStateWantYes来处理。

有人可以通过 - 慢慢地 - 告诉我如何处理来自一方的请求以协商控制另一端的选项 - 对于另一端将不接受的情况一个选项;以及如何在重叠的情况下对两个方向起作用?

我已经完成并从提到的RFC开始我编辑它以表达六态的转换:

There are two sides, we (us) and he (him).  Originally RFC1143 kept two
sets of two variables:

us:      state of option on our side (NO/WANTNO/WANTYES/YES)  
usq:     a queue bit (EMPTY/OPPOSITE) if us is WANTNO or WANTYES  

him:     state of option on his side  
himq:    a queue bit if him is WANTNO or WANTYES  

An option is enabled if and only if its state is YES.

Note that below us/usq and him/himq has been combined into two six-choice
states:    

∙ NO              default (starting) state
∙ WANTYES         no pending request for this option to be enabled
∙ WANTYESQUEUEDNO already requested for this option to be enabled  
∙ WANTNO          no pending request for this option to be disabled  
∙ WANTNOQUEUEDYES already requested for this option to be disabled  
∙ YES             state is enabled - ONLY state in which option is ACTIVE

"ERROR" below means that producing diagnostic information may be a good idea,
though it isn't required.

Upon receipt of WILL(for his state){DO(for our state)}, we choose based upon
him{us} state:

∘ NO (if we agree)        ==> YES and send DO{WILL}
∘ NO (if we do not agree) ==> NOCHANGE but still send DONT{WONT}
∘ YES                     ==> NOCHANGE
∘ WANTNO                  ==> NO; ERROR: DONT{WONT} answered by WILL{DO}
∘ WANTNOQUEUEDYES         ==> WANTYES; ERROR: DONT{WONT} answered by WILL{DO}†
∘ WANTYES                 ==> YES
∘ WANTYESQUEUEDNO         ==> WANTNO and send DONT{WONT}

† This behaviour is debatable; DONT{WONT} will never be answered by WILL{DO}
over a reliable connection between TELNETs compliant with this RFC, so this
was chosen:
  1. not to generate further messages, because if we know we're dealing with
     a non-compliant TELNET we shouldn't trust it to be sensible;
  2. to empty the queue sensibly.

Upon receipt of WONT{DONT}, we choose based upon him{us} state:
∙ NO                      ==> NOCHANGE
∙ YES                     ==> NO and send DONT{WONT}
∙ WANTNO                  ==> NO
∙ WANTNOQUEUEDYES         ==> WANTYES and send DO{WILL}
∙ WANTYES                 ==> NO ‡
∙ WANTYESQUEUEDNO         ==> NO ※

‡ Here is the only spot a length-two queue could be useful; after a WILL{DO}
negotiation was refused, a queue of WONT{DONT} WILL{DO} would mean to request
the option again. This seems of too little utility and too much potential
waste; there is little chance that the other side will change its mind
immediately.

※ Here we don't have to generate another request because we've{he's} been
"refused into" the correct state anyway.

If we decide to ask him to enable {we want to enable ourself}:
∘ NO              ==> WANTYES and send DO{WILL}
∘ YES             ==> NOCHANGE; ERROR: already enabled
∘ WANTNO          ==> WANTNOQUEUEDYES
∘ WANTNOQUEUEDYES ==> NOCHANGE; ERROR: cannot initiate new request in the
                      middle of negotiation.
∘ WANTYES         ==> NOCHANGE; ERROR: already negotiating for enable
∘ WANTYESQUEUEDNO ==> WANTYES

If we decide to ask him to disable {we want to disable ourself}:
∙ NO              ==> NOCHANGE; ERROR: already disabled
∙ YES             ==> WANTNO and send DONT{WONT}
∙ WANTNO          ==> NOCHANGE; error: already negotiating for disable
∙ WANTNOQUEUEDYES ==> WANTNO
∙ WANTYES         ==> WANTYESQUEUEDNO
∙ WANTYESQUEUEDNO ==> NOCHANGE; error: already queued a disable request
                      and must not initiate new request in the middle of
                      negotiation

We handle the option on our side by the same procedures, with DO<->WILL,
DONT<->WONT, him<->us swapped as shown above.

更新2017/07/26: 一个让我感到困惑的方面是,当他有一个选项被启用(处于YES状态)并且我们希望他禁用它时 - 根据这个我们将他的状态记录设置为WANTNO {并将他发送给他DONT命令} - 但是这已经将状态的记录从YES状态移开了,指南建议现在将该选项视为禁用,即使我们没有还有一个WONT确认它 - 公平,他必须接受它,因为对应于香草NVT的禁用状态要求 - 但是在我们得到确认之前它肯定不会生效吗?

0 个答案:

没有答案