Skip to content

Commit 77b25a3

Browse files
authored
Improvements in get/set socket optins (#223)
1 parent 1c59d5c commit 77b25a3

File tree

3 files changed

+110
-16
lines changed

3 files changed

+110
-16
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
using nanoFramework.TestFramework;
7+
using System;
8+
using System.Net.Sockets;
9+
10+
namespace NFUnitTestSocketTests
11+
{
12+
[TestClass]
13+
public class SocketOptionsTests
14+
{
15+
[Setup]
16+
public void SetupConnectToEthernetTests()
17+
{
18+
// Comment next line to run the tests on a real hardware
19+
Assert.SkipTest("Skipping tests using nanoCLR Win32 in a pipeline");
20+
}
21+
22+
[TestMethod]
23+
public void SocketGetSocketOptions_00()
24+
{
25+
SocketType socketType = SocketType.Stream;
26+
27+
Socket testSocket = new(
28+
AddressFamily.InterNetwork,
29+
socketType,
30+
ProtocolType.Tcp);
31+
32+
Assert.Throws(typeof(NotSupportedException), () =>
33+
{
34+
testSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.AddMembership);
35+
}, "Getting SocketOptionName.AddMembership should have thrown an exception");
36+
37+
Assert.Throws(typeof(NotSupportedException), () =>
38+
{
39+
testSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DropMembership);
40+
}, "Getting SocketOptionName.DropMembership should have thrown an exception");
41+
42+
Assert.True((SocketType)testSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Type) == socketType, "Getting SocketOptionName.Type returned a different type.");
43+
44+
testSocket?.Close();
45+
}
46+
47+
[TestMethod]
48+
public void SocketLinger()
49+
{
50+
SocketType socketType = SocketType.Stream;
51+
52+
Socket testSocket = new(
53+
AddressFamily.InterNetwork,
54+
socketType,
55+
ProtocolType.Tcp);
56+
57+
// TODO
58+
// connect to endpoint
59+
60+
// get linger option
61+
//Assert.IsType(typeof(bool), testSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger), "SocketOptionName.DontLinger should return a bool.");
62+
63+
// set DontLinger option
64+
// read back linger option
65+
// set LINGER value
66+
67+
// read back linger option
68+
69+
testSocket?.Close();
70+
}
71+
}
72+
}

Tests/SocketTests/SocketTests.nfproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<RunSettingsFilePath>$(MSBuildProjectDirectory)\nano.runsettings</RunSettingsFilePath>
2828
</PropertyGroup>
2929
<ItemGroup>
30+
<Compile Include="SocketOptionsTests.cs" />
3031
<Compile Include="SocketPair.cs" />
3132
<Compile Include="SocketExceptionsTests.cs" />
3233
<Compile Include="Properties\AssemblyInfo.cs" />

