Fix for issue #29
This commit is contained in:
parent
0527568d04
commit
75dab14cf5
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2013 sta.blockhead
|
* Copyright (c) 2012-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -37,6 +37,7 @@ namespace WebSocketSharp
|
|||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
|
private byte [] _entity;
|
||||||
private NameValueCollection _headers;
|
private NameValueCollection _headers;
|
||||||
private Version _version;
|
private Version _version;
|
||||||
|
|
||||||
@ -58,8 +59,30 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Internal Properties
|
||||||
|
|
||||||
|
internal byte [] EntityBodyData {
|
||||||
|
get {
|
||||||
|
return _entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_entity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
|
public string EntityBody {
|
||||||
|
get {
|
||||||
|
return _entity != null && _entity.LongLength > 0
|
||||||
|
? getEncoding (_headers ["Content-Type"]).GetString (_entity)
|
||||||
|
: String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NameValueCollection Headers {
|
public NameValueCollection Headers {
|
||||||
get {
|
get {
|
||||||
return _headers;
|
return _headers;
|
||||||
@ -82,6 +105,27 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private static Encoding getEncoding (string contentType)
|
||||||
|
{
|
||||||
|
if (contentType == null || contentType.Length == 0)
|
||||||
|
return Encoding.UTF8;
|
||||||
|
|
||||||
|
var i = contentType.IndexOf ("charset=", StringComparison.Ordinal);
|
||||||
|
if (i == -1)
|
||||||
|
return Encoding.UTF8;
|
||||||
|
|
||||||
|
var charset = contentType.Substring (i + 8);
|
||||||
|
i = charset.IndexOf (';');
|
||||||
|
if (i != -1)
|
||||||
|
charset = charset.Substring (0, i);
|
||||||
|
|
||||||
|
return Encoding.GetEncoding (charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public byte [] ToByteArray ()
|
public byte [] ToByteArray ()
|
||||||
|
@ -192,13 +192,19 @@ namespace WebSocketSharp
|
|||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
var buffer = new StringBuilder (64);
|
var buffer = new StringBuilder (64);
|
||||||
buffer.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _rawUrl, ProtocolVersion, CrLf);
|
buffer.AppendFormat (
|
||||||
|
"{0} {1} HTTP/{2}{3}", _method, _rawUrl, ProtocolVersion, CrLf);
|
||||||
|
|
||||||
var headers = Headers;
|
var headers = Headers;
|
||||||
foreach (var key in headers.AllKeys)
|
foreach (var key in headers.AllKeys)
|
||||||
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
|
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
|
||||||
|
|
||||||
buffer.Append (CrLf);
|
buffer.Append (CrLf);
|
||||||
|
|
||||||
|
var entity = EntityBody;
|
||||||
|
if (entity.Length > 0)
|
||||||
|
buffer.Append (entity);
|
||||||
|
|
||||||
return buffer.ToString ();
|
return buffer.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +175,11 @@ namespace WebSocketSharp
|
|||||||
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
|
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
|
||||||
|
|
||||||
buffer.Append (CrLf);
|
buffer.Append (CrLf);
|
||||||
|
|
||||||
|
var entity = EntityBody;
|
||||||
|
if (entity.Length > 0)
|
||||||
|
buffer.Append (entity);
|
||||||
|
|
||||||
return buffer.ToString ();
|
return buffer.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2013 sta.blockhead
|
* Copyright (c) 2012-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -64,7 +64,7 @@ namespace WebSocketSharp.Net.WebSockets
|
|||||||
_client = client;
|
_client = client;
|
||||||
_secure = secure;
|
_secure = secure;
|
||||||
_stream = WsStream.CreateServerStream (client, cert, secure);
|
_stream = WsStream.CreateServerStream (client, cert, secure);
|
||||||
_request = HandshakeRequest.Parse (_stream.ReadHandshake ());
|
_request = _stream.ReadHandshakeRequest ();
|
||||||
_websocket = new WebSocket (this, logger);
|
_websocket = new WebSocket (this, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ namespace WebSocketSharp.Net.WebSockets
|
|||||||
var res = new HandshakeResponse (HttpStatusCode.Unauthorized);
|
var res = new HandshakeResponse (HttpStatusCode.Unauthorized);
|
||||||
res.Headers ["WWW-Authenticate"] = challenge;
|
res.Headers ["WWW-Authenticate"] = challenge;
|
||||||
_stream.WriteHandshake (res);
|
_stream.WriteHandshake (res);
|
||||||
_request = HandshakeRequest.Parse (_stream.ReadHandshake ());
|
_request = _stream.ReadHandshakeRequest ();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetUser (
|
internal void SetUser (
|
||||||
|
@ -1035,8 +1035,9 @@ namespace WebSocketSharp
|
|||||||
// As client
|
// As client
|
||||||
private HandshakeResponse receiveHandshakeResponse ()
|
private HandshakeResponse receiveHandshakeResponse ()
|
||||||
{
|
{
|
||||||
var res = HandshakeResponse.Parse (_stream.ReadHandshake ());
|
var res = _stream.ReadHandshakeResponse ();
|
||||||
_logger.Debug ("A response to this WebSocket connection request:\n" + res.ToString ());
|
_logger.Debug (
|
||||||
|
"A response to this WebSocket connection request:\n" + res.ToString ());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1310,7 +1311,7 @@ namespace WebSocketSharp
|
|||||||
frame => {
|
frame => {
|
||||||
if (acceptFrame (frame))
|
if (acceptFrame (frame))
|
||||||
receive ();
|
receive ();
|
||||||
else
|
else if (_exitReceiving != null)
|
||||||
_exitReceiving.Set ();
|
_exitReceiving.Set ();
|
||||||
},
|
},
|
||||||
ex => processException (
|
ex => processException (
|
||||||
|
@ -98,6 +98,72 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private byte [] readHandshakeEntityBody (string length)
|
||||||
|
{
|
||||||
|
var len = Int64.Parse (length);
|
||||||
|
return _innerStream.ReadBytes (len, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string [] readHandshakeHeaders ()
|
||||||
|
{
|
||||||
|
var read = false;
|
||||||
|
var exception = false;
|
||||||
|
|
||||||
|
var buffer = new List<byte> ();
|
||||||
|
Action<int> add = i => buffer.Add ((byte) i);
|
||||||
|
|
||||||
|
var timeout = false;
|
||||||
|
var timer = new Timer (
|
||||||
|
state => {
|
||||||
|
timeout = true;
|
||||||
|
_innerStream.Close ();
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
_handshakeTimeout,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (buffer.Count < _handshakeLimitLen) {
|
||||||
|
if (_innerStream.ReadByte ().EqualsWith ('\r', add) &&
|
||||||
|
_innerStream.ReadByte ().EqualsWith ('\n', add) &&
|
||||||
|
_innerStream.ReadByte ().EqualsWith ('\r', add) &&
|
||||||
|
_innerStream.ReadByte ().EqualsWith ('\n', add)) {
|
||||||
|
read = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
exception = true;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
timer.Change (-1, -1);
|
||||||
|
timer.Dispose ();
|
||||||
|
}
|
||||||
|
|
||||||
|
var reason = timeout
|
||||||
|
? "A timeout has occurred while receiving a handshake."
|
||||||
|
: exception
|
||||||
|
? "An exception has occurred while receiving a handshake."
|
||||||
|
: !read
|
||||||
|
? "A handshake length is greater than the limit length."
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (reason != null)
|
||||||
|
throw new WebSocketException (reason);
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString (buffer.ToArray ())
|
||||||
|
.Replace ("\r\n", "\n")
|
||||||
|
.Replace ("\n ", " ")
|
||||||
|
.Replace ("\n\t", " ")
|
||||||
|
.TrimEnd ('\n')
|
||||||
|
.Split ('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static WsStream CreateClientStream (
|
internal static WsStream CreateClientStream (
|
||||||
@ -177,60 +243,24 @@ namespace WebSocketSharp
|
|||||||
WsFrame.ParseAsync (_innerStream, true, completed, error);
|
WsFrame.ParseAsync (_innerStream, true, completed, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string [] ReadHandshake ()
|
public HandshakeRequest ReadHandshakeRequest ()
|
||||||
{
|
{
|
||||||
var exception = false;
|
var req = HandshakeRequest.Parse (readHandshakeHeaders ());
|
||||||
var read = false;
|
var contentLen = req.Headers ["Content-Length"];
|
||||||
var timeout = false;
|
if (contentLen != null && contentLen.Length > 0)
|
||||||
|
req.EntityBodyData = readHandshakeEntityBody (contentLen);
|
||||||
|
|
||||||
var buffer = new List<byte> ();
|
return req;
|
||||||
Action<int> add = i => buffer.Add ((byte) i);
|
}
|
||||||
|
|
||||||
var timer = new Timer (
|
public HandshakeResponse ReadHandshakeResponse ()
|
||||||
state => {
|
{
|
||||||
timeout = true;
|
var res = HandshakeResponse.Parse (readHandshakeHeaders ());
|
||||||
_innerStream.Close ();
|
var contentLen = res.Headers ["Content-Length"];
|
||||||
},
|
if (contentLen != null && contentLen.Length > 0)
|
||||||
null,
|
res.EntityBodyData = readHandshakeEntityBody (contentLen);
|
||||||
_handshakeTimeout,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
try {
|
return res;
|
||||||
while (buffer.Count < _handshakeLimitLen) {
|
|
||||||
if (_innerStream.ReadByte ().EqualsWith ('\r', add) &&
|
|
||||||
_innerStream.ReadByte ().EqualsWith ('\n', add) &&
|
|
||||||
_innerStream.ReadByte ().EqualsWith ('\r', add) &&
|
|
||||||
_innerStream.ReadByte ().EqualsWith ('\n', add)) {
|
|
||||||
read = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
timer.Change (-1, -1);
|
|
||||||
timer.Dispose ();
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = timeout
|
|
||||||
? "A timeout has occurred while receiving a handshake."
|
|
||||||
: exception
|
|
||||||
? "An exception has occurred while receiving a handshake."
|
|
||||||
: !read
|
|
||||||
? "A handshake length is greater than the limit length."
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (reason != null)
|
|
||||||
throw new WebSocketException (reason);
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetString (buffer.ToArray ())
|
|
||||||
.Replace ("\r\n", "\n")
|
|
||||||
.Replace ("\n ", " ")
|
|
||||||
.Replace ("\n\t", " ")
|
|
||||||
.TrimEnd ('\n')
|
|
||||||
.Split ('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteFrame (WsFrame frame)
|
public bool WriteFrame (WsFrame frame)
|
||||||
|
Loading…
Reference in New Issue
Block a user