⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raw.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 2 页
字号:
/* raw.c
 * Copyright (c) 1997 David Cole
 *
 * Strip off and process raw protocol from session
 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "utils.h"
#define TELNET_STRINGS
#include "protocol.h"
#include "emul.h"
#include "connect.h"
#include "socket.h"
#include "term.h"
#include "raw.h"
#include "log.h"

/* Describe the different protocol types we can use on the connection.
 * The order of the entries in this array is important - the index of
 * array must match the RawProtocol enum defined in raw.h
 */
struct Protocols protocols[] = {
    { "telnet", 23, protoTelnet },
    { "login", 513, protoRlogin },
    { "none", -1, protoNone }
};
unsigned int numProtocols = 3;

static BOOL inCommand;		/* are we reading a telnet command? */
static unsigned char cmdBuff[40]; /* build up telnet command */
static int cmdUpto;		/* next available character in cmdBuff */
static BOOL ignoreTextUntilDM;	/* processing TELNET Synch */

static RawProtocol rawProtocol;	/* which protocol are we using? */

static BOOL startSession;	/* we have just started a new telnet
				 * session */

static BOOL dontNAWS;		/* do not send NAWS any more */
static BOOL doneNAWS;		/* have done NAWS exchange */
static BOOL doneSGA;		/* have done the SGA exchange */
static BOOL doneLFLOW;		/* have done the LFLOW exchange */

static BOOL enableBINARY;	/* binary mode negotiation is disabled
				 * by default */
static BOOL doneBINARY;		/* have done the BINARY exchange */
static BOOL inBINARY;		/* are we in binary mode? */

static BOOL compressResize;	/* wait until user has finished
				 * resizing before sending new size to
				 * server? */
static BOOL needResize;		/* is a user resize queued? */

static TelnetLocalOption toXdisploc; /* XDISPLOC telnet option */
static BOOL fDoSgaSent;         /* TRUE if I've already sent DO SGA */

/* Enable telnet BINARY mode negotiation
 */
void rawEnableBinaryMode()
{
    enableBINARY = TRUE;
}

/* Return whether or not we are in telnet BINARY mode
 */
BOOL rawInBinaryMode()
{
    return inBINARY;
}

/* From rfc1258.  As soon as the connection is established, we send a
 * message of the form:
 *  <null>
 *  client-user-name<null>
 *  server-user-name<null>
 *  terminal-type/speed<null>
 */
static void rawRloginStart(void)
{
    char msg[64];	/* build message here */
    int idx;			/* current position in msg */
    char* userName = connectGetUser(); /* user to client/server user-name */
    char* term = connectGetTerm(); /* terminal type */
    char* str;			/* copy strings into msg */
    int p2offset;		/* index of parameter-2 (server-user-name) */
    int p3offset;		/* index of parameter-3 */

    /* Copy in initial null
     */
    msg[0] = 0;
    /* Copy in client-user-name + null
     */
    for (idx = 1, str = userName; *str; ++idx, ++str)
	msg[idx] = *str;
    msg[idx++] = '\0';
    /* Copy in server-user-name + null
     */
    p2offset = idx;
    for (str = userName; *str; ++idx, ++str)
	msg[idx] = *str;
    msg[idx++] = '\0';
    /* Copy in terminal-type
     */
    p3offset = idx;
    for (str = term; *str; ++idx, ++str)
	msg[idx] = *str;
    /* Copy in /speed (fixed at 9600) + null
     */
    for (str = "/9600"; *str; ++idx, ++str)
	msg[idx] = *str;
    msg[idx++] = '\0';

    /* Send message to remote end and log protocol
     */
    socketWrite(msg, idx);
    logProtocol("send \\0 %s\\0 %s\\0 %s\\0\n",
		msg + 1, msg + p2offset, msg + p3offset);
}

static char* telcmd(unsigned char cmd)
{
    static char buff[16];

    if (TELCMD_OK(cmd))
	return TELCMD(cmd);
    sprintf(buff, "0x%02x", cmd);
    return buff;
}

static char* telopt(unsigned char opt)
{
    static char buff[16];

    if (TELOPT_OK(opt))
	return TELOPT(opt);
    sprintf(buff, "0x%02x", opt);
    return buff;
}

/* Send a telnet command to the server
 *
 * Args:
 * cmd - the telnet command to send
 * opt - option to send with the comand
 */
