Fix due to the modified WebSocketServer.cs

This commit is contained in:
sta
2012-10-01 15:26:31 +09:00
parent b4d8689bb3
commit fbcea4699b
66 changed files with 377 additions and 340 deletions

View File

@@ -1,14 +1,15 @@
#region MIT License
/**
* Ext.cs
* IsPredefinedScheme and MaybeUri methods derived from System.Uri
* IsPredefinedScheme and MaybeUri methods derived from System.Uri.cs
* GetStatusDescription method derived from System.Net.HttpListenerResponse.cs
*
* The MIT License
*
* (C) 2001 Garrett Rooney (System.Uri)
* (C) 2003 Ian MacLean (System.Uri)
* (C) 2003 Ben Maurer (System.Uri)
* Copyright (C) 2003,2009 Novell, Inc (http://www.novell.com) (System.Uri)
* Copyright (C) 2003, 2005, 2009 Novell, Inc. (http://www.novell.com) (System.Uri, System.Net.HttpListenerResponse)
* Copyright (c) 2009 Stephane Delcroix (System.Uri)
* Copyright (c) 2010-2012 sta.blockhead
*
@@ -37,16 +38,15 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp
{
public static class Ext
{
namespace WebSocketSharp {
public static class Ext {
public static TcpListenerWebSocketContext AcceptWebSocket(this TcpClient client)
{
return new TcpListenerWebSocketContext(client);
@@ -101,12 +101,73 @@ namespace WebSocketSharp
return false;
}
public static string GetDescription(this HttpStatusCode code)
{
return ((int)code).GetStatusDescription();
}
public static string GetHeaderValue(this string src, string separater)
{
int i = src.IndexOf(separater);
return src.Substring(i + 1).Trim();
}
// Derived from System.Net.HttpListenerResponse.GetStatusDescription method
public static string GetStatusDescription(this int code)
{
switch (code)
{
case 100: return "Continue";
case 101: return "Switching Protocols";
case 102: return "Processing";
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 203: return "Non-Authoritative Information";
case 204: return "No Content";
case 205: return "Reset Content";
case 206: return "Partial Content";
case 207: return "Multi-Status";
case 300: return "Multiple Choices";
case 301: return "Moved Permanently";
case 302: return "Found";
case 303: return "See Other";
case 304: return "Not Modified";
case 305: return "Use Proxy";
case 307: return "Temporary Redirect";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 402: return "Payment Required";
case 403: return "Forbidden";
case 404: return "Not Found";
case 405: return "Method Not Allowed";
case 406: return "Not Acceptable";
case 407: return "Proxy Authentication Required";
case 408: return "Request Timeout";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length Required";
case 412: return "Precondition Failed";
case 413: return "Request Entity Too Large";
case 414: return "Request-Uri Too Long";
case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable";
case 417: return "Expectation Failed";
case 422: return "Unprocessable Entity";
case 423: return "Locked";
case 424: return "Failed Dependency";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
case 503: return "Service Unavailable";
case 504: return "Gateway Timeout";
case 505: return "Http Version Not Supported";
case 507: return "Insufficient Storage";
}
return String.Empty;
}
public static bool IsHostOrder(this ByteOrder order)
{
if (BitConverter.IsLittleEndian ^ (order == ByteOrder.LITTLE))
@@ -195,7 +256,7 @@ namespace WebSocketSharp
}
var host = uri.DnsSafeHost;
var addrs = Dns.GetHostAddresses(host);
var addrs = System.Net.Dns.GetHostAddresses(host);
if (addrs.Length == 0)
{
message = "Invalid WebSocket URI host: " + host;
@@ -238,6 +299,9 @@ namespace WebSocketSharp
public static byte[] ReadBytes(this Stream stream, int length)
{
if (length <= 0)
return new byte[]{};
var buffer = new byte[length];
stream.Read(buffer, 0, length);
return buffer;
@@ -471,8 +535,7 @@ namespace WebSocketSharp
return new Uri(uriString);
}
public static void WriteContent(
this WebSocketSharp.Net.HttpListenerResponse response, byte[] content)
public static void WriteContent(this HttpListenerResponse response, byte[] content)
{
var output = response.OutputStream;
response.ContentLength64 = content.Length;

View File

@@ -503,7 +503,7 @@ namespace WebSocketSharp.Net {
HttpListenerResponse response = context.Response;
response.StatusCode = status;
response.ContentType = "text/html";
string description = HttpListenerResponse.GetStatusDescription (status);
string description = status.GetStatusDescription ();
string str;
if (msg != null)
str = String.Format ("<h1>{0} ({1})</h1>", description, msg);

View File

@@ -1,6 +1,6 @@
//
// HttpListenerRequest.cs
// Copied from System.Net.HttpListenerRequest
// Copied from System.Net.HttpListenerRequest.cs
//
// Author:
// Gonzalo Paniagua Javier (gonzalo@novell.com)

View File

@@ -1,11 +1,12 @@
//
// HttpListenerResponse.cs
// Copied from System.Net.HttpListenerResponse
// Copied from System.Net.HttpListenerResponse.cs
//
// Author:
// Gonzalo Paniagua Javier (gonzalo@novell.com)
//
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
// Copyright (c) 2012 sta.blockhead (sta.blockhead@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -37,33 +38,53 @@ namespace WebSocketSharp.Net {
public sealed class HttpListenerResponse : IDisposable
{
bool disposed;
Encoding content_encoding;
long content_length;
bool cl_set;
string content_type;
CookieCollection cookies;
WebHeaderCollection headers = new WebHeaderCollection ();
bool keep_alive = true;
ResponseStream output_stream;
Version version = HttpVersion.Version11;
string location;
int status_code = 200;
string status_description = "OK";
bool chunked;
#region Private Fields
bool chunked;
bool cl_set;
Encoding content_encoding;
long content_length;
string content_type;
HttpListenerContext context;
CookieCollection cookies;
bool disposed;
bool force_close_chunked;
WebHeaderCollection headers;
bool keep_alive;
string location;
ResponseStream output_stream;
int status_code;
string status_description;
Version version;
#endregion
#region Internal Fields
internal bool HeadersSent;
bool force_close_chunked;
#endregion
#region Constructor
internal HttpListenerResponse (HttpListenerContext context)
{
this.context = context;
Init ();
}
#endregion
#region Internal Property
internal bool ForceCloseChunked {
get { return force_close_chunked; }
}
#endregion
#region Public Properties
public Encoding ContentEncoding {
get {
if (content_encoding == null)
@@ -74,10 +95,10 @@ namespace WebSocketSharp.Net {
if (disposed)
throw new ObjectDisposedException (GetType ().ToString ());
//TODO: is null ok?
// TODO: is null ok?
if (HeadersSent)
throw new InvalidOperationException ("Cannot be changed after headers are sent.");
content_encoding = value;
}
}
@@ -214,65 +235,13 @@ namespace WebSocketSharp.Net {
if (HeadersSent)
throw new InvalidOperationException ("Cannot be changed after headers are sent.");
if (value < 100 || value > 999)
throw new ProtocolViolationException ("StatusCode must be between 100 and 999.");
status_code = value;
status_description = GetStatusDescription (value);
}
}
internal static string GetStatusDescription (int code)
{
switch (code){
case 100: return "Continue";
case 101: return "Switching Protocols";
case 102: return "Processing";
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 203: return "Non-Authoritative Information";
case 204: return "No Content";
case 205: return "Reset Content";
case 206: return "Partial Content";
case 207: return "Multi-Status";
case 300: return "Multiple Choices";
case 301: return "Moved Permanently";
case 302: return "Found";
case 303: return "See Other";
case 304: return "Not Modified";
case 305: return "Use Proxy";
case 307: return "Temporary Redirect";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 402: return "Payment Required";
case 403: return "Forbidden";
case 404: return "Not Found";
case 405: return "Method Not Allowed";
case 406: return "Not Acceptable";
case 407: return "Proxy Authentication Required";
case 408: return "Request Timeout";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length Required";
case 412: return "Precondition Failed";
case 413: return "Request Entity Too Large";
case 414: return "Request-Uri Too Long";
case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable";
case 417: return "Expectation Failed";
case 422: return "Unprocessable Entity";
case 423: return "Locked";
case 424: return "Failed Dependency";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
case 503: return "Service Unavailable";
case 504: return "Gateway Timeout";
case 505: return "Http Version Not Supported";
case 507: return "Insufficient Storage";
status_code = value;
status_description = value.GetStatusDescription ();
}
return "";
}
public string StatusDescription {
@@ -282,55 +251,9 @@ namespace WebSocketSharp.Net {
}
}
void IDisposable.Dispose ()
{
Close (true); //TODO: Abort or Close?
}
#endregion
public void Abort ()
{
if (disposed)
return;
Close (true);
}
public void AddHeader (string name, string value)
{
if (name == null)
throw new ArgumentNullException ("name");
if (name == "")
throw new ArgumentException ("'name' cannot be empty", "name");
//TODO: check for forbidden headers and invalid characters
if (value.Length > 65535)
throw new ArgumentOutOfRangeException ("value");
headers.Set (name, value);
}
public void AppendCookie (Cookie cookie)
{
if (cookie == null)
throw new ArgumentNullException ("cookie");
Cookies.Add (cookie);
}
public void AppendHeader (string name, string value)
{
if (name == null)
throw new ArgumentNullException ("name");
if (name == "")
throw new ArgumentException ("'name' cannot be empty", "name");
if (value.Length > 65535)
throw new ArgumentOutOfRangeException ("value");
headers.Add (name, value);
}
#region Private Methods
void Close (bool force)
{
@@ -338,43 +261,9 @@ namespace WebSocketSharp.Net {
context.Connection.Close (force);
}
public void Close ()
void IDisposable.Dispose ()
{
if (disposed)
return;
Close (false);
}
public void Close (byte [] responseEntity, bool willBlock)
{
if (disposed)
return;
if (responseEntity == null)
throw new ArgumentNullException ("responseEntity");
//TODO: if willBlock -> BeginWrite + Close ?
ContentLength64 = responseEntity.Length;
OutputStream.Write (responseEntity, 0, (int) content_length);
Close (false);
}
public void CopyFrom (HttpListenerResponse templateResponse)
{
headers.Clear ();
headers.Add (templateResponse.headers);
content_length = templateResponse.content_length;
status_code = templateResponse.status_code;
status_description = templateResponse.status_description;
keep_alive = templateResponse.keep_alive;
version = templateResponse.version;
}
public void Redirect (string url)
{
StatusCode = 302; // Found
location = url;
Close (true); // TODO: Abort or Close?
}
bool FindCookie (Cookie cookie)
@@ -394,6 +283,19 @@ namespace WebSocketSharp.Net {
return false;
}
void Init ()
{
headers = new WebHeaderCollection ();
keep_alive = true;
status_code = 200;
status_description = "OK";
version = HttpVersion.Version11;
}
#endregion
#region Internal Method
internal void SendHeaders (bool closing, MemoryStream ms)
{
Encoding encoding = content_encoding;
@@ -431,13 +333,13 @@ namespace WebSocketSharp.Net {
chunked = true;
/* Apache forces closing the connection for these status codes:
* HttpStatusCode.BadRequest 400
* HttpStatusCode.RequestTimeout 408
* HttpStatusCode.LengthRequired 411
* HttpStatusCode.BadRequest 400
* HttpStatusCode.RequestTimeout 408
* HttpStatusCode.LengthRequired 411
* HttpStatusCode.RequestEntityTooLarge 413
* HttpStatusCode.RequestUriTooLong 414
* HttpStatusCode.InternalServerError 500
* HttpStatusCode.ServiceUnavailable 503
* HttpStatusCode.RequestUriTooLong 414
* HttpStatusCode.InternalServerError 500
* HttpStatusCode.ServiceUnavailable 503
*/
bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 ||
status_code == 413 || status_code == 414 || status_code == 500 ||
@@ -492,6 +394,94 @@ namespace WebSocketSharp.Net {
HeadersSent = true;
}
#endregion
#region Public Methods
public void Abort ()
{
if (disposed)
return;
Close (true);
}
public void AddHeader (string name, string value)
{
if (name == null)
throw new ArgumentNullException ("name");
if (name == "")
throw new ArgumentException ("'name' cannot be empty", "name");
// TODO: check for forbidden headers and invalid characters
if (value.Length > 65535)
throw new ArgumentOutOfRangeException ("value");
headers.Set (name, value);
}
public void AppendCookie (Cookie cookie)
{
if (cookie == null)
throw new ArgumentNullException ("cookie");
Cookies.Add (cookie);
}
public void AppendHeader (string name, string value)
{
if (name == null)
throw new ArgumentNullException ("name");
if (name == "")
throw new ArgumentException ("'name' cannot be empty", "name");
if (value.Length > 65535)
throw new ArgumentOutOfRangeException ("value");
headers.Add (name, value);
}
public void Close ()
{
if (disposed)
return;
Close (false);
}
public void Close (byte [] responseEntity, bool willBlock)
{
if (disposed)
return;
if (responseEntity == null)
throw new ArgumentNullException ("responseEntity");
// TODO: if willBlock -> BeginWrite + Close ?
ContentLength64 = responseEntity.Length;
OutputStream.Write (responseEntity, 0, (int) content_length);
Close (false);
}
public void CopyFrom (HttpListenerResponse templateResponse)
{
headers.Clear ();
headers.Add (templateResponse.headers);
content_length = templateResponse.content_length;
status_code = templateResponse.status_code;
status_description = templateResponse.status_description;
keep_alive = templateResponse.keep_alive;
version = templateResponse.version;
}
public void Redirect (string url)
{
StatusCode = 302; // Found
location = url;
}
public void SetCookie (Cookie cookie)
{
if (cookie == null)
@@ -506,5 +496,7 @@ namespace WebSocketSharp.Net {
cookies.Add (cookie);
}
#endregion
}
}

