mirror of https://gitee.com/apiumc/Gateway.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
8.8 KiB
C#
314 lines
8.8 KiB
C#
using System;
|
|
using System.Buffers;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Security;
|
|
using System.Net.Sockets;
|
|
using System.Security.Authentication;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UMC.Net;
|
|
|
|
namespace UMC.Host
|
|
{
|
|
|
|
public class HttpMimeSocket : HttpMime
|
|
{
|
|
|
|
String _scheme = "http";
|
|
public override string Scheme => _scheme;
|
|
int _timeOut = 20;
|
|
public int TimeOut => _timeOut;
|
|
|
|
public HttpMimeSocket(String scheme, System.IO.Stream stream, String host, String ip)
|
|
{
|
|
_scheme = scheme;
|
|
this._stream = stream;
|
|
this.ActiveTime = UMC.Data.Utility.TimeSpan();
|
|
|
|
this.pid = stream.GetHashCode();
|
|
|
|
this._Host = host;
|
|
|
|
this._remoteIpAddress = ip;
|
|
|
|
HttpMimeServier.httpMimes.TryAdd(pid, this);
|
|
Read(new HttpMimeRequest(this));
|
|
|
|
}
|
|
Stream _stream;
|
|
int pid = 0;
|
|
public int Id => pid;
|
|
String _remoteIpAddress, _Host;
|
|
public override String Host => _Host;
|
|
public override String RemoteIpAddress => _remoteIpAddress;
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
if (isDispose == false)
|
|
{
|
|
try
|
|
{
|
|
|
|
_stream.Write(buffer, offset, count);
|
|
|
|
}
|
|
catch
|
|
{
|
|
this.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public override void OutputFinish()
|
|
{
|
|
try
|
|
{
|
|
Read(new HttpMimeRequest(this));
|
|
|
|
this.ActiveTime = UMC.Data.Utility.TimeSpan();
|
|
_timeOut = 20;
|
|
}
|
|
catch
|
|
{
|
|
this.Dispose();
|
|
}
|
|
}
|
|
public override void PrepareRespone(HttpMimeRequest httpMimeRequest)
|
|
{
|
|
_timeOut = 300;
|
|
base.PrepareRespone(httpMimeRequest);
|
|
}
|
|
public override void Subscribe(HttpMimeRequest webRequest)
|
|
{
|
|
var _subscribe = UMC.Net.NetSubscribe.Subscribe(webRequest.Headers, webRequest.UserHostAddress, HttpMimeServier.Server, _stream, UMC.Data.WebResource.Instance().Provider["appSecret"]);
|
|
if (_subscribe != null)
|
|
{
|
|
HttpMimeSocket link;
|
|
HttpMimeServier.httpMimes.TryRemove(pid, out link);
|
|
|
|
var writer = new Net.TextWriter(this.Write, _data);
|
|
writer.Write($"HTTP/1.1 101 {HttpStatusDescription.Get(101)}\r\n");
|
|
writer.Write("Connection: upgrade\r\n");
|
|
writer.Write("Upgrade: websocket\r\n");
|
|
writer.Write($"UMC-Publisher-Key: {HttpMimeServier.Server}\r\n");
|
|
writer.Write("Server: UMC.Proxy\r\n\r\n");
|
|
|
|
writer.Flush();
|
|
writer.Dispose();
|
|
_subscribe.Publish();
|
|
}
|
|
else
|
|
{
|
|
OutText(401, "连接验证不通过");
|
|
}
|
|
}
|
|
protected override void WebSocket(NetContext context)
|
|
{
|
|
if (context.Tag is HttpWebRequest)
|
|
{
|
|
var webr = context.Tag as HttpWebRequest;
|
|
this.WebSocket(webr);
|
|
}
|
|
else
|
|
{
|
|
HttpWebSocket.AcceptWebSocketAsyncCore(context, _stream);
|
|
}
|
|
}
|
|
public int ActiveTime
|
|
{
|
|
|
|
get; set;
|
|
}
|
|
bool isDispose = false;
|
|
public override void Dispose()
|
|
{
|
|
if (isDispose == false)
|
|
{
|
|
isDispose = true;
|
|
try
|
|
{
|
|
_stream.Close();
|
|
_stream.Dispose();
|
|
_data = null;
|
|
if (_webSocket != null)
|
|
{
|
|
_webSocket.Dispose();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
}
|
|
HttpMimeServier.httpMimes.TryRemove(pid, out var _);
|
|
|
|
}
|
|
async void WebSocket(HttpWebRequest webRequest)
|
|
{
|
|
try
|
|
{
|
|
var url = webRequest.RequestUri;
|
|
if (webRequest.CookieContainer != null)
|
|
{
|
|
String cookie;
|
|
if (webRequest.CookieContainer is Net.NetCookieContainer)
|
|
{
|
|
cookie = ((Net.NetCookieContainer)webRequest.CookieContainer).GetCookieHeader(url);
|
|
}
|
|
else
|
|
{
|
|
cookie = webRequest.CookieContainer.GetCookieHeader(url);
|
|
}
|
|
if (String.IsNullOrEmpty(cookie) == false)
|
|
{
|
|
webRequest.Headers[HttpRequestHeader.Cookie] = cookie;
|
|
}
|
|
}
|
|
if (String.IsNullOrEmpty(webRequest.Headers[HttpRequestHeader.Host]))
|
|
{
|
|
webRequest.Headers[HttpRequestHeader.Host] = webRequest.Host;
|
|
}
|
|
webRequest.Headers["Connection"] = "Upgrade";
|
|
|
|
|
|
var client = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
await client.ConnectAsync(url.Host, url.Port);
|
|
|
|
_webSocket = new WebSocketer();
|
|
|
|
if (url.Scheme == "https")
|
|
{
|
|
SslStream ssl = new SslStream(new NetworkStream(client, true), false, (sender, certificate, chain, sslPolicyErrors) => true);
|
|
await ssl.AuthenticateAsClientAsync(url.Host, new X509CertificateCollection(), SslProtocols.None, false);
|
|
_webSocket.stream = ssl;
|
|
}
|
|
else
|
|
{
|
|
_webSocket.stream = new NetworkStream(client, true);
|
|
|
|
}
|
|
WebSocketWrite();
|
|
await _webSocket.stream.WriteAsync(_webSocket.buffer, 0, UMC.Net.NetHttpResponse.Header(webRequest, _webSocket.buffer));
|
|
WebSocketRead();
|
|
|
|
HttpMimeServier.httpMimes.TryRemove(this.pid, out var _);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
OutText(500, ex.ToString());
|
|
}
|
|
}
|
|
|
|
class WebSocketer : IDisposable
|
|
{
|
|
public byte[] buffer = new byte[0x600];
|
|
public System.IO.Stream stream;
|
|
|
|
public void Dispose()
|
|
{
|
|
stream.Close();
|
|
stream.Dispose();
|
|
buffer = null;
|
|
|
|
}
|
|
}
|
|
WebSocketer _webSocket;
|
|
byte[] _data = new byte[0x600];
|
|
|
|
async void WebSocketRead()
|
|
{
|
|
int size = 0;
|
|
try
|
|
{
|
|
size = await _webSocket.stream.ReadAsync(_webSocket.buffer, 0, _webSocket.buffer.Length);
|
|
|
|
if (size > 0)
|
|
{
|
|
await _stream.WriteAsync(_webSocket.buffer, 0, size);
|
|
WebSocketRead();
|
|
}
|
|
else
|
|
{
|
|
this.Dispose();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
this.Dispose();
|
|
}
|
|
}
|
|
async void WebSocketWrite()
|
|
{
|
|
this.ActiveTime = UMC.Data.Utility.TimeSpan();
|
|
int size = 0;
|
|
try
|
|
{
|
|
size = await _stream.ReadAsync(this._data, 0, this._data.Length);
|
|
|
|
await _webSocket.stream.WriteAsync(_data, 0, size);
|
|
|
|
|
|
WebSocketWrite();
|
|
|
|
}
|
|
catch
|
|
{
|
|
this.Dispose();
|
|
}
|
|
}
|
|
async void Read(HttpMimeRequest req)
|
|
{
|
|
int size = 0;
|
|
try
|
|
{
|
|
size = await _stream.ReadAsync(this._data, 0, this._data.Length);
|
|
}
|
|
catch
|
|
{
|
|
this.Dispose();
|
|
return;
|
|
}
|
|
if (size > 0)
|
|
{
|
|
this.ActiveTime = UMC.Data.Utility.TimeSpan();
|
|
try
|
|
{
|
|
req.Receive(this._data, 0, size);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.OutText(500, ex.ToString());
|
|
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.Dispose();
|
|
return;
|
|
}
|
|
|
|
if (req.IsHttpFormatError)
|
|
{
|
|
req.Dispose();
|
|
this.Dispose();
|
|
return;
|
|
}
|
|
|
|
if (req.IsWebSocket == false && req.IsMimeFinish == false)
|
|
{
|
|
Read(req);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|