using EVCB_OCPP.Domain; using SuperSocket.Common; using SuperWebSocket; using SuperWebSocket.SubProtocol; using System; using System.Collections.Generic; using System.Linq; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; namespace OCPPServer.Protocol { public class OCPPWSServer : WebSocketServer { /// /// 可允許連線Clinet數 /// public int connectNum { get; set; } /// /// 是否限制連線Clinet數 /// public bool beConnectLimit { get; set; } /// /// Initializes a new instance of the class. /// /// The sub protocols. public OCPPWSServer(IEnumerable> subProtocols) : base(subProtocols) { } /// /// Initializes a new instance of the class. /// /// The sub protocol. public OCPPWSServer(ISubProtocol subProtocol) : base(subProtocol) { } /// /// Initializes a new instance of the class. /// public OCPPWSServer() : base(new List>()) { } protected override bool ValidateClientCertificate(ClientData session, object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId+" ValidateClientCertificate", sslPolicyErrors)); return true; // return base.ValidateClientCertificate(session, sender, certificate, chain, sslPolicyErrors); } protected override bool ValidateHandshake(ClientData session, string origin) { string[] words = session.Path.Split('/'); session.ChargeBoxId = words.Last(); bool isExistedSN = false; using (var db = new MainDBContext()) { var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault(); isExistedSN = machine == null ? false : true; } if(!isExistedSN) { byte[] m_SwitchResponse; var responseBuilder = new StringBuilder(); responseBuilder.AppendWithCrCf("HTTP/1.1 403"); //403 Forbidden : 用戶端並無訪問權限,所以伺服器給予應有的回應。 responseBuilder.AppendWithCrCf("Upgrade: WebSocket"); responseBuilder.AppendWithCrCf("Connection: Upgrade"); responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion); responseBuilder.AppendWithCrCf(); m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString()); session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length); return false; } else { //確認電樁連線所送的SubProtocol是否被Server支援 if (!session.SecWebSocketProtocol.ToLower().Contains("ocpp1.6")) { const string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; const string SecWebSocketKey = "Sec-WebSocket-Key"; const string ResponseHeadLine10 = "HTTP/1.1 101 Switching Protocols"; const string Upgrade = "Upgrade"; const string ResponseUpgradeLine = Upgrade + ": WebSocket"; const string Connection = "Connection"; const string ResponseConnectionLine = Connection + ": Upgrade"; const string ResponseAcceptLine = "Sec-WebSocket-Accept: {0}"; var responseBuilder = new StringBuilder(); var secWebSocketKey = session.Items.GetValue(SecWebSocketKey, string.Empty); if (string.IsNullOrEmpty(secWebSocketKey)) { return false; } string secKeyAccept = string.Empty; try { secKeyAccept = Convert.ToBase64String(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(secWebSocketKey + m_Magic))); } catch (Exception) { return false; } responseBuilder.AppendWithCrCf(ResponseHeadLine10); responseBuilder.AppendWithCrCf(ResponseUpgradeLine); responseBuilder.AppendWithCrCf(ResponseConnectionLine); responseBuilder.AppendFormatWithCrCf(ResponseAcceptLine, secKeyAccept); responseBuilder.AppendWithCrCf(); byte[] data = Encoding.UTF8.GetBytes(responseBuilder.ToString()); session.SendRawData(data, 0, data.Length); session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This SubProtocol can't be supported."); return false; } } return true; } } }