View File

@@ -35,47 +35,21 @@ namespace WebSocketSharp {
public class ResponseHandshake : Handshake
{
#region Public Static Fields
public static ResponseHandshake BadRequest;
public static ResponseHandshake NotImplemented;
#endregion
#region Static Constructor
static ResponseHandshake()
{
var badRequest = new ResponseHandshake {
Reason = "Bad Request",
StatusCode = ((int)HttpStatusCode.BadRequest).ToString()
};
badRequest.Headers.Clear();
badRequest.AddHeader("Connection", "Close");
BadRequest = badRequest;
var notImplemented = new ResponseHandshake {
Reason = "Not Implemented",
StatusCode = ((int)HttpStatusCode.NotImplemented).ToString()
};
notImplemented.Headers.Clear();
notImplemented.AddHeader("Connection", "Close");
NotImplemented = notImplemented;
}
#endregion
#region Public Constructor
#region Constructor
public ResponseHandshake()
: this(HttpStatusCode.SwitchingProtocols)
{
StatusCode = "101";
Reason = "Switching Protocols";
AddHeader("Upgrade", "websocket");
AddHeader("Connection", "Upgrade");
}
public ResponseHandshake(HttpStatusCode code)
{
StatusCode = ((int)code).ToString();
Reason = code.GetDescription();
}
#endregion
#region Properties
@@ -102,12 +76,21 @@ namespace WebSocketSharp {
}
}
public string Reason { get; internal set; }
public string Reason { get; internal set; }
public string StatusCode { get; internal set; }
#endregion
#region Public Static Methods
#region Methods
public static ResponseHandshake CreateCloseResponse(HttpStatusCode code)
{
var res = new ResponseHandshake(code);
res.AddHeader("Connection", "close");
return res;
}
public static ResponseHandshake Parse(string[] response)
{
@@ -131,10 +114,6 @@ namespace WebSocketSharp {
};
}
#endregion
#region Public Methods
public override string ToString()
{
var buffer = new StringBuilder();

View File

@@ -161,13 +161,13 @@ namespace WebSocketSharp.Server {
{
respondToClient(context);
}
res.Close();
}
catch (Exception ex)
{
OnError.Emit(this, new ErrorEventArgs(ex.Message));
}
res.Close();
};
ThreadPool.QueueUserWorkItem(respondCb);
}
@@ -247,12 +247,6 @@ namespace WebSocketSharp.Server {
var req = context.Request;
var res = context.Response;
if (!req.IsWebSocketRequest)
{
res.StatusCode = (int)HttpStatusCode.BadRequest;
return false;
}
var path = req.RawUrl;
if (!_wsServers.ContainsKey(path))
{
@@ -303,6 +297,7 @@ namespace WebSocketSharp.Server {
_acceptRequestThread.Join(5 * 1000);
foreach (var server in _wsServers.Values)
server.Stop();
_wsServers.Clear();
}
#endregion

View File

@@ -31,9 +31,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using WebSocketSharp.Frame;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp.Server {
@@ -54,7 +54,7 @@ namespace WebSocketSharp.Server {
}
public WebSocketServer(int port)
: base(IPAddress.Any, port)
: base(System.Net.IPAddress.Any, port)
{
_servers = new Dictionary<string, IWebSocketServer>();
}
@@ -66,18 +66,14 @@ namespace WebSocketSharp.Server {
protected override void bindSocket(TcpClient client)
{
var context = client.AcceptWebSocket();
var socket = context.WebSocket;
var path = context.RequestUri.ToString();
if (!_servers.ContainsKey(path))
{
var stream = context.Stream;
var res = ResponseHandshake.NotImplemented;
stream.WriteHandshake(res);
stream.Close();
client.Close();
socket.Close(HttpStatusCode.NotImplemented);
return;
}
var socket = context.WebSocket;
var server = _servers[path];
server.BindWebSocket(socket);
}
@@ -98,6 +94,7 @@ namespace WebSocketSharp.Server {
base.Stop();
foreach (var server in _servers.Values)
server.Stop();
_servers.Clear();
}
#endregion
@@ -137,7 +134,7 @@ namespace WebSocketSharp.Server {
}
public WebSocketServer(int port, string path)
: base(IPAddress.Any, port)
: base(System.Net.IPAddress.Any, port)
{
var uri = path.ToUri();
if (uri.IsAbsoluteUri)
@@ -206,6 +203,7 @@ namespace WebSocketSharp.Server {
{
foreach (WebSocketService service in _services.Values)
service.Stop(code, reason);
_services.Clear();
}
}

View File

@@ -36,7 +36,6 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
@@ -46,8 +45,8 @@ using WebSocketSharp.Frame;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp
{
namespace WebSocketSharp {
public class WebSocket : IDisposable
{
#region Private Const Fields
@@ -60,25 +59,25 @@ namespace WebSocketSharp
#region Private Fields
private string _base64key;
private WebSocketSharp.Net.HttpListenerContext _baseContext;
private string _binaryType;
private WebSocketContext _context;
private IPEndPoint _endPoint;
private AutoResetEvent _exitMessageLoop;
private string _extensions;
private Object _forClose;
private Object _forSend;
private bool _isClient;
private bool _isSecure;
private string _protocol;
private string _protocols;
private volatile WsState _readyState;
private AutoResetEvent _receivedPong;
private TcpClient _tcpClient;
private Uri _uri;
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
private WsStream _wsStream;
private string _base64key;
private HttpListenerContext _baseContext;
private string _binaryType;
private WebSocketContext _context;
private System.Net.IPEndPoint _endPoint;
private AutoResetEvent _exitMessageLoop;
private string _extensions;
private Object _forClose;
private Object _forSend;
private bool _isClient;
private bool _isSecure;
private string _protocol;
private string _protocols;
private volatile WsState _readyState;
private AutoResetEvent _receivePong;
private TcpClient _tcpClient;
private Uri _uri;
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
private WsStream _wsStream;
#endregion
@@ -92,7 +91,7 @@ namespace WebSocketSharp
_forSend = new Object();
_protocol = String.Empty;
_readyState = WsState.CONNECTING;
_receivedPong = new AutoResetEvent(false);
_receivePong = new AutoResetEvent(false);
_unTransmittedBuffer = new SynchronizedCollection<WsFrame>();
}
@@ -107,7 +106,7 @@ namespace WebSocketSharp
_context = context;
_tcpClient = context.Client;
_wsStream = context.Stream;
_endPoint = (IPEndPoint)_tcpClient.Client.LocalEndPoint;
_endPoint = (System.Net.IPEndPoint)_tcpClient.Client.LocalEndPoint;
_isClient = false;
_isSecure = context.IsSecureConnection;
}
@@ -129,9 +128,10 @@ namespace WebSocketSharp
{
_uri = uri;
_tcpClient = tcpClient;
_endPoint = (IPEndPoint)_tcpClient.Client.LocalEndPoint;
_wsStream = WsStream.CreateServerStream(tcpClient);
_endPoint = (System.Net.IPEndPoint)tcpClient.Client.LocalEndPoint;
_isClient = false;
_isSecure = _endPoint.Port == 443 ? true : false;
_isSecure = _wsStream.IsSecure;
}
#endregion
@@ -276,10 +276,18 @@ namespace WebSocketSharp
}
sendResponseHandshake();
ReadyState = WsState.OPEN;
}
private void close(HttpStatusCode code)
{
if (_readyState != WsState.CONNECTING || _isClient)
return;
sendResponseHandshake(code);
ReadyState = WsState.CLOSED;
}
private void close(PayloadData data)
{
#if DEBUG
@@ -294,8 +302,7 @@ namespace WebSocketSharp
if (_readyState == WsState.CONNECTING && !_isClient)
{
OnClose.Emit(this, new CloseEventArgs(data));
sendResponseHandshakeForInvalid();
ReadyState = WsState.CLOSED;
close(HttpStatusCode.BadRequest);
return;
}
@@ -314,14 +321,13 @@ namespace WebSocketSharp
{
var data = new List<byte>(((ushort)code).ToBytes(ByteOrder.BIG));
if (reason != String.Empty)
if (!String.IsNullOrEmpty(reason))
{
var buffer = Encoding.UTF8.GetBytes(reason);
data.AddRange(buffer);
}
var payloadData = new PayloadData(data.ToArray());
if (payloadData.Length > 125)
{
var msg = "Close frame must have a payload length of 125 bytes or less.";
@@ -366,7 +372,6 @@ namespace WebSocketSharp
private void createClientStream()
{
var host = _uri.DnsSafeHost;
var port = _uri.Port;
if (port <= 0)
port = IsSecure ? 443 : 80;
@@ -376,33 +381,27 @@ namespace WebSocketSharp
private string createExpectedKey()
{
byte[] keySrc;
SHA1 sha1 = new SHA1CryptoServiceProvider();
StringBuilder sb = new StringBuilder(_base64key);
SHA1 sha1 = new SHA1CryptoServiceProvider();
var sb = new StringBuilder(_base64key);
sb.Append(_guid);
keySrc = sha1.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
var keySrc = sha1.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
return Convert.ToBase64String(keySrc);
}
private WsFrame createFrame(Fin fin, Opcode opcode, PayloadData payloadData)
{
if (_isClient)
{
return new WsFrame(fin, opcode, payloadData);
}
else
{
return new WsFrame(fin, opcode, Mask.UNMASK, payloadData);
}
return _isClient
? new WsFrame(fin, opcode, payloadData)
: new WsFrame(fin, opcode, Mask.UNMASK, payloadData);
}
private RequestHandshake createOpeningHandshake()
{
var path = _uri.PathAndQuery;
var host = _uri.DnsSafeHost;
var port = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Port;
var port = ((System.Net.IPEndPoint)_tcpClient.Client.RemoteEndPoint).Port;
if (port != 80)
host += ":" + port;
@@ -429,22 +428,12 @@ namespace WebSocketSharp
return res;
}
private void createServerStream()
private ResponseHandshake createResponseHandshake(HttpStatusCode code)
{
if (_wsStream != null)
return;
var res = ResponseHandshake.CreateCloseResponse(code);
res.AddHeader("Sec-WebSocket-Version", _version);
if (_tcpClient != null)
{
_wsStream = WsStream.CreateServerStream(_tcpClient);
return;
}
if (_baseContext != null)
{
_wsStream = WsStream.CreateServerStream(_baseContext);
return;
}
return res;
}
private void doHandshake()
@@ -524,7 +513,7 @@ namespace WebSocketSharp
var expectedHost1 = host;
var expectedHost2 = address.ToString();
if (type != UriHostNameType.Dns)
expectedHost2 = Dns.GetHostEntry(address).HostName;
expectedHost2 = System.Net.Dns.GetHostEntry(address).HostName;
if (port != 80)
{
@@ -612,7 +601,7 @@ namespace WebSocketSharp
}
catch (Exception)
{
close(CloseStatusCode.ABNORMAL, "An exception has been raised.");
close(CloseStatusCode.ABNORMAL, "An exception has occured.");
}
}
@@ -698,7 +687,7 @@ namespace WebSocketSharp
if (frame.Opcode == Opcode.PONG)
{// FINAL & PONG
_receivedPong.Set();
_receivePong.Set();
}
// FINAL & (TEXT | BINARY | PONG)
@@ -756,7 +745,7 @@ namespace WebSocketSharp
if (frame.Opcode == Opcode.PONG)
{// FINAL & PONG
_receivedPong.Set();
_receivePong.Set();
OnMessage.Emit(this, new MessageEventArgs(frame.Opcode, frame.PayloadData));
continue;
}
@@ -774,12 +763,9 @@ namespace WebSocketSharp
private RequestHandshake receiveOpeningHandshake()
{
RequestHandshake req;
if (_context == null)
req = RequestHandshake.Parse(readHandshake());
else
req = RequestHandshake.Parse(_context);
var req = _context != null
? RequestHandshake.Parse(_context)
: RequestHandshake.Parse(readHandshake());
#if DEBUG
Console.WriteLine("WS: Info@receiveOpeningHandshake: Opening handshake from client:\n");
Console.WriteLine(req.ToString());
@@ -787,6 +773,16 @@ namespace WebSocketSharp
return req;
}
private ResponseHandshake receiveResponseHandshake()
{
var res = ResponseHandshake.Parse(readHandshake());
#if DEBUG
Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
return res;
}
private bool send(WsFrame frame)
{
if (_readyState == WsState.CONNECTING ||
@@ -856,11 +852,10 @@ namespace WebSocketSharp
}
}
private void send(Fin fin, Opcode opcode, byte[] data)
private bool send(Fin fin, Opcode opcode, byte[] data)
{
var payloadData = new PayloadData(data);
var frame = createFrame(fin, opcode, payloadData);
send(frame);
var frame = createFrame(fin, opcode, new PayloadData(data));
return send(frame);
}
private long sendFragmented(Opcode opcode, Stream stream)
@@ -894,35 +889,38 @@ namespace WebSocketSharp
private ResponseHandshake sendOpeningHandshake()
{
var req = createOpeningHandshake();
sendOpeningHandshake(req);
return receiveResponseHandshake();
}
private void sendOpeningHandshake(RequestHandshake request)
{
#if DEBUG
Console.WriteLine("WS: Info@sendOpeningHandshake: Opening handshake from client:\n");
Console.WriteLine(req.ToString());
Console.WriteLine(request.ToString());
#endif
_wsStream.WriteHandshake(req);
var res = ResponseHandshake.Parse(readHandshake());
#if DEBUG
Console.WriteLine("WS: Info@sendOpeningHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
return res;
writeHandshake(request);
}
private void sendResponseHandshake()
{
var res = createResponseHandshake();
#if DEBUG
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
_wsStream.WriteHandshake(res);
sendResponseHandshake(res);
}
private void sendResponseHandshakeForInvalid()
private void sendResponseHandshake(HttpStatusCode code)
{
var res = ResponseHandshake.BadRequest;
res.AddHeader("Sec-WebSocket-Version", _version);
_wsStream.WriteHandshake(res);
var res = createResponseHandshake(code);
sendResponseHandshake(res);
}
private void sendResponseHandshake(ResponseHandshake response)
{
#if DEBUG
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
Console.WriteLine(response.ToString());
#endif
writeHandshake(response);
}
private void startMessageThread()
@@ -938,6 +936,20 @@ namespace WebSocketSharp
messageInvoker.BeginInvoke(messageLoopCallback, messageInvoker);
}
private void writeHandshake(Handshake handshake)
{
_wsStream.WriteHandshake(handshake);
}
#endregion
#region Internal Method
internal void Close(HttpStatusCode code)
{
close(code);
}
#endregion
#region Public Methods
@@ -961,27 +973,27 @@ namespace WebSocketSharp
{
if (_readyState == WsState.OPEN)
{
Console.WriteLine("\nWS: Info@Connect: Connection is already established.");
Console.WriteLine("WS: Info@Connect: Connection has been established already.");
return;
}
try
{
// As client
if (_isClient)
{
createClientStream();
doHandshake();
return;
}
else
{
createServerStream();
acceptHandshake();
}
// As server
acceptHandshake();
}
catch (Exception ex)
{
error(ex.Message);
close(CloseStatusCode.HANDSHAKE_FAILURE, "An exception has been raised.");
close(CloseStatusCode.HANDSHAKE_FAILURE, "An exception has occured.");
}
}
@@ -997,20 +1009,18 @@ namespace WebSocketSharp
public bool Ping(string data)
{
var payloadData = new PayloadData(data);
if (payloadData.Length > 125)
var buffer = Encoding.UTF8.GetBytes(data);
if (buffer.Length > 125)
{
var msg = "Ping frame must have a payload length of 125 bytes or less.";
error(msg);
return false;
}
var frame = createFrame(Fin.FINAL, Opcode.PING, payloadData);
if (!send(frame))
if (!send(Fin.FINAL, Opcode.PING, buffer))
return false;
return _receivedPong.WaitOne(5 * 1000);
return _receivePong.WaitOne(5 * 1000);
}
public void Send(string data)

Binary file not shown.