| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- #region MIT License
- /**
- * WsStream.cs
- *
- * The MIT License
- *
- * Copyright (c) 2010-2012 sta.blockhead
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- #endregion
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Security.Cryptography.X509Certificates;
- using System.Text;
- using WebSocketSharp.Frame;
- using WebSocketSharp.Net.Security;
- namespace WebSocketSharp
- {
- internal class WsStream : IDisposable
- {
- #region Fields
- private Stream _innerStream;
- private bool _isSecure;
- private Object _forRead;
- private Object _forWrite;
- #endregion
- #region Private Constructor
- private WsStream()
- {
- _forRead = new object();
- _forWrite = new object();
- }
- #endregion
- #region Public Constructors
- public WsStream(NetworkStream innerStream)
- : this()
- {
- if (innerStream == null)
- throw new ArgumentNullException("innerStream");
- _innerStream = innerStream;
- _isSecure = false;
- }
- public WsStream(SslStream innerStream)
- : this()
- {
- if (innerStream == null)
- throw new ArgumentNullException("innerStream");
- _innerStream = innerStream;
- _isSecure = true;
- }
- #endregion
- #region Properties
- public bool DataAvailable
- {
- get
- {
- return _isSecure
- ? ((SslStream)_innerStream).DataAvailable
- : ((NetworkStream)_innerStream).DataAvailable;
- }
- }
- public bool IsSecure
- {
- get
- {
- return _isSecure;
- }
- }
- #endregion
- #region Private Methods
- private int read(byte[] buffer, int offset, int size)
- {
- var readLen = _innerStream.Read(buffer, offset, size);
- if (readLen < size)
- {
- var msg = String.Format("Data can not be read from {0}.", _innerStream.GetType().Name);
- throw new IOException(msg);
- }
- return readLen;
- }
- private int readByte()
- {
- return _innerStream.ReadByte();
- }
- private string[] readHandshake()
- {
- var buffer = new List<byte>();
- while (true)
- {
- if (Ext.EqualsAndSaveTo(readByte(), '\r', buffer) &&
- Ext.EqualsAndSaveTo(readByte(), '\n', buffer) &&
- Ext.EqualsAndSaveTo(readByte(), '\r', buffer) &&
- Ext.EqualsAndSaveTo(readByte(), '\n', buffer))
- break;
- }
- return Encoding.UTF8.GetString(buffer.ToArray())
- .Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
- .Split('\n');
- }
- private void write(byte[] buffer, int offset, int count)
- {
- _innerStream.Write(buffer, offset, count);
- }
- private void writeByte(byte value)
- {
- _innerStream.WriteByte(value);
- }
- #endregion
- #region Internal Methods
- internal static WsStream CreateClientStream(TcpClient client, string host, bool secure)
- {
- var netStream = client.GetStream();
- if (secure)
- {
- System.Net.Security.RemoteCertificateValidationCallback validationCb = (sender, certificate, chain, sslPolicyErrors) =>
- {
- // FIXME: Always returns true
- return true;
- };
- var sslStream = new SslStream(netStream, false, validationCb);
- sslStream.AuthenticateAsClient(host);
- return new WsStream(sslStream);
- }
- return new WsStream(netStream);
- }
- internal static WsStream CreateServerStream(TcpClient client, bool secure)
- {
- var netStream = client.GetStream();
- if (secure)
- {
- var sslStream = new SslStream(netStream, false);
- var certPath = ConfigurationManager.AppSettings["ServerCertPath"];
- sslStream.AuthenticateAsServer(new X509Certificate2(certPath));
- return new WsStream(sslStream);
- }
- return new WsStream(netStream);
- }
- internal static WsStream CreateServerStream(WebSocketSharp.Net.HttpListenerContext context)
- {
- var conn = context.Connection;
- var stream = conn.Stream;
- return conn.IsSecure
- ? new WsStream((SslStream)stream)
- : new WsStream((NetworkStream)stream);
- }
- #endregion
- #region Public Methods
- public void Close()
- {
- _innerStream.Close();
- }
- public void Dispose()
- {
- _innerStream.Dispose();
- }
- public WsFrame ReadFrame()
- {
- lock (_forRead)
- {
- try
- {
- return WsFrame.Parse(_innerStream);
- }
- catch
- {
- return null;
- }
- }
- }
- public void ReadFrameAsync(Action<WsFrame> completed)
- {
- WsFrame.ParseAsync(_innerStream, completed);
- }
- public string[] ReadHandshake()
- {
- lock (_forRead)
- {
- try
- {
- return readHandshake();
- }
- catch
- {
- return null;
- }
- }
- }
- public bool WriteFrame(WsFrame frame)
- {
- lock (_forWrite)
- {
- try
- {
- var buffer = frame.ToBytes();
- write(buffer, 0, buffer.Length);
- return true;
- }
- catch
- {
- return false;
- }
- }
- }
- public bool WriteHandshake(Handshake handshake)
- {
- lock (_forWrite)
- {
- try
- {
- var buffer = handshake.ToBytes();
- write(buffer, 0, buffer.Length);
- return true;
- }
- catch
- {
- return false;
- }
- }
- }
- #endregion
- }
- }
|