Fix for issue #29

This commit is contained in:
sta 2014-01-14 22:42:02 +09:00
parent 0527568d04
commit 75dab14cf5
6 changed files with 144 additions and 58 deletions

View File

@ -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 ()

View File

@ -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 ();
} }

View File

@ -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 ();
} }

View File

@ -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 (

View File

@ -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 (

View File

@ -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)