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.
Gateway/Mime/HttpMimeSocket.cs

227 lines
7.4 KiB
C#

using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using UMC.Net;
namespace UMC.ITME
{
public class HttpMimeSocket : HttpMime
{
public override string Scheme => "http";
public HttpMimeSocket(Socket socket, String ip)
{
this._socket = socket;
this.ActiveTime = UMC.Data.Utility.TimeSpan();
this.pid = socket.GetHashCode();
this._Host = "127.0.0.1";
this._remoteIpAddress = ip;
HttpMimeServier.httpMimes.TryAdd(pid, this);
SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
eventArgs.SetBuffer(_data);
eventArgs.Completed += Http;
if (!this._socket.ReceiveAsync(eventArgs))
{
Receive(eventArgs);
}
}
Socket _socket;
int pid = 0;
public override 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
{
_socket.Send(buffer, offset, count, SocketFlags.None);
}
catch
{
this.Dispose();
}
}
}
// UMC.Net.MimeRequest request;
private void Http(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
Receive(e);
break;
}
}
bool IsHeader = true;
private void Receive(SocketAsyncEventArgs e)
{
if (ProcessReceive(e))
{
while (this.isDispose == false && !_socket.ReceiveAsync(e))
{
if (!ProcessReceive(e))
{
break;
}
}
}
}
private bool ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
if (e.BytesTransferred > 0)
{
this.ActiveTime = UMC.Data.Utility.TimeSpan();
try
{
if (this.Request == null)
{
if (IsHeader)
{
if (this._data[0] == 0x1)
{
try
{
Subscribe(this._data, e.Offset + 1, e.BytesTransferred - 1);
}
catch (Exception ex)
{
Utility.Error("Subscribe", ex.ToString());
}
finally
{
this.Dispose();
}
return false;
}
IsHeader = true;
}
this.Request = new HttpMimeRequest(this);
}
var req = this.Request;
req.Receive(this._data, e.Offset, e.BytesTransferred);
if (req.IsHttpFormatError)
{
this.Dispose();
return false;
}
else if (this.isDispose == false)
{
return true;
}
}
catch (Exception ex)
{
this.OutText(500, ex.ToString());
return false;
}
}
return false;
}
else
{
this.Dispose();
return false;
}
}
void Subscribe(byte[] header, int offset, int size)
{
var headers = new NameValueCollection();
var ps = System.Text.Encoding.UTF8.GetString(header, offset, size).Split("\r\n", StringSplitOptions.RemoveEmptyEntries);
foreach (var s in ps)
{
var vi = s.IndexOf(':');
if (vi > 0 && vi + 2 < s.Length)
{
var key = s.Substring(0, vi);
var value = s.Substring(vi + 2);
headers.Add(key, value);
}
}
int length = 0;
var _subscribe = UMC.Net.NetSubscribe.Subscribe(headers, this._remoteIpAddress, HttpMimeServier.Server, _socket, UMC.Data.WebResource.Instance().Provider["appSecret"]);
if (_subscribe != null)
{
length += $"HTTP/1.1 101 {HttpStatusDescription.Get(101)}\r\n".WriteBytes(header, length);
length += "Connection: upgrade\r\n".WriteBytes(header, length);
length += "Upgrade: websocket\r\n".WriteBytes(header, length);
length += $"UMC-Publisher-Key: {HttpMimeServier.Server}\r\n".WriteBytes(header, length);
length += "Server: ITME\r\n\r\n".WriteBytes(header, length);
_socket.Send(header, 0, length, SocketFlags.None);
_socket = null;
}
else
{
var text = "数据订阅连接验证不通过";
length += $"HTTP/1.1 401 {HttpStatusDescription.Get(401)}\r\n".WriteBytes(header, length);
length += $"Content-Type: text/plain; charset=utf-8\r\n".WriteBytes(header, length);
length += $"Content-Length: {System.Text.Encoding.UTF8.GetByteCount(text)}\r\n".WriteBytes(header, length);
length += "Connection: close\r\n".WriteBytes(header, length);
length += "Server: ITME\r\n\r\n".WriteBytes(header, length);
length += text.WriteBytes(header, length);
_socket.Send(header, 0, length, SocketFlags.None);
}
}
bool isDispose = false;
public override void Dispose()
{
if (isDispose == false)
{
if (this._data != null)
{
System.Buffers.ArrayPool<byte>.Shared.Return(this._data);
_data = null;
}
isDispose = true;
try
{
if (this.Request is IDisposable)
{
((IDisposable)this.Request).Dispose();
}
_socket?.Shutdown(SocketShutdown.Both);
}
catch
{
}
_socket?.Close();
}
HttpMimeServier.httpMimes.TryRemove(pid, out var _);
}
byte[] _data = System.Buffers.ArrayPool<byte>.Shared.Rent(0x600);
}
}