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
*
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -37,6 +37,7 @@ namespace WebSocketSharp
{
#region Private Fields
private byte [] _entity;
private NameValueCollection _headers;
private Version _version;
@ -58,8 +59,30 @@ namespace WebSocketSharp
#endregion
#region Internal Properties
internal byte [] EntityBodyData {
get {
return _entity;
}
set {
_entity = value;
}
}
#endregion
#region Public Properties
public string EntityBody {
get {
return _entity != null && _entity.LongLength > 0
? getEncoding (_headers ["Content-Type"]).GetString (_entity)
: String.Empty;
}
}
public NameValueCollection Headers {
get {
return _headers;
@ -82,6 +105,27 @@ namespace WebSocketSharp
#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
public byte [] ToByteArray ()

View File

@ -192,13 +192,19 @@ namespace WebSocketSharp
public override string ToString ()
{
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;
foreach (var key in headers.AllKeys)
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
buffer.Append (CrLf);
var entity = EntityBody;
if (entity.Length > 0)
buffer.Append (entity);
return buffer.ToString ();
}

View File

@ -175,6 +175,11 @@ namespace WebSocketSharp
buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
buffer.Append (CrLf);
var entity = EntityBody;
if (entity.Length > 0)
buffer.Append (entity);
return buffer.ToString ();
}

View File

@ -4,7 +4,7 @@
*
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -64,7 +64,7 @@ namespace WebSocketSharp.Net.WebSockets
_client = client;
_secure = secure;
_stream = WsStream.CreateServerStream (client, cert, secure);
_request = HandshakeRequest.Parse (_stream.ReadHandshake ());
_request = _stream.ReadHandshakeRequest ();
_websocket = new WebSocket (this, logger);
}
@ -365,7 +365,7 @@ namespace WebSocketSharp.Net.WebSockets
var res = new HandshakeResponse (HttpStatusCode.Unauthorized);
res.Headers ["WWW-Authenticate"] = challenge;
_stream.WriteHandshake (res);
_request = HandshakeRequest.Parse (_stream.ReadHandshake ());
_request = _stream.ReadHandshakeRequest ();
}
internal void SetUser (

View File

@ -1035,8 +1035,9 @@ namespace WebSocketSharp
// As client
private HandshakeResponse receiveHandshakeResponse ()
{
var res = HandshakeResponse.Parse (_stream.ReadHandshake ());
_logger.Debug ("A response to this WebSocket connection request:\n" + res.ToString ());
var res = _stream.ReadHandshakeResponse ();
_logger.Debug (
"A response to this WebSocket connection request:\n" + res.ToString ());
return res;
}
@ -1310,7 +1311,7 @@ namespace WebSocketSharp
frame => {
if (acceptFrame (frame))
receive ();
else
else if (_exitReceiving != null)
_exitReceiving.Set ();
},
ex => processException (

View File

@ -98,6 +98,72 @@ namespace WebSocketSharp
#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
internal static WsStream CreateClientStream (
@ -177,60 +243,24 @@ namespace WebSocketSharp
WsFrame.ParseAsync (_innerStream, true, completed, error);
}
public string [] ReadHandshake ()
public HandshakeRequest ReadHandshakeRequest ()
{
var exception = false;
var read = false;
var timeout = false;
var req = HandshakeRequest.Parse (readHandshakeHeaders ());
var contentLen = req.Headers ["Content-Length"];
if (contentLen != null && contentLen.Length > 0)
req.EntityBodyData = readHandshakeEntityBody (contentLen);
var buffer = new List<byte> ();
Action<int> add = i => buffer.Add ((byte) i);
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 ();
return req;
}
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;
public HandshakeResponse ReadHandshakeResponse ()
{
var res = HandshakeResponse.Parse (readHandshakeHeaders ());
var contentLen = res.Headers ["Content-Length"];
if (contentLen != null && contentLen.Length > 0)
res.EntityBodyData = readHandshakeEntityBody (contentLen);
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');
return res;
}
public bool WriteFrame (WsFrame frame)