108 lines
3.4 KiB
C#
108 lines
3.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Text;
|
|
|
|
namespace ln.http
|
|
{
|
|
public abstract class HttpConnection
|
|
{
|
|
public Listener Listener { get; }
|
|
public IPEndPoint LocalEndpoint => Listener.LocalEndpoint;
|
|
public IPEndPoint RemoteEndpoint { get; }
|
|
public Stream ConnectionStream { get; }
|
|
public string Method { get; }
|
|
//public Uri RequestUri { get; }
|
|
public HttpVersion HttpVersion { get; }
|
|
|
|
public string RequestUriLine { get; set; }
|
|
|
|
public HttpConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method,
|
|
String requestUriLine, HttpVersion httpVersion)
|
|
{
|
|
Listener = listener;
|
|
RemoteEndpoint = remoteEndpoint;
|
|
ConnectionStream = connectionStream;
|
|
|
|
Method = method;
|
|
RequestUriLine = requestUriLine;
|
|
HttpVersion = httpVersion;
|
|
}
|
|
|
|
public abstract void Run();
|
|
|
|
public static string ReadLine(Stream stream) => ReadLine(stream, Encoding.ASCII);
|
|
|
|
public static string ReadLine(Stream stream, Encoding encoding)
|
|
{
|
|
if (!stream.CanRead)
|
|
return null;
|
|
|
|
byte[] line = new byte[1024];
|
|
int n = 0;
|
|
int ch;
|
|
while ((ch = stream.ReadByte()) != -1)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case '\r':
|
|
break;
|
|
case '\n':
|
|
return encoding.GetString(line, 0, n);
|
|
default:
|
|
line[n++] = (byte)ch;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (n > 0)
|
|
return encoding.GetString(line, 0, n);
|
|
|
|
return null;
|
|
}
|
|
|
|
public static bool ReadRequestLine(Stream stream, out string method, out string requestUri,
|
|
out HttpVersion httpVersion)
|
|
{
|
|
string requestLine = ReadLine(stream);
|
|
if (requestLine is null)
|
|
{
|
|
method = null;
|
|
requestUri = null;
|
|
httpVersion = HttpVersion.None;
|
|
return false;
|
|
}
|
|
|
|
int idxSpace1 = requestLine.IndexOf(' ');
|
|
int idxSpace2 = requestLine.IndexOf(' ', idxSpace1 + 1);
|
|
|
|
if ((idxSpace1 > 0) && (idxSpace2 > 0))
|
|
{
|
|
method = requestLine.Substring(0, idxSpace1);
|
|
requestUri = requestLine.Substring(idxSpace1 + 1, (idxSpace2 - idxSpace1 - 1));
|
|
string protocol = requestLine.Substring(idxSpace2 + 1);
|
|
httpVersion = HttpVersion.None;
|
|
|
|
if ("PRI".Equals(method) && Http2PrefaceUri.Equals(requestUri) && "HTTP/2.0".Equals(protocol))
|
|
httpVersion = HttpVersion.HTTP2;
|
|
else if ("HTTP/1.0".Equals(protocol))
|
|
httpVersion = HttpVersion.HTTP10;
|
|
else if ("HTTP/1.1".Equals(protocol))
|
|
httpVersion = HttpVersion.HTTP11;
|
|
|
|
return true;
|
|
}
|
|
|
|
method = null;
|
|
requestUri = null;
|
|
httpVersion = HttpVersion.None;
|
|
return false;
|
|
}
|
|
|
|
public abstract void SendResponse(HttpRequestContext requestContext);
|
|
|
|
private static string Http2PrefaceUri = "*";
|
|
}
|
|
}
|