nanoFramework.System.Net/Sockets/Socket.cs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,8 @@ public int ReceiveFrom(byte[] buffer, ref EndPoint remoteEP)
869869
/// <para><see cref="Socket"/> options determine the behavior of the current <see cref="Socket"/>. For an option with a Boolean data type, specify a nonzero value to enable the option, and a
870870
/// zero value to disable the option. For an option with an integer data type, specify the appropriate value. <see cref="Socket"/> options are grouped by level of protocol support.
871871
/// </para>
872+
/// For <see cref="SocketOptionName.Linger"/> option the <paramref name="optionValue"/> it's the number of seconds that the socket will linger before closing the connection.
873+
/// To disable socket linger call <see cref="SetSocketOption(SocketOptionLevel,SocketOptionName,bool)"/> with <see cref="SocketOptionName.DontLinger"/> and setting it to <see langword="true"/>.
872874
/// </remarks>
873875
public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
874876
{
@@ -931,32 +933,33 @@ public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName opti
931933
/// <param name="optionLevel">One of the <see cref="SocketOptionLevel"/> values.</param>
932934
/// <param name="optionName">One of the <see cref="SocketOptionName"/> values.</param>
933935
/// <returns>
934-
/// An object that represents the value of the option. When the optionName parameter is set to <see cref="SocketOptionName.Linger"/> the return value is an instance of the LingerOption
935-
/// class. When optionName is set to <see cref="SocketOptionName.AddMembership"/> or <see cref="SocketOptionName.DropMembership"/>, the return value is an instance of the MulticastOption class. When optionName is
936-
/// any other value, the return value is an integer.
936+
/// <para>/// An object that represents the value of the option.</para>
937+
/// <para>
938+
/// When the <paramref name="optionName"/> parameter is set to <see cref="SocketOptionName.Linger"/> the return value is an <see cref="int"/> with the value in seconds that the socket will linger after close.
939+
/// To check if linger is enabled for the socket the <see cref="SocketOptionName.DontLinger"/> option should be queried.
940+
/// </para>
941+
/// <para>
942+
/// When optionName is set to <see cref="SocketOptionName.ExclusiveAddressUse"/>, <see cref="SocketOptionName.DontLinger"/>, <see cref="SocketOptionName.AcceptConnection"/>, <see cref="SocketOptionName.Broadcast"/> or <see cref="SocketOptionName.KeepAlive"/>, the return value is <see cref="bool"/>.
943+
/// </para>
944+
/// <para>
945+
/// When optionName is any other value, the return value is an integer.
946+
/// </para>
937947
/// </returns>
938-
/// <remarks>
939-
/// <see cref="Socket"/> options determine the behavior of the current <see cref="Socket"/>. Use this overload to get the <see cref="SocketOptionName.Linger"/>, <see cref="SocketOptionName.AddMembership"/>, and <see cref="SocketOptionName.DropMembership"/> options.
940-
/// For the <see cref="SocketOptionName.Linger"/> option, use <see cref="Socket"/> for the optionLevel parameter. For <see cref="SocketOptionName.AddMembership"/> and <see cref="SocketOptionName.DropMembership"/>, use <see cref="SocketOptionLevel.IP"/>. If you want to set the value of any of
941-
/// the options listed above, use the <see cref="SetSocketOption(SocketOptionLevel, SocketOptionName, Int32)"/> method.
942-
/// </remarks>
948+
/// <exception cref="NotSupportedException">When using an <see cref="SocketOptionName"/> that can't be retrieved.</exception>
943949
public object GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName)
944950
{
945-
if (optionName == SocketOptionName.DontLinger ||
946-
optionName == SocketOptionName.AddMembership ||
947-
optionName == SocketOptionName.DropMembership)
951+
if (optionName is SocketOptionName.AddMembership
952+
or SocketOptionName.DropMembership)
948953
{
949954
//special case linger?
950955
throw new NotSupportedException();
951956
}
952957

953958
// socket options that don't require any request to the native end
954-
if(optionLevel == SocketOptionLevel.Socket)
959+
if (optionLevel == SocketOptionLevel.Socket
960+
&& optionName == SocketOptionName.Type)
955961
{
956-
if(optionName == SocketOptionName.Type)
957-
{
958-
return _socketType;
959-
}
962+
return _socketType;
960963
}
961964

962965
// reached here: have to make a request to the lower level to get it
@@ -965,6 +968,24 @@ public object GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName op
965968

966969
GetSocketOption(optionLevel, optionName, val);
967970

971+
// process specific options
972+
if (optionName is
973+
SocketOptionName.ExclusiveAddressUse or
974+
SocketOptionName.DontLinger)
975+
{
976+
// these are boolean AND negated
977+
return val[0] == 0;
978+
}
979+
else if (optionName is
980+
SocketOptionName.AcceptConnection or
981+
SocketOptionName.Broadcast or
982+
SocketOptionName.KeepAlive)
983+
{
984+
// these are boolean
985+
return val[0] == 1;
986+
}
987+
988+
// all the others are integers
968989
int iVal = (val[0] << 0) | (val[1] << 8) | (val[2] << 16) | (val[3] << 24);
969990

970991
return iVal;

0 commit comments

Comments
 (0)