void rawCmd(unsigned char cmd, unsigned char opt)
{
    char msg[3];	/* format command */

    /* Build command, send and log it
     */
    msg[0] = (char)IAC;
    msg[1] = (char)cmd;
    msg[2] = (char)opt;
    socketWrite(msg, sizeof(msg));
    logProtocol("send %s %s\n", telcmd(cmd), telopt(opt));
}

/* Make sure we ask the telnet server about options that it did not
 * ask us about.
 */
static void rawTelnetStart(void)
{
    logProtocol("Client initiated options\n");
    ignoreTextUntilDM = FALSE;
    if (!doneNAWS) {
	/* Server did not ask us about NAWS, tell it we will NAWS
	 */
	rawCmd(WILL, TELOPT_NAWS);
	doneNAWS = TRUE;
    }
    if (!doneLFLOW) {
	/* Server did not ask us about LFLOW, tell it we will LFLOW
	 */
	rawCmd(WILL, TELOPT_LFLOW);
	socketSetLocalFlowControl(TRUE);
    }
    if (!doneSGA) {
	/* Tell the server not to send us GA commands.
	 *   TCP/IP Illustrated Volume 1 pg. 407
	 */
	rawCmd(DO, TELOPT_SGA);
	fDoSgaSent = TRUE;
    }

    /* Do not perform binary mode negotiation unless told to
     */
    if (enableBINARY && !doneBINARY) {
	rawCmd(DO, TELOPT_BINARY);
	doneBINARY = TRUE;
    }
    if (socketHaveXServer ()) {
	rawCmd(WILL, TELOPT_XDISPLOC);
	toXdisploc = toIWPending;
    } else {
	toXdisploc = toIDontWant;
    }
}

/* Perform initialisation for session on new connection
 */
void rawStartSession()
{
    /* Clear telnet state
     */
    cmdUpto = 0;
    dontNAWS = TRUE;
    doneNAWS = doneSGA = doneLFLOW = doneBINARY = FALSE;
    fDoSgaSent = FALSE;

    /* Flag that we have just started a new session
     */
    startSession = TRUE;
    /* Flag that we are not in BINARY mode
     */
    inBINARY = FALSE;

    if (rawProtocol == protoRlogin)
	/* When doing rlogin, we have to get the ball rolling
	 */
	rawRloginStart();
    else if (rawProtocol == protoTelnet)
	rawTelnetStart();
}

/* User has started resizing the window
 */
void rawResizeBegin()
{
    compressResize = TRUE;
}

/* User just finished resizing the window
 */
void rawResizeEnd()
{
    compressResize = FALSE;
    if (needResize)
	rawSetWindowSize();
}

/* Tell the telnet/rlogin server what our window size is
 */
void rawSetWindowSize()
{
    char msg[12];	/* format message */

    if (dontNAWS)
	/* If the server does not want to receive window size
	 * messages, do not send message
	 */
	return;

    if (compressResize) {
	needResize = TRUE;
	return;
    } else
	needResize = FALSE;

    termCheckSizeLimits();	// Khader

    switch (rawProtocol) {
    case protoTelnet:
	/* Build telnet message for communicating window size
	 */
	msg[0] = (char)IAC;
	msg[1] = (char)SB;
	msg[2] = (char)TELOPT_NAWS;
	msg[3] = (char)(term.winSize.cx >> 8);
	msg[4] = (char)(term.winSize.cx % 0xff);
	msg[5] = (char)(term.winSize.cy >> 8);
	msg[6] = (char)(term.winSize.cy % 0xff);
	msg[7] = (char)IAC;
	msg[8] = (char)SE;
	/* Send and log message
	 */
	socketWrite(msg, 9);
	logProtocol("send SB NAWS %d %d IAC SE\n",
		    term.winSize.cx, term.winSize.cy);
	break;

    case protoRlogin:
	/* Build rlogin message for communicating window size
	 */
	msg[0] = (char)0xff;
	msg[1] = (char)0xff;
	msg[2] = 's';
	msg[3] = 's';
	msg[4] = (char)(term.winSize.cy >> 8);
	msg[5] = (char)(term.winSize.cy % 0xff);
	msg[6] = (char)(term.winSize.cx >> 8);
	msg[7] = (char)(term.winSize.cx % 0xff);
	msg[8] = msg[4];
	msg[9] = msg[5];
	msg[10] = msg[6];
	msg[11] = msg[7];

	/* Send and log message
	 */
	socketWrite(msg, 12);
	logProtocol("send 0xff 0xff ss %d %d %d %d\n",
		    term.winSize.cy, term.winSize.cx,
		    term.winSize.cy, term.winSize.cx);
	break;
    }
}

