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.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.Shared.Rent(0x600); } }