📄 raw.c
字号:
break;
case TELOPT_ECHO:
switch (cmd) {
case DO: /* Server has told us to ECHO - reject */
/* Note: netkit-telnetd sends "DO ECHO" */
/* just to detect broken clients */
/* but we are not (so) broken */
rawCmd(WONT, TELOPT_ECHO);
break;
case DONT:
/* Server told us not to ECHO - ignore */
break;
case WILL:
/* Server told us it WILL ECHO, tell it to ECHO */
rawCmd(DO, TELOPT_ECHO);
emulSetEcho(FALSE);
break;
case WONT:
/* Server has told us it WONT ECHO, tell it not to */
rawCmd(DONT, TELOPT_ECHO);
emulSetEcho(TRUE);
break;
}
break;
case TELOPT_SGA:
switch (cmd) {
case DO:
/* Server told us to SGA, tell it we WILL SGA
*/
rawCmd(WILL, TELOPT_SGA);
break;
case WILL:
/* Server told us it WILL SGA, tell it to SGA
*/
if (!fDoSgaSent) {
rawCmd(DO, TELOPT_SGA);
fDoSgaSent = TRUE;
}
break;
}
doneSGA = TRUE;
break;
case TELOPT_TTYPE:
switch (cmd) {
case DO:
/* Server told us to TTYPE, tell it we WILL TTYPE
*/
rawCmd(WILL, TELOPT_TTYPE);
break;
}
break;
case TELOPT_LFLOW:
switch (cmd) {
case DO:
/* Server told us DO LFLOW, tell it we will LFLOW
*/
if (!socketLocalFlowControl()) {
rawCmd(WILL, TELOPT_LFLOW);
socketSetLocalFlowControl(TRUE);
}
break;
case DONT:
/* Server told us not to LFLOW, tell it we WONT LFLOW
*/
rawCmd(WONT, TELOPT_LFLOW);
socketSetLocalFlowControl(FALSE);
break;
}
doneLFLOW = TRUE;
break;
case TELOPT_XDISPLOC:
switch (cmd) {
case WILL: /* Server should never send me his DISPLAY ! */
rawCmd(DONT, TELOPT_XDISPLOC);
break;
case WONT: /* No reply required */
break;
case DO:
case DONT:
rawTLOMachine (TELOPT_XDISPLOC, &toXdisploc, cmd);
break;
}
break;
default:
switch (cmd) {
case DO:
case DONT:
/* For all other commands, say we WONT do them
*/
rawCmd(WONT, opt);
break;
case WILL:
case WONT:
/* For all other commands tell the server not to do them
*/
rawCmd(DONT, opt);
break;
}
break;
}
cmdUpto = 0;
return FALSE; /* Not in command any more */
case SB:
/* Server wants to negotiate something we agreed to do
*/
if (cmdUpto < 3)
return TRUE;
opt = cmdBuff[2];
switch (opt) {
case TELOPT_TTYPE:
/* IAC SB TERMINAL-TYPE SEND IAC SE
* Server wants us to send our terminal type
*/
if (cmdUpto < 6)
return TRUE;
if (cmdBuff[3] == 1 && cmdBuff[4] == IAC && cmdBuff[5] == SE) {
logProtocol("recv SB TERMINAL-TYPE SEND IAC SE\n");
rawSetTerm();
}
break;
case TELOPT_LFLOW:
/* IAC SB TOGGLE-FLOW-CONTROL ? IAC SE
* Server is telling us to modify local flow control
*/
if (cmdUpto < 6 || cmdBuff[cmdUpto - 1] != SE)
return TRUE;
switch (cmdBuff[3]) {
case LFLOW_OFF:
socketSetLocalFlowControl(FALSE);
logProtocol("recv SB LFLOW OFF IAC SE\n");
break;
case LFLOW_ON:
socketSetLocalFlowControl(TRUE);
logProtocol("recv SB LFLOW ON IAC SE\n");
break;
case LFLOW_RESTART_ANY:
emulLocalFlowAny(TRUE);
logProtocol("recv SB LFLOW RESTART-ANY IAC SE\n");
break;
case LFLOW_RESTART_XON:
emulLocalFlowAny(FALSE);
logProtocol("recv SB LFLOW RESTART-XON IAC SE\n");
break;
}
case TELOPT_XDISPLOC:
if (cmdUpto < 6 || cmdBuff[cmdUpto - 1] != SE)
return TRUE;
if (cmdBuff[3] == TELNET_SEND &&
cmdBuff[4] == IAC &&
cmdBuff[5] == SE) {
logProtocol("recv SB XDISPLOC SEND IAC SE\n");
sprintf (display, "%s:0", socketGetLocalIP());
msglen = sprintf (msg, "%c%c%c%c%s%c%c",
IAC, SB, TELOPT_XDISPLOC, 0,
display, IAC, SE);
socketWrite(msg, msglen);
logProtocol("send SB XDISPLOC IS %s IAC SE\n",
display);
}
}
cmdUpto = 0;
return FALSE; /* Not in command any more */
case DM: /* Data mark--for connect. cleaning */
case GA: /* You may reverse the line */
case EL: /* Erase the current line */
case EC: /* Erase the current character */
case BRK: /* Break */
case NOP: /* NOP */
case AYT: /* Are you there */
case AO: /* Abort output--but let prog finish */
case IP: /* Interrupt process--permanently */
case SE: /* End sub negotiation */
cmdUpto = 0;
return FALSE; /* Not in command any more */
}
return TRUE;
}
/* Set the protocol to interpret in the session
*
* Args:
* proto - the protocol to interpret
*/
void rawEnableProtocol(RawProtocol proto)
{
rawProtocol = proto;
switch (proto) {
case protoNone:
/* When not doing any protocol, echo all characters
*/
emulSetEcho(TRUE);
logProtocol("no protocol\n");
break;
case protoTelnet:
/* When doing telnet, start by not echoing characters
*/
emulSetEcho(TRUE); /* Changed to TRUE by LZS on 2001.04.02 */
logProtocol("telnet protocol enabled\n");
break;
case protoRlogin:
/* When doing rlogin, start by not echoing characters
*/
emulSetEcho(FALSE);
logProtocol("rlogin protocol enabled\n");
break;
}
}
/* Return the protocol that we are interpreting
*/
RawProtocol rawGetProtocol()
{
return rawProtocol;
}
/* Interpret some data from the telnet server
*
* Args:
* text - the text received from the server
* len - the amount of text received
*/
static int rawProcessTelnet(unsigned char* text, int len)
{
int numChars = 0; /* number of consecutive session
* characters found */
int idx; /* iterate over text */
ASSERT(text != NULL);
ASSERT(len > 0);
if (startSession) {
/* This is the first data received from the telnet server
*/
logProtocol("Server initiated options\n");
startSession = FALSE;
}
/* Process the text received
*/
for (idx = 0; idx < len; idx++) {
if (inCommand) {
/* If we are in a command, process the command one
* character at a time.
*/
inCommand = parseTelnetCommand(text[idx]);
} else {
/* Scan over text until we hit a command
*/
if (text[idx] != IAC) {
/* Normal text, just count it for now
*/
if (ignoreTextUntilDM && text[idx] == DM) {
/* Server has told us to ignore text until we see DM
*/
ignoreTextUntilDM = FALSE;
numChars = 0;
} else
numChars++;
} else {
/* Some kind of command
*/
if (numChars > 0) {
/* If we scanned any text, pass this text to the
* text receive processing.
*/
if (!ignoreTextUntilDM)
emulAddText(text + idx - numChars, numChars, FALSE);
numChars = 0;
}
/* Pass the IAC into the command parser
*/
inCommand = parseTelnetCommand(text[idx]);
}
}
}
if (numChars > 0 && !ignoreTextUntilDM)
/* We finished the loop with scanned text, pass this text to
* the text receive processing.
*/
emulAddText(text + idx - numChars, numChars, FALSE);
return len;
}
/* Interpret some data from the rlogin server
*
* Args:
* text - text received from the server
* len - the amount of text received
*/
static int rawProcessRlogin(unsigned char* text, int len)
{
int idx = 0; /* index to process from */
ASSERT(text != NULL);
ASSERT(len > 0);
if (startSession) {
/* The server might send a nul as the very first character,
* skip over it
*/
if (*text == '\0')
idx = 1;
startSession = FALSE;
}
/* Send the rest of the text to the terminal emulator
*/
if (idx < len)
emulAddText(text + idx, len - idx, FALSE);
return len;
}
/* Process some data received from the server
*
* Args:
* text - text received from the server
* len - amount of text received
*/
int rawProcessData(unsigned char* text, int len)
{
ASSERT(text != NULL);
ASSERT(len > 0);
switch (rawProtocol) {
case protoNone:
/* No protocol - send text directly to terminal
*/
emulAddText(text, len, FALSE);
return len;
case protoTelnet:
return rawProcessTelnet(text, len);
case protoRlogin:
return rawProcessRlogin(text, len);
}
/* Just in case...
*/
return len;
}
/* Process some out-of-band data from the server
*
* Args:
* text - text received from server
* len - length of text received
*/
void rawProcessOob(unsigned char* text, int len)
{
#if 0
/* Display the text via OutputDebugString
*/
int idx;
ods("OOB:\n");
for (idx = 0; idx < len; idx += 16) {
int off;
for (off = 0; idx + off < len && off < 16; ++off)
ods("%02x ", text[idx + off]);
while (off++ < 16)
ods(" ");
for (off = 0; idx + off < len && off < 16; ++off)
if (isprint(text[idx + off]))
ods("%c", text[idx + off]);
else
ods(".");
ods("\n");
}
#endif
ASSERT(text != NULL);
ASSERT(len > 0);
switch (rawProtocol) {
case protoTelnet:
switch (*text) {
case 0xff:
logProtocol("recv TELNET Synch\n");
ignoreTextUntilDM = TRUE;
break;
}
break;
case protoRlogin:
switch (*text) {
case 0x02: /* discard buffered data from server */
break;
case 0x10: /* raw mode - send ^S/^Q to server */
socketSetLocalFlowControl(FALSE);
break;
case 0x20: /* handle ^S/^Q locally */
socketSetLocalFlowControl(TRUE);
break;
case 0x80:
dontNAWS = FALSE;
rawSetWindowSize();
break;
}
break;
}
}
/* Find the protocol appropriate for the specified port
*/
RawProtocol findPortProtocol(char* portName)
{
int idx;
for (idx = 0; idx < numElem(protocols); idx++)
if (stricmp(portName, protocols[idx].name) == 0
|| atoi(portName) == protocols[idx].port)
return protocols[idx].proto;
return protoNone;
}
void rawTLOMachine (unsigned char option, TelnetLocalOption *state,
int input /* DO or DONT */)
{
if (*state==toIDontWant) { /* never change this state */
if (input==DO) {
rawCmd (WONT, option);
}
} else if (input==DO) {
if (*state == toIWDisabled) {
rawCmd (WILL, option);
}
*state = toIWEnabled;
} else { /* input==DONT */
if (*state == toIWEnabled) {
rawCmd (WONT, option);
}
*state = toIWDisabled;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -