Skip to content

Commit f7818c5

Browse files
Christoph BauerChristoph Bauer
authored andcommitted
Tcp Keepalive for Linux (NET8.0)
New Target .NET 8.0 Fixes setup of Tcp Keepalive under Linux
1 parent 0af4d61 commit f7818c5

23 files changed

+93
-83
lines changed

src/NetMQ.Tests/ClientServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public async void AsyncWithCancellationToken()
8282
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await server.ReceiveStringAsync(source.Token));
8383
}
8484

85-
#if NETCOREAPP3_1
85+
#if NET8_0_OR_GREATER
8686

8787
[Fact(Timeout = 120)]
8888
public async void AsyncEnumerableCanceled()

src/NetMQ/Annotations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information.
22

3-
#if !NETSTANDARD2_1
3+
#if !NETSTANDARD2_1 && !NET8_0_OR_GREATER
44

55
namespace System.Diagnostics.CodeAnalysis
66
{

src/NetMQ/AsyncReceiveExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47
1+
#if NET8_0_OR_GREATER || NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47
22

33
using System;
44
using System.Collections.Generic;

src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ PullMsgResult ProduceInitiate(ref Msg msg)
189189

190190
VouchNoncePrefix.CopyTo(vouchNonce);
191191
using var rng = RandomNumberGenerator.Create();
192-
#if NETSTANDARD2_1
192+
#if NET8_0_OR_GREATER || NETSTANDARD2_1
193193
rng.GetBytes(vouchNonce.Slice(8));
194194
#else
195195
byte[] temp = new byte[16];

src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ PullMsgResult ProduceWelcome(ref Msg msg)
157157
// 8-byte prefix plus 16-byte random nonce
158158
CookieNoncePrefix.CopyTo(cookieNonce);
159159
using var rng = RandomNumberGenerator.Create();
160-
#if NETSTANDARD2_1
160+
#if NET8_0_OR_GREATER || NETSTANDARD2_1
161161
rng.GetBytes(cookieNonce.Slice(8));
162162
#else
163163
byte[] temp = new byte[16];
@@ -184,7 +184,7 @@ PullMsgResult ProduceWelcome(ref Msg msg)
184184
// Create full nonce for encryption
185185
// 8-byte prefix plus 16-byte random nonce
186186
WelcomeNoncePrefix.CopyTo(welcomeNonce);
187-
#if NETSTANDARD2_1
187+
#if NET8_0_OR_GREATER || NETSTANDARD2_1
188188
rng.GetBytes(welcomeNonce.Slice(8));
189189
#else
190190
rng.GetBytes(temp);

src/NetMQ/Core/Transports/Pgm/PgmSocket.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ internal void Init()
9797
Debug.WriteLine(xMsg);
9898

9999
// If running on Microsoft Windows, suggest to the developer that he may need to install MSMQ in order to get PGM socket support.
100-
#if NETSTANDARD1_1_OR_GREATER
100+
#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER
101101
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
102102
#else
103103
bool isWindows = true;

src/NetMQ/Core/Transports/Tcp/TcpConnector.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ public void OutCompleted(SocketError socketError, int bytesTransferred)
250250

251251
if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1)
252252
{
253+
#if NET8_0_OR_GREATER
254+
if (m_options.TcpKeepaliveIdle != -1)
255+
m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000);
256+
if (m_options.TcpKeepaliveIntvl != -1)
257+
m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000);
258+
#else
253259
// Write the TCP keep-alive options to a byte-array, to feed to the IOControl method..
254260
var bytes = new ByteArraySegment(new byte[12]);
255261

@@ -260,6 +266,7 @@ public void OutCompleted(SocketError socketError, int bytesTransferred)
260266
bytes.PutInteger(endian, m_options.TcpKeepaliveIntvl, 8);
261267

262268
m_s.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null);
269+
#endif
263270
}
264271
}
265272

src/NetMQ/Core/Transports/Tcp/TcpListener.cs

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ You should have received a copy of the GNU Lesser General Public License
2222
using System;
2323
using System.Diagnostics;
2424
using System.Net.Sockets;
25-
#if NETSTANDARD2_0 || NETSTANDARD2_1
25+
#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1
2626
using System.Runtime.InteropServices;
2727
#endif
2828
using AsyncIO;
@@ -45,12 +45,12 @@ internal class TcpListener : Own, IProactorEvents
4545
/// </summary>
4646
private AsyncSocket? m_handle;
4747

48-
/*
49-
/// <summary>
50-
/// socket being accepted
51-
/// </summary>
52-
private AsyncSocket m_acceptedSocket;
53-
*/
48+
/*
49+
/// <summary>
50+
/// socket being accepted
51+
/// </summary>
52+
private AsyncSocket m_acceptedSocket;
53+
*/
5454

5555
/// <summary>
5656
/// Socket the listener belongs to.
@@ -107,7 +107,7 @@ protected override void ProcessPlug()
107107
protected override void ProcessTerm(int linger)
108108
{
109109
Assumes.NotNull(m_handle);
110-
110+
111111
m_ioObject.SetHandler(this);
112112
m_ioObject.RemoveSocket(m_handle);
113113
Close();
@@ -141,7 +141,7 @@ public virtual void SetAddress(string addr)
141141
}
142142
}
143143

