Unified · Split
| @@ -1250,55 +1250,19 @@ namespace GSF.Communication · 1249 unmodified lines | |||
| 1250 | 1250 | ||
| 1251 | private void AddMulticastMembership(IPAddress serverAddress, IPAddress sourceAddress, out byte[] multicastMembershipAddresses) | 1251 | private void AddMulticastMembership(IPAddress serverAddress, IPAddress sourceAddress, out byte[] multicastMembershipAddresses) |
| 1252 | { | 1252 | { |
| 1253 | if (!Transport.IsMulticastIP(serverAddress)) | 1253 | multicastMembershipAddresses = null; |
| 1254 | throw new InvalidOperationException("Cannot add multicast membership if server address is not a multicast IP."); | ||
| 1255 | 1254 | ||
| 1256 | if ((object)sourceAddress == null) | 1255 | try |
| 1257 | { | ||
| 1258 | // Execute multicast subscribe for any source | ||
| 1259 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(serverAddress)); | ||
| 1260 | multicastMembershipAddresses = null; | ||
| 1261 | } | ||
| 1262 | else | ||
| 1263 | { | 1256 | { |
| 1264 | IPAddress localAddress = ((IPEndPoint)m_udpClient.Provider.LocalEndPoint).Address; | 1257 | if (!Transport.IsMulticastIP(serverAddress)) |
| 1265 | 1258 | throw new InvalidOperationException("Cannot add multicast membership if server address is not a multicast IP."); | |
| 1266 | if (sourceAddress.AddressFamily != serverAddress.AddressFamily) | ||
| 1267 | throw new InvalidOperationException(string.Format("Source address \"{0}\" is not in the same IP format as server address \"{1}\"", sourceAddress, serverAddress)); | ||
| 1268 | |||
| 1269 | if (localAddress.AddressFamily != serverAddress.AddressFamily) | ||
| 1270 | throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, serverAddress)); | ||
| 1271 | |||
| 1272 | MemoryStream membershipAddresses = new MemoryStream(); | ||
| 1273 | |||
| 1274 | byte[] serverAddressBytes = serverAddress.GetAddressBytes(); | ||
| 1275 | byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); | ||
| 1276 | byte[] localAddressBytes = localAddress.GetAddressBytes(); | ||
| 1277 | |||
| 1278 | membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length); | ||
| 1279 | membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length); | ||
| 1280 | membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); | ||
| 1281 | |||
| 1282 | multicastMembershipAddresses = membershipAddresses.ToArray(); | ||
| 1283 | |||
| 1284 | // Execute multicast subscribe for specific source | ||
| 1285 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.AddSourceMembership, multicastMembershipAddresses); | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | 1259 | ||
| 1289 | private void DropMulticastMembership(IPAddress serverAddress, IPAddress sourceAddress, byte[] multicastMembershipAddresses) | 1260 | if ((object)sourceAddress == null) |
| 1290 | { | 1261 | { |
| 1291 | if (!Transport.IsMulticastIP(serverAddress)) | 1262 | // Execute multicast subscribe for any source |
| 1292 | throw new InvalidOperationException("Cannot drop multicast membership if server address is not a multicast IP."); | 1263 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(serverAddress)); |
| 1293 | 1264 | } | |
| 1294 | if ((object)sourceAddress == null && (object)multicastMembershipAddresses == null) | 1265 | else |
| 1295 | { | ||
| 1296 | // Execute multicast unsubscribe for any source | ||
| 1297 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.DropMembership, new MulticastOption(serverAddress)); | ||
| 1298 | } | ||
| 1299 | else | ||
| 1300 | { | ||
| 1301 | if ((object)multicastMembershipAddresses == null) | ||
| 1302 | { | 1266 | { |
| 1303 | IPAddress localAddress = ((IPEndPoint)m_udpClient.Provider.LocalEndPoint).Address; | 1267 | IPAddress localAddress = ((IPEndPoint)m_udpClient.Provider.LocalEndPoint).Address; |
| 1304 | 1268 | ||
| @@ -1309,6 +1273,7 @@ namespace GSF.Communication · 4 unmodified lines | |||
| 1309 | throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, serverAddress)); | 1273 | throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, serverAddress)); |
| 1310 | 1274 | ||
| 1311 | MemoryStream membershipAddresses = new MemoryStream(); | 1275 | MemoryStream membershipAddresses = new MemoryStream(); |
| 1276 | |||
| 1312 | byte[] serverAddressBytes = serverAddress.GetAddressBytes(); | 1277 | byte[] serverAddressBytes = serverAddress.GetAddressBytes(); |
| 1313 | byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); | 1278 | byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); |
| 1314 | byte[] localAddressBytes = localAddress.GetAddressBytes(); | 1279 | byte[] localAddressBytes = localAddress.GetAddressBytes(); |
| @@ -1318,10 +1283,62 @@ namespace GSF.Communication · 3 unmodified lines | |||
| 1318 | membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); | 1283 | membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); |
| 1319 | 1284 | ||
| 1320 | multicastMembershipAddresses = membershipAddresses.ToArray(); | 1285 | multicastMembershipAddresses = membershipAddresses.ToArray(); |
| 1286 | |||
| 1287 | // Execute multicast subscribe for specific source | ||
| 1288 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.AddSourceMembership, multicastMembershipAddresses); | ||
| 1321 | } | 1289 | } |
| 1290 | } | ||
| 1291 | catch (SocketException ex) | ||
| 1292 | { | ||
| 1293 | if (ex.SocketErrorCode != SocketError.InvalidArgument) | ||
| 1294 | throw; | ||
| 1295 | } | ||
| 1296 | } | ||
| 1322 | 1297 | ||
| 1323 | // Execute multicast unsubscribe for specific source | 1298 | private void DropMulticastMembership(IPAddress serverAddress, IPAddress sourceAddress, byte[] multicastMembershipAddresses) |
| 1324 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.DropSourceMembership, multicastMembershipAddresses); | 1299 | { |
| 1300 | try | ||
| 1301 | { | ||
| 1302 | if (!Transport.IsMulticastIP(serverAddress)) | ||
| 1303 | throw new InvalidOperationException("Cannot drop multicast membership if server address is not a multicast IP."); | ||
| 1304 | |||
| 1305 | if ((object)sourceAddress == null && (object)multicastMembershipAddresses == null) | ||
| 1306 | { | ||
| 1307 | // Execute multicast unsubscribe for any source | ||
| 1308 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.DropMembership, new MulticastOption(serverAddress)); | ||
| 1309 | } | ||
| 1310 | else | ||
| 1311 | { | ||
| 1312 | if ((object)multicastMembershipAddresses == null) | ||
| 1313 | { | ||
| 1314 | IPAddress localAddress = ((IPEndPoint)m_udpClient.Provider.LocalEndPoint).Address; | ||
| 1315 | |||
| 1316 | if (sourceAddress.AddressFamily != serverAddress.AddressFamily) | ||
| 1317 | throw new InvalidOperationException(string.Format("Source address \"{0}\" is not in the same IP format as server address \"{1}\"", sourceAddress, serverAddress)); | ||
| 1318 | |||
| 1319 | if (localAddress.AddressFamily != serverAddress.AddressFamily) | ||
| 1320 | throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, serverAddress)); | ||
| 1321 | |||
| 1322 | MemoryStream membershipAddresses = new MemoryStream(); | ||
| 1323 | byte[] serverAddressBytes = serverAddress.GetAddressBytes(); | ||
| 1324 | byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); | ||
| 1325 | byte[] localAddressBytes = localAddress.GetAddressBytes(); | ||
| 1326 | |||
| 1327 | membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length); | ||
| 1328 | membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length); | ||
| 1329 | membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); | ||
| 1330 | |||
| 1331 | multicastMembershipAddresses = membershipAddresses.ToArray(); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | // Execute multicast unsubscribe for specific source | ||
| 1335 | m_udpClient.Provider.SetSocketOption(serverAddress.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.DropSourceMembership, multicastMembershipAddresses); | ||
| 1336 | } | ||
| 1337 | } | ||
| 1338 | catch (SocketException ex) | ||
| 1339 | { | ||
| 1340 | if (ex.SocketErrorCode != SocketError.InvalidArgument) | ||
| 1341 | throw; | ||
| 1325 | } | 1342 | } |
| 1326 | } | 1343 | } |
| 1327 | 1344 | ||
| @@ -937,6 +937,7 @@ namespace GSF.PhasorProtocols · 936 unmodified lines | |||
| 937 | sharedClient.ReceiveDataException += SharedClient_ReceiveDataException; | 937 | sharedClient.ReceiveDataException += SharedClient_ReceiveDataException; |
| 938 | sharedClient.ReceiveDataFrom += SharedClient_ReceiveDataFrom; | 938 | sharedClient.ReceiveDataFrom += SharedClient_ReceiveDataFrom; |
| 939 | sharedClient.SendDataException += SharedClient_SendDataException; | 939 | sharedClient.SendDataException += SharedClient_SendDataException; |
| 940 | sharedClient.UnhandledUserException += SharedClient_UnhandledUserException; | ||
| 940 | 941 | ||
| 941 | if (!sharing) | 942 | if (!sharing) |
| 942 | { | 943 | { |
| @@ -1139,6 +1140,14 @@ namespace GSF.PhasorProtocols · 196 unmodified lines | |||
| 1139 | SendDataException(this, e); | 1140 | SendDataException(this, e); |
| 1140 | } | 1141 | } |
| 1141 | 1142 | ||
| 1143 | // Shared client unhandled user exception handler. | ||
| 1144 | // Forwards event to users attached to this client. | ||
| 1145 | private void SharedClient_UnhandledUserException(object sender, EventArgs<Exception> e) | ||
| 1146 | { | ||
| 1147 | if ((object)UnhandledUserException != null) | ||
| 1148 | UnhandledUserException(this, e); | ||
| 1149 | } | ||
| 1150 | |||
| 1142 | #endregion | 1151 | #endregion |
| 1143 | 1152 | ||
| 1144 | #region [ Static ] | 1153 | #region [ Static ] |
| @@ -2527,6 +2536,7 @@ namespace GSF.PhasorProtocols · 1382 unmodified lines | |||
| 2527 | m_commandChannel.ReceiveData += m_commandChannel_ReceiveData; | 2536 | m_commandChannel.ReceiveData += m_commandChannel_ReceiveData; |
| 2528 | m_commandChannel.ReceiveDataException += m_commandChannel_ReceiveDataException; | 2537 | m_commandChannel.ReceiveDataException += m_commandChannel_ReceiveDataException; |
| 2529 | m_commandChannel.SendDataException += m_commandChannel_SendDataException; | 2538 | m_commandChannel.SendDataException += m_commandChannel_SendDataException; |
| 2539 | m_commandChannel.UnhandledUserException += m_commandChannel_UnhandledUserException; | ||
| 2530 | 2540 | ||
| 2531 | // Attempt connection to device over command channel | 2541 | // Attempt connection to device over command channel |
| 2532 | m_commandChannel.ReceiveBufferSize = m_bufferSize; | 2542 | m_commandChannel.ReceiveBufferSize = m_bufferSize; |
| @@ -2595,6 +2605,7 @@ namespace GSF.PhasorProtocols · 62 unmodified lines | |||
| 2595 | m_dataChannel.ReceiveData += m_dataChannel_ReceiveData; | 2605 | m_dataChannel.ReceiveData += m_dataChannel_ReceiveData; |
| 2596 | m_dataChannel.ReceiveDataException += m_dataChannel_ReceiveDataException; | 2606 | m_dataChannel.ReceiveDataException += m_dataChannel_ReceiveDataException; |
| 2597 | m_dataChannel.SendDataException += m_dataChannel_SendDataException; | 2607 | m_dataChannel.SendDataException += m_dataChannel_SendDataException; |
| 2608 | m_dataChannel.UnhandledUserException += m_dataChannel_UnhandledUserException; | ||
| 2598 | 2609 | ||
| 2599 | // Attempt connection to device | 2610 | // Attempt connection to device |
| 2600 | m_dataChannel.ReceiveBufferSize = m_bufferSize; | 2611 | m_dataChannel.ReceiveBufferSize = m_bufferSize; |
| @@ -2612,6 +2623,7 @@ namespace GSF.PhasorProtocols · 11 unmodified lines | |||
| 2612 | m_serverBasedDataChannel.ReceiveClientData += m_serverBasedDataChannel_ReceiveClientData; | 2623 | m_serverBasedDataChannel.ReceiveClientData += m_serverBasedDataChannel_ReceiveClientData; |
| 2613 | m_serverBasedDataChannel.ReceiveClientDataException += m_serverBasedDataChannel_ReceiveClientDataException; | 2624 | m_serverBasedDataChannel.ReceiveClientDataException += m_serverBasedDataChannel_ReceiveClientDataException; |
| 2614 | m_serverBasedDataChannel.SendClientDataException += m_serverBasedDataChannel_SendClientDataException; | 2625 | m_serverBasedDataChannel.SendClientDataException += m_serverBasedDataChannel_SendClientDataException; |
| 2626 | m_serverBasedDataChannel.UnhandledUserException += m_serverBasedDataChannel_UnhandledUserException; | ||
| 2615 | 2627 | ||
| 2616 | // Listen for device connection | 2628 | // Listen for device connection |
| 2617 | m_serverBasedDataChannel.ReceiveBufferSize = m_bufferSize; | 2629 | m_serverBasedDataChannel.ReceiveBufferSize = m_bufferSize; |
| @@ -2702,6 +2714,7 @@ namespace GSF.PhasorProtocols · 84 unmodified lines | |||
| 2702 | m_dataChannel.ReceiveData -= m_dataChannel_ReceiveData; | 2714 | m_dataChannel.ReceiveData -= m_dataChannel_ReceiveData; |
| 2703 | m_dataChannel.ReceiveDataException -= m_dataChannel_ReceiveDataException; | 2715 | m_dataChannel.ReceiveDataException -= m_dataChannel_ReceiveDataException; |
| 2704 | m_dataChannel.SendDataException -= m_dataChannel_SendDataException; | 2716 | m_dataChannel.SendDataException -= m_dataChannel_SendDataException; |
| 2717 | m_dataChannel.UnhandledUserException -= m_dataChannel_UnhandledUserException; | ||
| 2705 | m_dataChannel.Dispose(); | 2718 | m_dataChannel.Dispose(); |
| 2706 | } | 2719 | } |
| 2707 | } | 2720 | } |
| @@ -2726,6 +2739,7 @@ namespace GSF.PhasorProtocols · 18 unmodified lines | |||
| 2726 | m_serverBasedDataChannel.ReceiveClientData -= m_serverBasedDataChannel_ReceiveClientData; | 2739 | m_serverBasedDataChannel.ReceiveClientData -= m_serverBasedDataChannel_ReceiveClientData; |
| 2727 | m_serverBasedDataChannel.ReceiveClientDataException -= m_serverBasedDataChannel_ReceiveClientDataException; | 2740 | m_serverBasedDataChannel.ReceiveClientDataException -= m_serverBasedDataChannel_ReceiveClientDataException; |
| 2728 | m_serverBasedDataChannel.SendClientDataException -= m_serverBasedDataChannel_SendClientDataException; | 2741 | m_serverBasedDataChannel.SendClientDataException -= m_serverBasedDataChannel_SendClientDataException; |
| 2742 | m_serverBasedDataChannel.UnhandledUserException -= m_serverBasedDataChannel_UnhandledUserException; | ||
| 2729 | m_serverBasedDataChannel.Dispose(); | 2743 | m_serverBasedDataChannel.Dispose(); |
| 2730 | } | 2744 | } |
| 2731 | } | 2745 | } |
| @@ -2750,6 +2764,7 @@ namespace GSF.PhasorProtocols · 18 unmodified lines | |||
| 2750 | m_commandChannel.ReceiveData -= m_commandChannel_ReceiveData; | 2764 | m_commandChannel.ReceiveData -= m_commandChannel_ReceiveData; |
| 2751 | m_commandChannel.ReceiveDataException -= m_commandChannel_ReceiveDataException; | 2765 | m_commandChannel.ReceiveDataException -= m_commandChannel_ReceiveDataException; |
| 2752 | m_commandChannel.SendDataException -= m_commandChannel_SendDataException; | 2766 | m_commandChannel.SendDataException -= m_commandChannel_SendDataException; |
| 2767 | m_commandChannel.UnhandledUserException -= m_commandChannel_UnhandledUserException; | ||
| 2753 | m_commandChannel.Dispose(); | 2768 | m_commandChannel.Dispose(); |
| 2754 | } | 2769 | } |
| 2755 | } | 2770 | } |
| @@ -3415,6 +3430,14 @@ namespace GSF.PhasorProtocols · 659 unmodified lines | |||
| 3415 | OnParsingException(e.Argument, "Data channel receive exception: {0}", ex.Message); | 3430 | OnParsingException(e.Argument, "Data channel receive exception: {0}", ex.Message); |
| 3416 | } | 3431 | } |
| 3417 | 3432 | ||
| 3433 | private void m_dataChannel_UnhandledUserException(object sender, EventArgs<Exception> e) | ||
| 3434 | { | ||
| 3435 | Exception ex = e.Argument; | ||
| 3436 | |||
| 3437 | if (!(ex is NullReferenceException) && !(ex is ObjectDisposedException)) | ||
| 3438 | OnParsingException(e.Argument, "Data channel user unhandled exception: {0}", ex.Message); | ||
| 3439 | } | ||
| 3440 | |||
| 3418 | #endregion | 3441 | #endregion |
| 3419 | 3442 | ||
| 3420 | #region [ Server Based Data Channel Event Handlers ] | 3443 | #region [ Server Based Data Channel Event Handlers ] |
| @@ -3477,6 +3500,14 @@ namespace GSF.PhasorProtocols · 56 unmodified lines | |||
| 3477 | OnParsingException(e.Argument2, "Server based data channel receive exception: {0}", ex.Message); | 3500 | OnParsingException(e.Argument2, "Server based data channel receive exception: {0}", ex.Message); |
| 3478 | } | 3501 | } |
| 3479 | 3502 | ||
| 3503 | private void m_serverBasedDataChannel_UnhandledUserException(object sender, EventArgs<Exception> e) | ||
| 3504 | { | ||
| 3505 | Exception ex = e.Argument; | ||
| 3506 | |||
| 3507 | if (!(ex is NullReferenceException) && !(ex is ObjectDisposedException)) | ||
| 3508 | OnParsingException(e.Argument, "Server based data channel user unhandled exception: {0}", ex.Message); | ||
| 3509 | } | ||
| 3510 | |||
| 3480 | #endregion | 3511 | #endregion |
| 3481 | 3512 | ||
| 3482 | #region [ Command Channel Event Handlers ] | 3513 | #region [ Command Channel Event Handlers ] |
| @@ -3553,6 +3584,14 @@ namespace GSF.PhasorProtocols · 70 unmodified lines | |||
| 3553 | OnParsingException(e.Argument, "Command channel send exception: {0}", ex.Message); | 3584 | OnParsingException(e.Argument, "Command channel send exception: {0}", ex.Message); |
| 3554 | } | 3585 | } |
| 3555 | 3586 | ||
| 3587 | private void m_commandChannel_UnhandledUserException(object sender, EventArgs<Exception> e) | ||
| 3588 | { | ||
| 3589 | Exception ex = e.Argument; | ||
| 3590 | |||
| 3591 | if (!(ex is NullReferenceException) && !(ex is ObjectDisposedException)) | ||
| 3592 | OnParsingException(e.Argument, "Command channel user unhandled exception: {0}", ex.Message); | ||
| 3593 | } | ||
| 3594 | |||
| 3556 | #endregion | 3595 | #endregion |
| 3557 | 3596 | ||
| 3558 | #region [ Frame Parser Event Handlers ] | 3597 | #region [ Frame Parser Event Handlers ] |