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

Telnet服务器

开发平台:

C#

  1. /*
  2.  Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3.  This file is a part of the Granados SSH Client Library that is subject to
  4.  the license included in the distributed package.
  5.  You may not use this file except in compliance with the license.
  6.  $Id: Socket.cs,v 1.2 2005/04/20 08:58:56 okajima Exp $
  7. */
  8. using System;
  9. using System.Text;
  10. using System.IO;
  11. using System.Net.Sockets;
  12. using System.Threading;
  13. using System.Diagnostics;
  14. namespace Granados.SSHC
  15. {
  16. internal enum ReceiverState {
  17. Ready,
  18. Closed,
  19. Error
  20. }
  21. internal interface IHandlerBase {
  22. void OnClosed();
  23. void OnError(Exception error, string msg);
  24. }
  25. internal interface IByteArrayHandler : IHandlerBase {
  26. void OnData(byte[] data, int offset, int length);
  27. }
  28. internal interface IStringHandler : IHandlerBase {
  29. void OnString(string data);
  30. }
  31. internal abstract class SynchronizedHandlerBase {
  32. public virtual void SetClosed() {
  33. _state = ReceiverState.Closed;
  34. _event.Set();
  35. }
  36. public virtual void SetError(string msg) {
  37. _errorMessage = msg;
  38. _state = ReceiverState.Error;
  39. _event.Set();
  40. }
  41. public virtual void SetReady() {
  42. _state = ReceiverState.Ready;
  43. _event.Set();
  44. }
  45. protected ManualResetEvent _event;
  46. protected ReceiverState _state;
  47. protected string _errorMessage;
  48. public WaitHandle WaitHandle {
  49. get {
  50. return _event;
  51. }
  52. }
  53. public ReceiverState State {
  54. get {
  55. return _state;
  56. }
  57. }
  58. public string ErrorMessage {
  59. get {
  60. return _errorMessage;
  61. }
  62. }
  63. public void Wait() {
  64. _event.WaitOne();
  65. _event.Reset();
  66. }
  67. protected SynchronizedHandlerBase() {
  68. _event = new ManualResetEvent(false);
  69. }
  70. }
  71. internal class ProtocolNegotiationHandler : SynchronizedHandlerBase, IByteArrayHandler {
  72. protected string _serverVersion;
  73. protected SSHConnectionParameter _param;
  74. protected string _endOfLine;
  75. public ProtocolNegotiationHandler(SSHConnectionParameter param) {
  76. _param = param;
  77. _errorMessage = Strings.GetString("NotSSHServer");
  78. }
  79. public string ServerVersion {
  80. get {
  81. return _serverVersion;
  82. }
  83. }
  84. public string EOL {
  85. get {
  86. return _endOfLine;
  87. }
  88. }
  89. public void OnData(byte[] buf, int offset, int length) {
  90. try {
  91. //the specification claims the version string ends with CRLF, however some servers send LF only
  92. if(length<=2 || buf[offset+length-1]!=0x0A) throw new SSHException(Strings.GetString("NotSSHServer"));
  93. //Debug.WriteLine(String.Format("receiveServerVersion len={0}",len));
  94. string sv = Encoding.ASCII.GetString(buf, offset, length);
  95. _serverVersion = sv.Trim();
  96. _endOfLine = sv.EndsWith("rn")? "rn" : "n"; //quick hack
  97. //check compatibility
  98. int a = _serverVersion.IndexOf('-');
  99. if(a==-1) throw new SSHException("Format of server version is invalid");
  100. int b = _serverVersion.IndexOf('-', a+1);
  101. if(b==-1) throw new SSHException("Format of server version is invalid");
  102. int comma = _serverVersion.IndexOf('.', a, b-a);
  103. if(comma==-1) throw new SSHException("Format of server version is invalid");
  104. int major = Int32.Parse(_serverVersion.Substring(a+1, comma-a-1));
  105. int minor = Int32.Parse(_serverVersion.Substring(comma+1, b-comma-1));
  106. if(_param.Protocol==SSHProtocol.SSH1) {
  107. if(major!=1) throw new SSHException("The protocol version of server is not compatible for SSH1");
  108. }
  109. else {
  110. if(major>=3 || major<=0 || (major==1 && minor!=99)) throw new SSHException("The protocol version of server is not compatible with SSH2");
  111. }
  112. this.SetReady();
  113. }
  114. catch(Exception ex) {
  115. OnError(ex, ex.Message);
  116. }
  117. }
  118. public void OnError(Exception error, string msg) {
  119. base.SetError(msg);
  120. }
  121. public void OnClosed() {
  122. base.SetClosed();
  123. }
  124. }
  125. //System.IO.Socket偲IChannelEventReceiver傪拪徾壔偡傞
  126. internal abstract class AbstractSocket {
  127. protected IByteArrayHandler _handler;
  128. protected AbstractSocket(IByteArrayHandler h) {
  129. _handler = h;
  130. }
  131. public void SetHandler(IByteArrayHandler h) {
  132. _handler = h;
  133. }
  134. internal abstract void Write(byte[] data, int offset, int length);
  135. internal abstract void WriteByte(byte data);
  136. internal abstract void Flush();
  137. internal abstract void Close();
  138. internal abstract bool DataAvailable { get; }
  139. }
  140. internal class PlainSocket : AbstractSocket {
  141. private Socket _socket;
  142. private byte[] _buf;
  143. private bool _closed;
  144. internal PlainSocket(Socket s, IByteArrayHandler h) : base(h) {
  145. _socket = s;
  146. _buf = new byte[0x1000];
  147. _closed = false;
  148. }
  149. internal override void Write(byte[] data, int offset, int length) {
  150. _socket.Send(data, offset, length, SocketFlags.None);
  151. }
  152. internal override void WriteByte(byte data) {
  153. byte[] t = new byte[1];
  154. t[0] = data;
  155. _socket.Send(t, 0, 1, SocketFlags.None);
  156. }
  157. internal override void Flush() {
  158. }
  159. internal override void Close() {
  160. _socket.Close();
  161. _closed = true;
  162. }
  163. internal void RepeatAsyncRead() {
  164. _socket.BeginReceive(_buf, 0, _buf.Length, SocketFlags.None, new AsyncCallback(RepeatCallback), null);
  165. }
  166. internal override bool DataAvailable {
  167. get {
  168. return _socket.Available>0;
  169. }
  170. }
  171. private void RepeatCallback(IAsyncResult result) {
  172. try {
  173. int n = _socket.EndReceive(result);
  174. //GUtil.WriteDebugLog(String.Format("t={0}, n={1} cr={2} cw={3}", DateTime.Now.ToString(), n, _socket.CanRead, _socket.CanWrite));
  175. //Debug.WriteLine(String.Format("r={0}, n={1} cr={2} cw={3}", result.IsCompleted, n, _socket.CanRead, _socket.CanWrite));
  176. if(n > 0) {
  177. _handler.OnData(_buf, 0, n);
  178. _socket.BeginReceive(_buf, 0, _buf.Length, SocketFlags.None, new AsyncCallback(RepeatCallback), null);
  179. }
  180. else if(n < 0) {
  181. //in case of Win9x, EndReceive() returns 0 every 288 seconds even if no data is available
  182. _socket.BeginReceive(_buf, 0, _buf.Length, SocketFlags.None, new AsyncCallback(RepeatCallback), null);
  183. }
  184. else
  185. _handler.OnClosed();
  186. }
  187. catch(Exception ex) {
  188. if((ex is SocketException) && ((SocketException)ex).ErrorCode==995) {
  189. //in case of .NET1.1 on Win9x, EndReceive() changes the behavior. it throws SocketException with an error code 995. 
  190. _socket.BeginReceive(_buf, 0, _buf.Length, SocketFlags.None, new AsyncCallback(RepeatCallback), null);
  191. }
  192. else if(!_closed)
  193. _handler.OnError(ex, ex.Message);
  194. else
  195. _handler.OnClosed();
  196. }
  197. }
  198. }
  199. internal class ChannelSocket : AbstractSocket, ISSHChannelEventReceiver {
  200. private SSHChannel _channel;
  201. private bool _ready;
  202. internal ChannelSocket(IByteArrayHandler h) : base(h) {
  203. _ready = false;
  204. }
  205. internal SSHChannel SSHChennal {
  206. get {
  207. return _channel;
  208. }
  209. set {
  210. _channel = value;
  211. }
  212. }
  213. internal override void Write(byte[] data, int offset, int length) {
  214. if(!_ready || _channel==null) throw new SSHException("channel not ready");
  215. _channel.Transmit(data, offset, length);
  216. }
  217. internal override void WriteByte(byte data) {
  218. if(!_ready || _channel==null) throw new SSHException("channel not ready");
  219. byte[] t = new byte[1];
  220. t[0] = data;
  221. _channel.Transmit(t);
  222. }
  223. internal override bool DataAvailable {
  224. get {
  225. return _channel.Connection.Available;
  226. }
  227. }
  228. internal override void Flush() {
  229. }
  230. internal override void Close() {
  231. if(!_ready || _channel==null) throw new SSHException("channel not ready");
  232. _channel.Close();
  233. if(_channel.Connection.ChannelCount<=1) //close last channel
  234. _channel.Connection.Close();
  235. }
  236. public void OnData(byte[] data, int offset, int length) {
  237. _handler.OnData(data, offset, length);
  238. }
  239. public void OnChannelEOF() {
  240. _handler.OnClosed();
  241. }
  242. public void OnChannelError(Exception error, string msg) {
  243. _handler.OnError(error, msg);
  244. }
  245. public void OnChannelClosed() {
  246. _handler.OnClosed();
  247. }
  248. public void OnChannelReady() {
  249. _ready = true;
  250. }
  251. public void OnExtendedData(int type, byte[] data) {
  252. //!!handle data
  253. }
  254. public void OnMiscPacket(byte type, byte[] data, int offset, int length) {
  255. }
  256. }
  257. }