我需要/想要在我正在编码的 MUD 客户端中实现一个符合RFC1143 的Telnet 子选项协商系统,但我很难将第 7 节中的方法转换为可用的 C/C++ 代码。正如文本所建议的一种方法,我有两个六状态枚举 - 我明白,鉴于选择的位模式,当且仅当以下TelnetQStateFlag情况下state,一个选项被认为是活动的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;
Run Code Online (Sandbox Code Playgroud)
默认/设计/魔法所有选项都将默认为 ,QStateNo但我可以看到我应该在初始化时设置我端准备通过设置处理的那些(size_t变量的特定值optionIndex)mMyOptions[optionIndex] = QStateWantYes以及类似的我们准备好的接受他作为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.
Run Code Online (Sandbox Code Playgroud)
2017 年 7 月 26 日更新:让我有点困惑的一个方面是当他启用了一个选项(处于 YES 状态)并且我们希望他禁用它时 - 根据这一点,我们设置了他的状态记录到 WANTNO {并向他发送 DONT 命令} - 但这已经将我们的状态记录从 YES状态移开,并且指南建议该选项现在被视为禁用,即使我们还没有 WONT 来确认它- 公平地说,他必须接受它,因为与 vanilla NVT 相对应的禁用状态要求 - 但它肯定不会在我们得到确认之前生效?