OCPPWSServer.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. 
  2. using EVCB_OCPP.Domain;
  3. using NLog;
  4. using OCPPPackage.Profiles;
  5. using SuperWebSocket;
  6. using SuperWebSocket.SubProtocol;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Net;
  11. using System.Net.Security;
  12. using System.Security.Cryptography.X509Certificates;
  13. using System.Text;
  14. namespace OCPPServer.Protocol
  15. {
  16. public class OCPPWSServer : WebSocketServer<ClientData>
  17. {
  18. static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  19. /// <summary>
  20. /// 可允許連線Clinet數
  21. /// </summary>
  22. public int connectNum { get; set; }
  23. /// <summary>
  24. /// 是否限制連線Clinet數
  25. /// </summary>
  26. public bool beConnectLimit { get; set; }
  27. /// <summary>
  28. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  29. /// </summary>
  30. /// <param name="subProtocols">The sub protocols.</param>
  31. public OCPPWSServer(IEnumerable<ISubProtocol<ClientData>> subProtocols)
  32. : base(subProtocols)
  33. {
  34. }
  35. /// <summary>
  36. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  37. /// </summary>
  38. /// <param name="subProtocol">The sub protocol.</param>
  39. public OCPPWSServer(ISubProtocol<ClientData> subProtocol)
  40. : base(subProtocol)
  41. {
  42. }
  43. /// <summary>
  44. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  45. /// </summary>
  46. public OCPPWSServer()
  47. : base(new List<ISubProtocol<ClientData>>())
  48. {
  49. }
  50. protected override bool ValidateClientCertificate(ClientData session, object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  51. {
  52. // Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId + " ValidateClientCertificate", sslPolicyErrors));
  53. return true;
  54. // return base.ValidateClientCertificate(session, sender, certificate, chain, sslPolicyErrors);
  55. }
  56. protected override bool ValidateHandshake(ClientData session, string origin)
  57. {
  58. session.ISOCPP20 = session.SecWebSocketProtocol.ToLower().Contains("ocpp2.0");
  59. int securityProfile = 0;
  60. string authorizationKey = string.Empty;
  61. if (string.IsNullOrEmpty(session.Path))
  62. {
  63. logger.Warn("===========================================");
  64. logger.Warn("session.Path EMPTY");
  65. logger.Warn("===========================================");
  66. }
  67. string[] words = session.Path.Split('/');
  68. session.ChargeBoxId = words.Last();
  69. logger.Info(string.Format("ValidateHandshake: {0}", session.Path));
  70. bool isExistedSN = false;
  71. bool authorizated = false;
  72. using (var db = new MainDBContext())
  73. {
  74. var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id }).FirstOrDefault();
  75. session.CustomerName = machine == null ? "Unknown" : db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefault();
  76. session.CustomerId = machine == null ? Guid.Empty : machine.CustomerId;
  77. session.MachineId = machine == null ? String.Empty : machine.Id;
  78. isExistedSN = machine == null ? false : true;
  79. var configVaule = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.SecurityProfile)
  80. .Select(x => x.ConfigureSetting).FirstOrDefault();
  81. int.TryParse(configVaule, out securityProfile);
  82. if (session.ISOCPP20)
  83. {
  84. // 1.6 server only support change server function
  85. securityProfile = 0;
  86. }
  87. }
  88. if (securityProfile == 3 && session.UriScheme == "ws")
  89. {
  90. StringBuilder responseBuilder = new StringBuilder();
  91. responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1",
  92. (int)HttpStatusCode.Unauthorized, @"Unauthorized");
  93. responseBuilder.AppendWithCrCf();
  94. string sb = responseBuilder.ToString();
  95. byte[] data = Encoding.UTF8.GetBytes(sb);
  96. ((IWebSocketSession)session).SendRawData(data, 0, data.Length);
  97. return false;
  98. }
  99. if ((securityProfile == 1 || securityProfile == 2))
  100. {
  101. if (securityProfile == 2 && session.UriScheme == "ws")
  102. {
  103. authorizated = false;
  104. }
  105. if (session.Items.ContainsKey("Authorization") || session.Items.ContainsKey("authorization"))
  106. {
  107. using (var db = new MainDBContext())
  108. {
  109. authorizationKey = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.AuthorizationKey)
  110. .Select(x => x.ConfigureSetting).FirstOrDefault();
  111. if (session.ISOCPP20)
  112. {
  113. // 1.6 server only support change server function
  114. securityProfile = 0;
  115. }
  116. }
  117. logger.Info("***********Authorization ");
  118. if (!string.IsNullOrEmpty(authorizationKey))
  119. {
  120. string base64Encoded = session.Items.ContainsKey("Authorization") ? session.Items["Authorization"].ToString().Replace("Basic ", "") : session.Items["authorization"].ToString().Replace("Basic ", "");
  121. byte[] data = Convert.FromBase64String(base64Encoded);
  122. string[] base64Decoded = System.Text.ASCIIEncoding.ASCII.GetString(data).Split(':');
  123. logger.Info("***********Authorization " + System.Text.ASCIIEncoding.ASCII.GetString(data));
  124. if (base64Decoded.Count() == 2 && base64Decoded[0] == session.ChargeBoxId && base64Decoded[1] == authorizationKey)
  125. {
  126. authorizated = true;
  127. }
  128. }
  129. }
  130. else
  131. {
  132. authorizated = true;
  133. }
  134. if (!authorizated)
  135. {
  136. StringBuilder responseBuilder = new StringBuilder();
  137. responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1",
  138. (int)HttpStatusCode.Unauthorized, @"Unauthorized");
  139. responseBuilder.AppendWithCrCf();
  140. string sb = responseBuilder.ToString();
  141. byte[] data = Encoding.UTF8.GetBytes(sb);
  142. ((IWebSocketSession)session).SendRawData(data, 0, data.Length);
  143. return false;
  144. }
  145. }
  146. if (!isExistedSN)
  147. {
  148. StringBuilder responseBuilder = new StringBuilder();
  149. responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1",
  150. (int)HttpStatusCode.NotFound, @"Not Found");
  151. responseBuilder.AppendWithCrCf();
  152. string sb = responseBuilder.ToString();
  153. byte[] data = Encoding.UTF8.GetBytes(sb);
  154. ((IWebSocketSession)session).SendRawData(data, 0, data.Length);
  155. return false;
  156. }
  157. return true;
  158. }
  159. }
  160. }