Fix due to the added ResponseHandshake.cs
This commit is contained in:
81
websocket-sharp/Handshake.cs
Normal file
81
websocket-sharp/Handshake.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
#region MIT License
|
||||
/**
|
||||
* Handshake.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 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.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
public abstract class Handshake {
|
||||
|
||||
protected const string _crlf = "\r\n";
|
||||
|
||||
protected Handshake()
|
||||
{
|
||||
}
|
||||
|
||||
public NameValueCollection Headers { get; protected set; }
|
||||
public string Version { get; protected set; }
|
||||
|
||||
public void AddHeader(string name, string value)
|
||||
{
|
||||
Headers.Add(name, value);
|
||||
}
|
||||
|
||||
public string[] GetHeaderValues(string name)
|
||||
{
|
||||
return Headers.GetValues(name);
|
||||
}
|
||||
|
||||
public bool HeaderExists(string name)
|
||||
{
|
||||
return Headers[name] != null
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
public bool HeaderExists(string name, string value)
|
||||
{
|
||||
var values = GetHeaderValues(name);
|
||||
if (values == null)
|
||||
return false;
|
||||
|
||||
foreach (string v in values)
|
||||
if (String.Compare(value, v, true) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(ToString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,16 +28,13 @@
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
public class RequestHandshake
|
||||
{
|
||||
private const string _crlf = "\r\n";
|
||||
namespace WebSocketSharp {
|
||||
|
||||
public class RequestHandshake : Handshake
|
||||
{
|
||||
private RequestHandshake()
|
||||
{
|
||||
}
|
||||
@@ -53,8 +50,6 @@ namespace WebSocketSharp
|
||||
AddHeader("Connection", "Upgrade");
|
||||
}
|
||||
|
||||
public NameValueCollection Headers { get; private set; }
|
||||
|
||||
public bool IsWebSocketRequest {
|
||||
|
||||
get {
|
||||
@@ -85,26 +80,14 @@ namespace WebSocketSharp
|
||||
|
||||
public string Method { get; private set; }
|
||||
public string Uri { get; private set; }
|
||||
public string Version { get; private set; }
|
||||
|
||||
public static RequestHandshake Parse(byte[] data)
|
||||
{
|
||||
var request = Encoding.UTF8.GetString(data)
|
||||
.Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
|
||||
.Split('\n');
|
||||
|
||||
return Parse(request);
|
||||
}
|
||||
|
||||
public static RequestHandshake Parse(string[] request)
|
||||
{
|
||||
var requestLine = request[0].Split(' ');
|
||||
|
||||
if (requestLine.Length != 3)
|
||||
throw new ArgumentException("Invalid request line.");
|
||||
|
||||
var headers = new WebHeaderCollection();
|
||||
|
||||
for (int i = 1; i < request.Length; i++)
|
||||
headers.Add(request[i]);
|
||||
|
||||
@@ -116,42 +99,6 @@ namespace WebSocketSharp
|
||||
};
|
||||
}
|
||||
|
||||
public void AddHeader(string name, string value)
|
||||
{
|
||||
Headers.Add(name, value);
|
||||
}
|
||||
|
||||
public string[] GetHeaderValues(string name)
|
||||
{
|
||||
return Headers.GetValues(name);
|
||||
}
|
||||
|
||||
public bool HeaderExists(string name)
|
||||
{
|
||||
return Headers[name] != null
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
public bool HeaderExists(string name, string value)
|
||||
{
|
||||
var values = GetHeaderValues(name);
|
||||
|
||||
if (values == null)
|
||||
return false;
|
||||
|
||||
foreach (string v in values)
|
||||
if (String.Compare(value, v, true) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(ToString());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
110
websocket-sharp/ResponseHandshake.cs
Normal file
110
websocket-sharp/ResponseHandshake.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
#region MIT License
|
||||
/**
|
||||
* ResponseHandshake.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 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.Specialized;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
public class ResponseHandshake : Handshake
|
||||
{
|
||||
public ResponseHandshake()
|
||||
{
|
||||
Version = "HTTP/1.1";
|
||||
Status = "101";
|
||||
Reason = "Switching Protocols";
|
||||
Headers = new NameValueCollection();
|
||||
|
||||
AddHeader("Upgrade", "websocket");
|
||||
AddHeader("Connection", "Upgrade");
|
||||
}
|
||||
|
||||
public bool IsWebSocketResponse {
|
||||
|
||||
get {
|
||||
if (Version != "HTTP/1.1")
|
||||
return false;
|
||||
|
||||
if (Status != "101")
|
||||
return false;
|
||||
|
||||
if (!HeaderExists("Upgrade", "websocket"))
|
||||
return false;
|
||||
|
||||
if (!HeaderExists("Connection", "Upgrade"))
|
||||
return false;
|
||||
|
||||
if (!HeaderExists("Sec-WebSocket-Accept"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public string Reason { get; private set; }
|
||||
public string Status { get; private set; }
|
||||
|
||||
public static ResponseHandshake Parse(string[] response)
|
||||
{
|
||||
var statusLine = response[0].Split(' ');
|
||||
if (statusLine.Length < 3)
|
||||
throw new ArgumentException("Invalid status line.");
|
||||
|
||||
var reason = new StringBuilder(statusLine[2]);
|
||||
for (int i = 3; i < statusLine.Length; i++)
|
||||
reason.AppendFormat(" {0}", statusLine[i]);
|
||||
|
||||
var headers = new WebHeaderCollection();
|
||||
for (int i = 1; i < response.Length; i++)
|
||||
headers.Add(response[i]);
|
||||
|
||||
return new ResponseHandshake {
|
||||
Headers = headers,
|
||||
Reason = reason.ToString(),
|
||||
Status = statusLine[1],
|
||||
Version = statusLine[0]
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
buffer.AppendFormat("{0} {1} {2}{3}", Version, Status, Reason, _crlf);
|
||||
|
||||
foreach (string key in Headers.AllKeys)
|
||||
buffer.AppendFormat("{0}: {1}{2}", key, Headers[key], _crlf);
|
||||
|
||||
buffer.Append(_crlf);
|
||||
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -251,7 +251,7 @@ namespace WebSocketSharp
|
||||
var response = createResponseHandshake();
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@acceptHandshake: Opening handshake from server:\n");
|
||||
Console.WriteLine(response);
|
||||
Console.WriteLine(response.ToString());
|
||||
#endif
|
||||
sendResponseHandshake(response);
|
||||
|
||||
@@ -435,24 +435,12 @@ namespace WebSocketSharp
|
||||
return request;
|
||||
}
|
||||
|
||||
private string createResponseHandshake()
|
||||
private ResponseHandshake createResponseHandshake()
|
||||
{
|
||||
string crlf = "\r\n";
|
||||
var response = new ResponseHandshake();
|
||||
response.AddHeader("Sec-WebSocket-Accept", createExpectedKey());
|
||||
|
||||
string resStatus = "HTTP/1.1 101 Switching Protocols" + crlf;
|
||||
string resUpgrade = "Upgrade: websocket" + crlf;
|
||||
string resConnection = "Connection: Upgrade" + crlf;
|
||||
string secWsAccept = String.Format("Sec-WebSocket-Accept: {0}{1}", createExpectedKey(), crlf);
|
||||
//string secWsProtocol = "Sec-WebSocket-Protocol: chat" + crlf;
|
||||
string secWsVersion = String.Format("Sec-WebSocket-Version: {0}{1}", _version, crlf);
|
||||
|
||||
return resStatus +
|
||||
resUpgrade +
|
||||
resConnection +
|
||||
secWsAccept +
|
||||
//secWsProtocol +
|
||||
secWsVersion +
|
||||
crlf;
|
||||
return response;
|
||||
}
|
||||
|
||||
private void createServerStream()
|
||||
@@ -467,32 +455,28 @@ namespace WebSocketSharp
|
||||
_sslStream.AuthenticateAsServer(new X509Certificate(certPath));
|
||||
|
||||
_wsStream = new WsStream<SslStream>(_sslStream);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wsStream = new WsStream<NetworkStream>(_netStream);
|
||||
}
|
||||
|
||||
_wsStream = new WsStream<NetworkStream>(_netStream);
|
||||
}
|
||||
|
||||
private void doHandshake()
|
||||
{
|
||||
var request = createOpeningHandshake();
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@doHandshake: Opening handshake from client:\n{0}", request);
|
||||
Console.WriteLine("WS: Info@doHandshake: Opening handshake from client:\n");
|
||||
Console.WriteLine(request.ToString());
|
||||
#endif
|
||||
var response = sendOpeningHandshake(request);
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@doHandshake: Opening handshake from server:\n");
|
||||
foreach (string s in response)
|
||||
{
|
||||
Console.WriteLine("{0}", s);
|
||||
}
|
||||
Console.WriteLine(response.ToString());
|
||||
#endif
|
||||
string msg;
|
||||
if (!isValidResponse(response, out msg))
|
||||
{
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
|
||||
ReadyState = WsState.OPEN;
|
||||
}
|
||||
@@ -552,87 +536,35 @@ namespace WebSocketSharp
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool isValidResponse(string[] response, out string message)
|
||||
private bool isValidResponse(ResponseHandshake response, out string message)
|
||||
{
|
||||
string resUpgrade, resConnection, secWsAccept, secWsVersion;
|
||||
string[] resStatus;
|
||||
|
||||
List<string> extensionList = new List<string>();
|
||||
|
||||
Func<string, Func<string, string, string>> func = s =>
|
||||
{
|
||||
return (e, a) =>
|
||||
{
|
||||
return String.Format("Invalid response {0} value: {1}(expected: {2})", s, a, e);
|
||||
};
|
||||
};
|
||||
|
||||
resStatus = response[0].Split(' ');
|
||||
if ("HTTP/1.1".NotEqualsDo(resStatus[0], func("HTTP Version"), out message, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ("101".NotEqualsDo(resStatus[1], func("Status Code"), out message, false))
|
||||
if (!response.IsWebSocketResponse)
|
||||
{
|
||||
message = "Not WebSocket response.";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 1; i < response.Length; i++)
|
||||
if (!response.HeaderExists("Sec-WebSocket-Accept", createExpectedKey()))
|
||||
{
|
||||
if (response[i].Contains("Upgrade:"))
|
||||
message = "Invalid Sec-WebSocket-Accept value.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.HeaderExists("Sec-WebSocket-Version"))
|
||||
{
|
||||
if (!response.HeaderExists("Sec-WebSocket-Version", _version))
|
||||
{
|
||||
resUpgrade = response[i].GetHeaderValue(":");
|
||||
if ("websocket".NotEqualsDo(resUpgrade, func("Upgrade"), out message, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (response[i].Contains("Connection:"))
|
||||
{
|
||||
resConnection = response[i].GetHeaderValue(":");
|
||||
if ("Upgrade".NotEqualsDo(resConnection, func("Connection"), out message, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (response[i].Contains("Sec-WebSocket-Accept:"))
|
||||
{
|
||||
secWsAccept = response[i].GetHeaderValue(":");
|
||||
if (createExpectedKey().NotEqualsDo(secWsAccept, func("Sec-WebSocket-Accept"), out message, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (response[i].Contains("Sec-WebSocket-Extensions:"))
|
||||
{
|
||||
extensionList.Add(response[i].GetHeaderValue(":"));
|
||||
}
|
||||
else if (response[i].Contains("Sec-WebSocket-Protocol:"))
|
||||
{
|
||||
_protocol = response[i].GetHeaderValue(":");
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@isValidResponse: Sub protocol: {0}", _protocol);
|
||||
#endif
|
||||
}
|
||||
else if (response[i].Contains("Sec-WebSocket-Version:"))
|
||||
{
|
||||
secWsVersion = response[i].GetHeaderValue(":");
|
||||
if (_version.NotEqualsDo(secWsVersion, func("Sec-WebSocket-Version"), out message, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("WS: Info@isValidResponse: Unsupported response header line: {0}", response[i]);
|
||||
message = "Unsupported Sec-WebSocket-Version.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
foreach (string s in extensionList)
|
||||
{
|
||||
Console.WriteLine("WS: Info@isValidResponse: Extensions: {0}", s);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (response.HeaderExists("Sec-WebSocket-Protocol"))
|
||||
_protocol = response.Headers["Sec-WebSocket-Protocol"];
|
||||
|
||||
if (response.HeaderExists("Sec-WebSocket-Extensions"))
|
||||
_extensions = response.Headers["Sec-WebSocket-Extensions"];
|
||||
|
||||
message = String.Empty;
|
||||
return true;
|
||||
}
|
||||
@@ -641,9 +573,7 @@ namespace WebSocketSharp
|
||||
{
|
||||
string scheme = uri.Scheme;
|
||||
if (scheme == "ws" || scheme == "wss")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -704,7 +634,7 @@ namespace WebSocketSharp
|
||||
pong(payloadData);
|
||||
}
|
||||
|
||||
private byte[] readHandshake()
|
||||
private string[] readHandshake()
|
||||
{
|
||||
var buffer = new List<byte>();
|
||||
|
||||
@@ -717,7 +647,9 @@ namespace WebSocketSharp
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer.ToArray();
|
||||
return Encoding.UTF8.GetString(buffer.ToArray())
|
||||
.Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
|
||||
.Split('\n');
|
||||
}
|
||||
|
||||
private MessageEventArgs receive()
|
||||
@@ -980,21 +912,15 @@ namespace WebSocketSharp
|
||||
return readLen;
|
||||
}
|
||||
|
||||
private string[] sendOpeningHandshake(RequestHandshake request)
|
||||
private ResponseHandshake sendOpeningHandshake(RequestHandshake request)
|
||||
{
|
||||
_wsStream.Write(request.ToBytes(), 0, request.ToBytes().Length);
|
||||
|
||||
var readData = readHandshake();
|
||||
|
||||
return Encoding.UTF8.GetString(readData)
|
||||
.Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
|
||||
.Split('\n');
|
||||
return ResponseHandshake.Parse(readHandshake());
|
||||
}
|
||||
|
||||
private void sendResponseHandshake(string value)
|
||||
private void sendResponseHandshake(ResponseHandshake response)
|
||||
{
|
||||
var buffer = Encoding.UTF8.GetBytes(value);
|
||||
_wsStream.Write(buffer, 0, buffer.Length);
|
||||
_wsStream.Write(response.ToBytes(), 0, response.ToBytes().Length);
|
||||
}
|
||||
|
||||
private void startMessageThread()
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -77,6 +77,8 @@
|
||||
<Compile Include="IWsStream.cs" />
|
||||
<Compile Include="WsStream.cs" />
|
||||
<Compile Include="RequestHandshake.cs" />
|
||||
<Compile Include="ResponseHandshake.cs" />
|
||||
<Compile Include="Handshake.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user