144-
#if NETSTANDARD2_0 || NETSTANDARD2_1
144+
#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1
145145
// This command is failing on linux
146146
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
147147
m_handle.ExclusiveAddressUse = false;
@@ -194,68 +194,75 @@ public void InCompleted(SocketError socketError, int bytesTransferred)
194194
switch (socketError)
195195
{
196196
case SocketError.Success:
197-
{
198-
// TODO: check TcpFilters
199-
var acceptedSocket = m_handle.GetAcceptedSocket();
197+
{
198+
// TODO: check TcpFilters
199+
var acceptedSocket = m_handle.GetAcceptedSocket();
200200

201201
acceptedSocket.NoDelay = true;
202202

203-
if (m_options.TcpKeepalive != -1)
204-
{
205-
acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive);
206-
207-
if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1)
203+
if (m_options.TcpKeepalive != -1)
208204
{
209-
var bytes = new ByteArraySegment(new byte[12]);
205+
acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive);
206+
207+
if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1)
208+
{
209+
#if NET8_0_OR_GREATER
210+
if (m_options.TcpKeepaliveIdle != -1)
211+
acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000);
212+
if (m_options.TcpKeepaliveIntvl != -1)
213+
acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000);
214+
#else
215+
var bytes = new ByteArraySegment(new byte[12]);
210216

211-
Endianness endian = BitConverter.IsLittleEndian ? Endianness.Little : Endianness.Big;
217+
Endianness endian = BitConverter.IsLittleEndian ? Endianness.Little : Endianness.Big;
212218

213-
bytes.PutInteger(endian, m_options.TcpKeepalive, 0);
214-
bytes.PutInteger(endian, m_options.TcpKeepaliveIdle, 4);
215-
bytes.PutInteger(endian, m_options.TcpKeepaliveIntvl, 8);
219+
bytes.PutInteger(endian, m_options.TcpKeepalive, 0);
220+
bytes.PutInteger(endian, m_options.TcpKeepaliveIdle, 4);
221+
bytes.PutInteger(endian, m_options.TcpKeepaliveIntvl, 8);
216222

217-
acceptedSocket.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null);
223+
acceptedSocket.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null);
224+
#endif
225+
}
218226
}
219-
}
220227

221-
// Create the engine object for this connection.
222-
var engine = new StreamEngine(acceptedSocket, m_options, m_endpoint);
228+
// Create the engine object for this connection.
229+
var engine = new StreamEngine(acceptedSocket, m_options, m_endpoint);
223230

224-
// Choose I/O thread to run connector in. Given that we are already
225-
// running in an I/O thread, there must be at least one available.
226-
IOThread? ioThread = ChooseIOThread(m_options.Affinity);
231+
// Choose I/O thread to run connector in. Given that we are already
232+
// running in an I/O thread, there must be at least one available.
233+
IOThread? ioThread = ChooseIOThread(m_options.Affinity);
227234

228-
Assumes.NotNull(ioThread);
235+
Assumes.NotNull(ioThread);
229236

230-
// Create and launch a session object.
231-
// TODO: send null in address parameter, is unneeded in this case
232-
SessionBase session = SessionBase.Create(ioThread, false, m_socket, m_options, new Address(m_handle.LocalEndPoint));
233-
session.IncSeqnum();
234-
LaunchChild(session);
237+
// Create and launch a session object.
238+
// TODO: send null in address parameter, is unneeded in this case
239+
SessionBase session = SessionBase.Create(ioThread, false, m_socket, m_options, new Address(m_handle.LocalEndPoint));
240+
session.IncSeqnum();
241+
LaunchChild(session);
235242

236-
SendAttach(session, engine, false);
243+
SendAttach(session, engine, false);
237244

238-
m_socket.EventAccepted(m_endpoint, acceptedSocket);
245+
m_socket.EventAccepted(m_endpoint, acceptedSocket);
239246

240-
Accept();
241-
break;
242-
}
247+
Accept();
248+
break;
249+
}
243250
case SocketError.ConnectionReset:
244251
case SocketError.NoBufferSpaceAvailable:
245252
case SocketError.TooManyOpenSockets:
246-
{
247-
m_socket.EventAcceptFailed(m_endpoint, socketError.ToErrorCode());
253+
{
254+
m_socket.EventAcceptFailed(m_endpoint, socketError.ToErrorCode());
248255

249-
Accept();
250-
break;
251-
}
256+
Accept();
257+
break;
258+
}
252259
default:
253-
{
254-
NetMQException exception = NetMQException.Create(socketError);
260+
{
261+
NetMQException exception = NetMQException.Create(socketError);
255262

256-
m_socket.EventAcceptFailed(m_endpoint, exception.ErrorCode);
257-
throw exception;
258-
}
263+
m_socket.EventAcceptFailed(m_endpoint, exception.ErrorCode);
264+
throw exception;
265+
}
259266
}
260267
}
261268

src/NetMQ/Core/Utils/OpCode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static bool Open()
2020
string val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC");
2121
if (!string.IsNullOrEmpty(val))
2222
return false;
23-
#if NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER
23+
#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER
2424
if (RuntimeInformation.ProcessArchitecture != Architecture.X86 &&
2525
RuntimeInformation.ProcessArchitecture != Architecture.X64)
2626
{

src/NetMQ/Core/Utils/SpanUtility.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal static class SpanUtility
77
{
88
public static string ToAscii(Span<byte> bytes)
99
{
10-
#if NETSTANDARD2_1
10+
#if NET8_0_OR_GREATER || NETSTANDARD2_1
1111
return Encoding.ASCII.GetString(bytes);
1212
#else
1313
return Encoding.ASCII.GetString(bytes.ToArray());

0 commit comments

Comments
 (0)