81 lines
2.4 KiB
Plaintext
81 lines
2.4 KiB
Plaintext
|
|
||
|
Three pieces of state need to be kept for each side of each option.
|
||
|
(You need the localside, sending WILL/WONT & receiving DO/DONT, and
|
||
|
the remoteside, sending DO/DONT and receiving WILL/WONT)
|
||
|
|
||
|
MY_STATE: What state am I in?
|
||
|
WANT_STATE: What state do I want?
|
||
|
WANT_RESP: How many requests have I initiated?
|
||
|
|
||
|
Default values:
|
||
|
MY_STATE = WANT_STATE = DONT
|
||
|
WANT_RESP = 0
|
||
|
|
||
|
The local setup will change based on the state of the Telnet
|
||
|
variables. When we are the originator, we can either make the
|
||
|
local setup changes at option request time (in which case if
|
||
|
the option is denied we need to change things back) or when
|
||
|
the option is acknowledged.
|
||
|
|
||
|
To initiate a switch to NEW_STATE:
|
||
|
|
||
|
if ((WANT_RESP == 0 && NEW_STATE == MY_STATE) ||
|
||
|
WANT_STATE == NEW_STATE) {
|
||
|
do nothing;
|
||
|
} else {
|
||
|
/*
|
||
|
* This is where the logic goes to change the local setup
|
||
|
* if we are doing so at request initiation
|
||
|
*/
|
||
|
WANT_STATE = NEW_STATE;
|
||
|
send NEW_STATE;
|
||
|
WANT_RESP += 1;
|
||
|
}
|
||
|
|
||
|
When receiving NEW_STATE:
|
||
|
|
||
|
if (WANT_RESP) {
|
||
|
--WANT_RESP;
|
||
|
if (WANT_RESP && (NEW_STATE == MY_STATE))
|
||
|
--WANT_RESP;
|
||
|
}
|
||
|
if (WANT_RESP == 0) {
|
||
|
if (NEW_STATE != WANT_STATE) {
|
||
|
/*
|
||
|
* This is where the logic goes to decide if it is ok
|
||
|
* to switch to NEW_STATE, and if so, do any necessary
|
||
|
* local setup changes.
|
||
|
*/
|
||
|
if (ok_to_switch_to NEW_STATE)
|
||
|
WANT_STATE = NEW_STATE;
|
||
|
else
|
||
|
WANT_RESP++;
|
||
|
* if (MY_STATE != WANT_STATE)
|
||
|
reply with WANT_STATE;
|
||
|
} else {
|
||
|
/*
|
||
|
* This is where the logic goes to change the local setup
|
||
|
* if we are doing so at request acknowledgment
|
||
|
*/
|
||
|
}
|
||
|
}
|
||
|
MY_STATE = NEW_STATE;
|
||
|
|
||
|
* This if() line is not needed, it should be ok to always do the
|
||
|
"reply with WANT_STATE". With the if() line, asking to turn on
|
||
|
an option that the other side doesn't understand is:
|
||
|
Send DO option
|
||
|
Recv WONT option
|
||
|
Without the if() line, it is:
|
||
|
Send DO option
|
||
|
Recv WONT option
|
||
|
Send DONT option
|
||
|
If the other side does not expect to receive the latter case,
|
||
|
but generates the latter case, then there is a potential for
|
||
|
option negotiation loops. An implementation that does not expect
|
||
|
to get the second case should not generate it, an implementation
|
||
|
that does expect to get it may or may not generate it, and things
|
||
|
will still work. Being conservative in what we send, we have the
|
||
|
if() statement in, but we expect the other side to generate the
|
||
|
last response.
|