Moved some methods from WebSocketStream class to HttpBase class

This commit is contained in:
sta 2014-07-25 13:28:28 +09:00
parent a0764d89ff
commit 48c6fac2f5
4 changed files with 120 additions and 115 deletions

View File

@ -27,8 +27,11 @@
#endregion
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Threading;
using WebSocketSharp.Net;
namespace WebSocketSharp
@ -38,6 +41,7 @@ namespace WebSocketSharp
#region Private Fields
private NameValueCollection _headers;
private const int _headersMaxLength = 8192;
private Version _version;
#endregion
@ -48,7 +52,7 @@ namespace WebSocketSharp
#endregion
#region Protected Const Fields
#region Protected Fields
protected const string CrLf = "\r\n";
@ -107,6 +111,96 @@ namespace WebSocketSharp
return Encoding.GetEncoding (charset);
}
private static byte[] readEntityBody (Stream stream, string length)
{
long len;
if (!Int64.TryParse (length, out len))
throw new ArgumentException ("Cannot be parsed.", "length");
if (len < 0)
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
return len > 1024
? stream.ReadBytes (len, 1024)
: len > 0
? stream.ReadBytes ((int) len)
: null;
}
private static string[] readHeaders (Stream stream, int maxLength)
{
var buff = new List<byte> ();
var cnt = 0;
Action<int> add = i => {
buff.Add ((byte) i);
cnt++;
};
var read = false;
while (cnt < maxLength) {
if (stream.ReadByte ().EqualsWith ('\r', add) &&
stream.ReadByte ().EqualsWith ('\n', add) &&
stream.ReadByte ().EqualsWith ('\r', add) &&
stream.ReadByte ().EqualsWith ('\n', add)) {
read = true;
break;
}
}
if (!read)
throw new WebSocketException ("The length of header part is greater than the max length.");
return Encoding.UTF8.GetString (buff.ToArray ())
.Replace (CrLf + " ", " ")
.Replace (CrLf + "\t", " ")
.Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
}
#endregion
#region Protected Methods
protected static T Read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
where T : HttpBase
{
var timeout = false;
var timer = new Timer (
state => {
timeout = true;
stream.Close ();
},
null,
millisecondsTimeout,
-1);
T http = null;
Exception exception = null;
try {
http = parser (readHeaders (stream, _headersMaxLength));
var contentLen = http.Headers["Content-Length"];
if (contentLen != null && contentLen.Length > 0)
http.EntityBodyData = readEntityBody (stream, contentLen);
}
catch (Exception ex) {
exception = ex;
}
finally {
timer.Change (-1, -1);
timer.Dispose ();
}
var msg = timeout
? "A timeout has occurred while reading an HTTP request/response."
: exception != null
? "An exception has occurred while reading an HTTP request/response."
: null;
if (msg != null)
throw new WebSocketException (msg, exception);
return http;
}
#endregion
#region Public Methods

View File

@ -28,6 +28,7 @@
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using WebSocketSharp.Net;
@ -137,6 +138,14 @@ namespace WebSocketSharp
return req;
}
internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
{
var buff = ToByteArray ();
stream.Write (buff, 0, buff.Length);
return Read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
}
internal static HttpRequest Parse (string[] headerParts)
{
var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
@ -151,6 +160,11 @@ namespace WebSocketSharp
requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
}
internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
{
return Read<HttpRequest> (stream, Parse, millisecondsTimeout);
}
#endregion
#region Public Methods

View File

@ -28,6 +28,7 @@
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using WebSocketSharp.Net;
@ -173,6 +174,11 @@ namespace WebSocketSharp
statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
}
internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
{
return Read<HttpResponse> (stream, Parse, millisecondsTimeout);
}
#endregion
#region Public Methods

View File

