Telnet.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:7k
源码类别:

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: Telnet.cs,v 1.2 2005/04/20 08:45:47 okajima Exp $
  4. */
  5. using System;
  6. using System.IO;
  7. using System.Text;
  8. using System.Collections;
  9. using System.Diagnostics;
  10. using Poderosa.Toolkit;
  11. using Poderosa.Terminal;
  12. using Poderosa.ConnectionParam;
  13. namespace Poderosa.Communication
  14. {
  15. /// <summary>
  16. /// TelnetOption偺憲庴怣傪偡傞丅偁傑傝暋嶨側僒億乕僩傪偡傞偮傕傝偼側偄丅
  17. /// Guevara偱昁梫側偺偼SuppressGoAhead(憃曽岦), TerminalType, NAWS偺俁偮偩偗偱丄偙傟傜偑惉棫偟側偗傟偽椺奜傪搳偘傞丅
  18. /// 偦傟埲奜偺TelnetOption偼嫅斲偡傞偑丄嫅斲偑惉棫偟側偔偰傕_refusedOption偵奿擺偡傞偩偗偱僄儔乕偵偼偟側偄丅
  19. /// 僆僾僔儑儞偺僱僑僔僄乕僔儑儞偑廔椆偟偨傜丄嵟屻偵庴怣偟偨僷働僢僩偼傕偆僔僃儖杮懱偱偁傞偺偱丄屇傃弌偟懁偼偙傟傪巊偆傛偆偵偟側偄偲偄偗側偄丅
  20. /// </summary>
  21. internal class TelnetNegotiator
  22. {
  23. //昁梫側傜偙偙偐傜忣曬傪撉傓
  24. private TerminalParam _param;
  25. private int _width;
  26. private int _height;
  27. private TelnetCode _state;
  28. private MemoryStream _sequenceBuffer;
  29. private TelnetOptionWriter _optionWriter;
  30. private bool _defaultOptionSent;
  31. internal enum ProcessResult {
  32. NOP,
  33. REAL_0xFF
  34. }
  35. //愙懕傪拞抐偡傞傎偳偱偼側偄偑婜懸偳偍傝偱側偐偭偨応崌偵寈崘傪弌偡
  36. private ArrayList _warnings;
  37. public ArrayList Warnings {
  38. get {
  39. return _warnings;
  40. }
  41. }
  42. private ArrayList   _refusedOptions;
  43. /*
  44. public TelnetCode[] RefusedOptions {
  45. get {
  46. return (TelnetCode[])_refusedOptions.ToArray(typeof(TelnetCode));
  47. }
  48. }
  49. */
  50. public TelnetNegotiator(TerminalParam param, int width, int height) {
  51. _param = param;
  52. _refusedOptions = new ArrayList();
  53. _width = width;
  54. _height = height;
  55. _warnings = new ArrayList();
  56. _state = TelnetCode.NA;
  57. _sequenceBuffer = new MemoryStream();
  58. _optionWriter = new TelnetOptionWriter();
  59. _defaultOptionSent = false;
  60. }
  61. public void Flush(AbstractGuevaraSocket s) {
  62. if(!_defaultOptionSent) {
  63. WriteDefaultOptions();
  64. _defaultOptionSent = true;
  65. }
  66. if(_optionWriter.Length > 0) {
  67. _optionWriter.WriteTo(s);
  68. s.Flush();
  69. _optionWriter.Clear();
  70. }
  71. }
  72. private void WriteDefaultOptions() {
  73. _optionWriter.Write(TelnetCode.WILL, TelnetOption.TerminalType);
  74. _optionWriter.Write(TelnetCode.DO,   TelnetOption.SuppressGoAhead);
  75. _optionWriter.Write(TelnetCode.WILL, TelnetOption.SuppressGoAhead);
  76. _optionWriter.Write(TelnetCode.WILL, TelnetOption.NAWS);
  77. }
  78. public bool InProcessing {
  79. get {
  80. return _state!=TelnetCode.NA;
  81. }
  82. }
  83. public void StartNegotiate() {
  84. _state = TelnetCode.IAC;
  85. }
  86. public ProcessResult Process(byte data) {
  87. Debug.Assert(_state!=TelnetCode.NA);
  88. switch(_state) {
  89. case TelnetCode.IAC:
  90. if(data==(byte)TelnetCode.SB || ((byte)TelnetCode.WILL<=data && data<=(byte)TelnetCode.DONT))
  91. _state = (TelnetCode)data;
  92. else if(data==(byte)TelnetCode.IAC) {
  93. _state = TelnetCode.NA;
  94. return ProcessResult.REAL_0xFF;
  95. }
  96. else
  97. _state = TelnetCode.NA;
  98. break;
  99. case TelnetCode.SB:
  100. if(data!=(byte)TelnetCode.SE)
  101. _sequenceBuffer.WriteByte(data);
  102. else {
  103. ProcessSequence(_sequenceBuffer.ToArray());
  104. _state = TelnetCode.NA;
  105. _sequenceBuffer.SetLength(0);
  106. }
  107. break;
  108. case TelnetCode.DO:
  109. case TelnetCode.DONT:
  110. case TelnetCode.WILL:
  111. case TelnetCode.WONT:
  112. ProcessOptionRequest(data);
  113. _state = TelnetCode.NA;
  114. break;
  115. }
  116. return ProcessResult.NOP;
  117. }
  118. private void ProcessSequence(byte[] response) {
  119. if(response[1]==1) {
  120. if(response[0]==(byte)TelnetOption.TerminalType)
  121. _optionWriter.WriteTerminalName(EnumDescAttribute.For(typeof(TerminalType)).GetDescription(_param.TerminalType));
  122. }
  123. }
  124. private void ProcessOptionRequest(byte option_) {
  125. TelnetOption option = (TelnetOption)option_;
  126. switch(option) {
  127. case TelnetOption.TerminalType:
  128. if(_state==TelnetCode.DO)
  129. _optionWriter.Write(TelnetCode.WILL, option);
  130. else
  131. _warnings.Add(GEnv.Strings.GetString("Message.Telnet.FailedToSendTerminalType"));
  132. break;
  133. case TelnetOption.NAWS:
  134. if(_state==TelnetCode.DO)
  135. _optionWriter.WriteTerminalSize(_width, _height);
  136. else
  137. _warnings.Add(GEnv.Strings.GetString("Message.Telnet.FailedToSendWidnowSize"));
  138. break;
  139. case TelnetOption.SuppressGoAhead:
  140. if(_state!=TelnetCode.WILL && _state!=TelnetCode.DO) //!!椉曽偑棃偨偙偲傪妋擣偡傞
  141. _warnings.Add(GEnv.Strings.GetString("Message.Telnet.FailedToSendSuppressGoAhead"));
  142. break;
  143. case TelnetOption.LocalEcho:
  144. if(_state==TelnetCode.DO)
  145. _optionWriter.Write(TelnetCode.WILL, option);
  146. break;
  147. default: //忋婰埲奜偼偡傋偰嫅斲丅DO偵偼WON'T, WILL偵偼DON'T偺墳摎傪曉偡丅 
  148. if(_state==TelnetCode.DO)
  149. _optionWriter.Write(TelnetCode.WONT, option);
  150. else if(_state==TelnetCode.WILL)
  151. _optionWriter.Write(TelnetCode.DONT, option);
  152. break;
  153. }
  154. }
  155. }
  156. internal class TelnetOptionWriter {
  157. private MemoryStream _strm;
  158. public TelnetOptionWriter() {
  159. _strm = new MemoryStream();
  160. }
  161. public long Length {
  162. get {
  163. return _strm.Length;
  164. }
  165. }
  166. public void Clear() {
  167. _strm.SetLength(0);
  168. }
  169. public void WriteTo(AbstractGuevaraSocket target) {
  170. byte[] data = _strm.ToArray();
  171. target.Transmit(data, 0, data.Length);
  172. target.Flush();
  173. }
  174. public void Write(TelnetCode code, TelnetOption opt) {
  175. _strm.WriteByte((byte)TelnetCode.IAC);
  176. _strm.WriteByte((byte)code);
  177. _strm.WriteByte((byte)opt);
  178. }
  179. public void WriteTerminalName(string name) {
  180. _strm.WriteByte((byte)TelnetCode.IAC);
  181. _strm.WriteByte((byte)TelnetCode.SB);
  182. _strm.WriteByte((byte)TelnetOption.TerminalType);
  183. _strm.WriteByte(0); //0 = IS
  184. byte[] t = Encoding.ASCII.GetBytes(name);
  185. _strm.Write(t, 0, t.Length);
  186. _strm.WriteByte((byte)TelnetCode.IAC);
  187. _strm.WriteByte((byte)TelnetCode.SE);
  188. }
  189. public void WriteTerminalSize(int width, int height) {
  190. _strm.WriteByte((byte)TelnetCode.IAC);
  191. _strm.WriteByte((byte)TelnetCode.SB);
  192. _strm.WriteByte((byte)TelnetOption.NAWS);
  193. //暆傗崅偝偑256埲忋偵側傞偙偲偼側偄偩傠偆偐傜偙傟偱摝偘傞
  194. _strm.WriteByte(0);
  195. _strm.WriteByte((byte)width);
  196. _strm.WriteByte(0);
  197. _strm.WriteByte((byte)height);
  198. _strm.WriteByte((byte)TelnetCode.IAC);
  199. _strm.WriteByte((byte)TelnetCode.SE);
  200. }
  201. }
  202. internal enum TelnetCode {
  203. NA = 0,
  204. SE = 240,
  205. NOP = 241,
  206. Break = 243,
  207. AreYouThere = 246,
  208. SB = 250,
  209. WILL = 251,
  210. WONT = 252,
  211. DO = 253,
  212. DONT = 254,
  213. IAC = 255
  214. }
  215. internal enum TelnetOption {
  216. LocalEcho = 1,
  217. SuppressGoAhead = 3,
  218. TerminalType = 24,
  219. NAWS = 31
  220. }
  221. internal class TelnetNegotiationException : ApplicationException {
  222. public TelnetNegotiationException(string msg) : base(msg) {}
  223. }
  224. }