Skip to content

Commit 226dd78

Browse files
Copilotromanett
andauthored
Make Network Socket in UdpPubSubConnection reachable (#3385)
* Initial plan * Add public properties to expose UDP client sockets in UdpPubSubConnection Co-authored-by: romanett <[email protected]> * Update documentation comments to be more accurate Co-authored-by: romanett <[email protected]> * Optimize property access by returning list directly instead of creating wrapper Co-authored-by: romanett <[email protected]> * Use AsReadOnly() to ensure true immutability and prevent external modification Co-authored-by: romanett <[email protected]> * Remove unused import Co-authored-by: romanett <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: romanett <[email protected]>
1 parent 2960388 commit 226dd78

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

Libraries/Opc.Ua.PubSub/Transport/UdpPubSubConnection.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,38 @@ public UdpPubSubConnection(
9595
/// </summary>
9696
public int Port { get; }
9797

98+
/// <summary>
99+
/// Gets the list of publisher UDP clients.
100+
/// Returns a read-only list of active UDP clients used for publishing.
101+
/// Can be used to configure socket settings such as ReceiveBuffer size.
102+
/// </summary>
103+
public IReadOnlyList<UdpClient> PublisherUdpClients
104+
{
105+
get
106+
{
107+
lock (Lock)
108+
{
109+
return m_publisherUdpClients.AsReadOnly();
110+
}
111+
}
112+
}
113+
114+
/// <summary>
115+
/// Gets the list of subscriber UDP clients.
116+
/// Returns a read-only list of active UDP clients used for subscribing.
117+
/// Can be used to configure socket settings such as ReceiveBuffer size.
118+
/// </summary>
119+
public IReadOnlyList<UdpClient> SubscriberUdpClients
120+
{
121+
get
122+
{
123+
lock (Lock)
124+
{
125+
return m_subscriberUdpClients.AsReadOnly();
126+
}
127+
}
128+
}
129+
98130
/// <summary>
99131
/// Perform specific Start tasks
100132
/// </summary>

Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,5 +523,95 @@ private static IPAddress GetFirstActiveNic()
523523

524524
return null;
525525
}
526+
527+
[Test(Description = "Validate UDP client socket access before connection is started")]
528+
public void ValidateUdpPubSubConnectionSocketAccessBeforeStart()
529+
{
530+
// Arrange
531+
Assert.IsNotNull(
532+
m_udpPublisherConnection,
533+
"The UADP connection from standard configuration is invalid.");
534+
535+
// Act - Access clients before connection is started
536+
IReadOnlyList<UdpClient> publisherClients = m_udpPublisherConnection.PublisherUdpClients;
537+
IReadOnlyList<UdpClient> subscriberClients = m_udpPublisherConnection.SubscriberUdpClients;
538+
539+
// Assert - Should return empty lists before connection is started
540+
Assert.IsNotNull(publisherClients, "PublisherUdpClients should not be null");
541+
Assert.IsNotNull(subscriberClients, "SubscriberUdpClients should not be null");
542+
Assert.AreEqual(0, publisherClients.Count, "PublisherUdpClients should be empty before start");
543+
Assert.AreEqual(0, subscriberClients.Count, "SubscriberUdpClients should be empty before start");
544+
}
545+
546+
[Test(Description = "Validate UDP client socket access after connection is started")]
547+
public void ValidateUdpPubSubConnectionSocketAccessAfterStart()
548+
{
549+
// Arrange
550+
Assert.IsNotNull(
551+
m_udpPublisherConnection,
552+
"The UADP connection from standard configuration is invalid.");
553+
554+
// Act - Start the connection
555+
m_udpPublisherConnection.Start();
556+
557+
try
558+
{
559+
// Access clients after connection is started
560+
IReadOnlyList<UdpClient> publisherClients = m_udpPublisherConnection.PublisherUdpClients;
561+
IReadOnlyList<UdpClient> subscriberClients = m_udpPublisherConnection.SubscriberUdpClients;
562+
563+
// Assert - Should have clients after connection is started
564+
Assert.IsNotNull(publisherClients, "PublisherUdpClients should not be null");
565+
Assert.IsNotNull(subscriberClients, "SubscriberUdpClients should not be null");
566+
567+
// Publisher should have clients since there are publishers configured
568+
if (m_udpPublisherConnection.Publishers.Count > 0)
569+
{
570+
Assert.Greater(publisherClients.Count, 0, "PublisherUdpClients should not be empty when publishers exist");
571+
572+
// Verify we can access the underlying socket
573+
foreach (UdpClient client in publisherClients)
574+
{
575+
Assert.IsNotNull(client, "UDP client should not be null");
576+
Assert.IsNotNull(client.Client, "UDP client Socket should not be null");
577+
578+
// Verify we can read socket properties (e.g., ReceiveBufferSize)
579+
int receiveBufferSize = client.Client.ReceiveBufferSize;
580+
Assert.Greater(receiveBufferSize, 0, "ReceiveBufferSize should be greater than 0");
581+
582+
m_logger.LogInformation(
583+
"Publisher UDP Socket - ReceiveBufferSize: {Size}, LocalEndPoint: {Endpoint}",
584+
receiveBufferSize,
585+
client.Client.LocalEndPoint);
586+
}
587+
}
588+
}
589+
finally
590+
{
591+
// Cleanup - Stop the connection
592+
m_udpPublisherConnection.Stop();
593+
}
594+
}
595+
596+
[Test(Description = "Validate that UDP client list is read-only")]
597+
public void ValidateUdpPubSubConnectionSocketListIsReadOnly()
598+
{
599+
// Arrange
600+
Assert.IsNotNull(
601+
m_udpPublisherConnection,
602+
"The UADP connection from standard configuration is invalid.");
603+
604+
// Act
605+
IReadOnlyList<UdpClient> publisherClients = m_udpPublisherConnection.PublisherUdpClients;
606+
IReadOnlyList<UdpClient> subscriberClients = m_udpPublisherConnection.SubscriberUdpClients;
607+
608+
// Assert - The returned collections should be read-only
609+
Assert.IsNotNull(publisherClients, "PublisherUdpClients should not be null");
610+
Assert.IsNotNull(subscriberClients, "SubscriberUdpClients should not be null");
611+
612+
// Verify that the collections are truly read-only (no Add/Remove methods exposed)
613+
Assert.IsInstanceOf<IReadOnlyList<UdpClient>>(publisherClients, "PublisherUdpClients should be IReadOnlyList");
614+
Assert.IsInstanceOf<IReadOnlyList<UdpClient>>(subscriberClients, "SubscriberUdpClients should be IReadOnlyList");
615+
}
526616
}
527617
}

0 commit comments

Comments
 (0)