@ -27,12 +27,9 @@
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Security;
@ -40,12 +37,6 @@ namespace WebSocketSharp
{
internal class WebSocketStream : IDisposable
{
#region Private Const Fields
private const int _headersMaxLength = 8192;
#endregion
#region Private Fields
private Stream _innerStream;
@ -81,106 +72,6 @@ namespace WebSocketSharp
#endregion
#region Private Methods
private static T read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
where T : HttpBase
{
var timeout = false;
var timer = new Timer (
state => {
timeout = true;
stream.Close ();
},
null,
millisecondsTimeout,
-1);
T http = null;
Exception exception = null;
try {
http = parser (readHeaders (stream, _headersMaxLength));
var contentLen = http.Headers["Content-Length"];
if (contentLen != null && contentLen.Length > 0)
http.EntityBodyData = readEntityBody (stream, contentLen);
}
catch (Exception ex) {
exception = ex;
}
finally {
timer.Change (-1, -1);
timer.Dispose ();
}
var msg = timeout
? "A timeout has occurred while reading an HTTP request/response."
: exception != null
? "An exception has occurred while reading an HTTP request/response."
: null;
if (msg != null)
throw new WebSocketException (msg, exception);
return http;
}
private static byte[] readEntityBody (Stream stream, string length)
{
long len;
if (!Int64.TryParse (length, out len))
throw new ArgumentException ("Cannot be parsed.", "length");
if (len < 0)
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
return len > 1024
? stream.ReadBytes (len, 1024)
: len > 0
? stream.ReadBytes ((int) len)
: null;
}
private static string[] readHeaders (Stream stream, int maxLength)
{
var buff = new List<byte> ();
var cnt = 0;
Action<int> add = i => {
buff.Add ((byte) i);
cnt++;
};
var read = false;
while (cnt < maxLength) {
if (stream.ReadByte ().EqualsWith ('\r', add) &&
stream.ReadByte ().EqualsWith ('\n', add) &&
stream.ReadByte ().EqualsWith ('\r', add) &&
stream.ReadByte ().EqualsWith ('\n', add)) {
read = true;
break;
}
}
if (!read)
throw new WebSocketException ("The length of header part is greater than the max length.");
var crlf = "\r\n";
return Encoding.UTF8.GetString (buff.ToArray ())
.Replace (crlf + " ", " ")
.Replace (crlf + "\t", " ")
.Split (new[] { crlf }, StringSplitOptions.RemoveEmptyEntries);
}
private static HttpResponse sendHttpRequest (
Stream stream, HttpRequest request, int millisecondsTimeout)
{
var buff = request.ToByteArray ();
stream.Write (buff, 0, buff.Length);
return read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
}
#endregion
#region Internal Methods
internal static WebSocketStream CreateClientStream (
@ -199,7 +90,7 @@ namespace WebSocketSharp
var netStream = tcpClient.GetStream ();
if (proxy) {
var req = HttpRequest.CreateConnectRequest (targetUri);
var res = sendHttpRequest (netStream, req, 90000);
var res = req.GetResponse (netStream, 90000);
if (res.IsProxyAuthenticationRequired) {
var authChal = res.ProxyAuthenticationChallenge;
if (authChal != null && proxyCredentials != null) {
@ -213,7 +104,7 @@ namespace WebSocketSharp
var authRes = new AuthenticationResponse (authChal, proxyCredentials, 0);
req.Headers["Proxy-Authorization"] = authRes.ToString ();
res = sendHttpRequest (netStream, req, 15000);
res = req.GetResponse (netStream, 15000);
}
if (res.IsProxyAuthenticationRequired)
@ -256,12 +147,12 @@ namespace WebSocketSharp
internal HttpRequest ReadHttpRequest (int millisecondsTimeout)
{
return read<HttpRequest> (_innerStream, HttpRequest.Parse, millisecondsTimeout);
return HttpRequest.Read (_innerStream, millisecondsTimeout);
}
internal HttpResponse ReadHttpResponse (int millisecondsTimeout)
{
return read<HttpResponse> (_innerStream, HttpResponse.Parse, millisecondsTimeout);
return HttpResponse.Read (_innerStream, millisecondsTimeout);
}
internal WebSocketFrame ReadWebSocketFrame ()
@ -277,7 +168,7 @@ namespace WebSocketSharp
internal HttpResponse SendHttpRequest (HttpRequest request, int millisecondsTimeout)
{
return sendHttpRequest (_innerStream, request, millisecondsTimeout);
return request.GetResponse (_innerStream, millisecondsTimeout);
}
internal bool WriteBytes (byte[] data)