/* Tell the telnet server what terminal we are using
 */
void rawSetTerm(void)
{
    unsigned char msg[20];	/* build message */
    int idx;			/* current position in message */
    char* term = connectGetTerm(); /* current terminal type */

    if (!socketConnected())
	/* Do not send message if not connected
	 */
	return;

    /* Build message
     */
    msg[0] = IAC;
    msg[1] = SB;
    msg[2] = TELOPT_TTYPE;
    msg[3] = 0;
    for (idx = 4; *term; ++idx, ++term)
	msg[idx] = (unsigned char)toupper(*term);
    msg[idx++] = IAC;
    msg[idx++] = SE;

    /* Send and log message
     */
    socketWrite((char*)msg, idx);
    logProtocol("send SB TTYPE IS %.*s IAC SE\n", idx - 6, msg + 4);
}

/* Add a character to the current command and try to process it.
 * Return whether or not to remain in command mode.
 *
 * Args:
 * ch - character to add to command
 */
static BOOL parseTelnetCommand(unsigned char ch)
{
    unsigned char cmd;		/* extract telnet command */
    unsigned char opt;		/* extract command option */
    char msg [300], display[200];
    int msglen;

    /* First copy the character into the command buffer
     */
    if (cmdUpto == sizeof(cmdBuff)) {
	logProtocol("TELNET Command buffer overflow\n");
	cmdUpto = 0;
	return FALSE;
    }

    cmdBuff[cmdUpto++] = ch;
    if (cmdUpto == 1)
	return TRUE;		/* Minimum command length is 2 */

    /* Get command
     */
    cmd = cmdBuff[1];
    switch (cmd) {
    case IAC:
	/* Command was escaped IAC (255) data byte
	 */
	emulAddText(cmdBuff, 1, FALSE);
	cmdUpto = 0;
	return FALSE;		/* Not in command any more */

    case DO:			/* server telling us to do something */
    case DONT:			/* server telling us not to do something */
    case WILL:			/* server telling us it will do something */
    case WONT:			/* server telling us it won't do something */
	if (cmdUpto < 3)
	    return TRUE;	/* Options require 3 bytes */

	/* Get command option
	 */
	opt = cmdBuff[2];
	logProtocol("recv %s %s\n", telcmd(cmd), telopt(opt));

	switch (opt) {
	case TELOPT_BINARY:
	    /* Code added 11/25/98, patrick@narkinsky.ml.org
	     */
	    switch (cmd) {
	    case DO:
		/* Server has asked us to send BINARY
		 */
		if (enableBINARY) {
		    rawCmd(WILL, TELOPT_BINARY);
		    inBINARY = TRUE;
		} else
		    rawCmd(WONT, TELOPT_BINARY);
		break;
	    case DONT:
		/* Server told us not to BINARY, tell it we WONT
		 */
		rawCmd(WONT, TELOPT_BINARY);
		inBINARY = FALSE;
		break;
	    case WILL:
		/* Server has told us it will send BINARY
		 */
		if (enableBINARY) {
		    rawCmd(DO, TELOPT_BINARY);
		    inBINARY = TRUE;
		} else
		    rawCmd(DONT, TELOPT_BINARY);
		break;
	    case WONT:
		/* Server has told us it WONT BINARY, tell it not to
		 */
		rawCmd(DONT, TELOPT_BINARY);
		inBINARY = FALSE;
		break;
	    }
	    if (enableBINARY)
		doneBINARY = TRUE;
	    break;

	case TELOPT_NAWS:
	    switch (cmd) {
	    case DO:
		/* Server has asked us to NAWS
		 */
		dontNAWS = FALSE;
		if (!doneNAWS)
		    rawCmd(WILL, TELOPT_NAWS);
		rawSetWindowSize();
		break;
	    case DONT:
		/* Server has told us not to NAWS
		 */
		dontNAWS = TRUE;
		break;
	    }
	    doneNAWS = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -