OCPPWSServer.cs 6.5 KB

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