zeromq / netmq

A 100% native C# implementation of ZeroMQ for .NET
Other
2.94k stars 742 forks source link

Curve support on ROUTERSOCKET as Server and DEALERSOCKET as Client not working as expected #1045

Closed StylesGumede closed 1 year ago

StylesGumede commented 1 year ago

Environment

NetMQ Version:    4.0.1.10
Operating System: Windows 10 Home
.NET Version:     6

Expected behaviour

Hi everyone, I’ve noted an issue with regards to Curve functionality when using a RouterSocket as the server and DealerSocket as the client. The expected behaviour is for successful curve functionality when using a the above mentioned sockets.

Actual behaviour + Steps to reproduce the behaviour

To simplify this issue, I based my proofing using the test found at the following source path https://github.com/zeromq/netmq/blob/master/src/NetMQ.Tests/CurveTests.cs

The above test uses a DealerSocket for both Client and Server to prove the curve functionality (the test PASSES). As per below:

    [Fact]
    public void CurveTest()
    {
        var serverPair = new NetMQCertificate();
        using var server = new DealerSocket();
        server.Options.CurveServer = true;
        server.Options.CurveCertificate = serverPair;
        server.Bind($"tcp://127.0.0.1:55367");

        var clientPair = new NetMQCertificate();
        using var client = new DealerSocket();
        client.Options.CurveServerKey = serverPair.PublicKey;
        client.Options.CurveCertificate = clientPair;
        client.Connect("tcp://127.0.0.1:55367");

        for (int i = 0; i < 100; i++)
        {
            client.SendFrame("Hello");
            var hello = server.ReceiveFrameString();
            Assert.Equal("Hello", hello);

            server.SendFrame("World");
            var world = client.ReceiveFrameString();
            Assert.Equal("World", world);
        }

    }

If you replace the SERVER DealerSocket with a RouterSocket and run the same test, the test fails.

[Fact]
public void CurveTest()
{
    var serverPair = new NetMQCertificate();
    using var server = new RouterSocket();
    server.Options.CurveServer = true;
    server.Options.CurveCertificate = serverPair;
    server.Bind($"tcp://127.0.0.1:55367");

    var clientPair = new NetMQCertificate();
    using var client = new DealerSocket();
    client.Options.CurveServerKey = serverPair.PublicKey;
    client.Options.CurveCertificate = clientPair;
    client.Connect("tcp://127.0.0.1:55367");

    for (int i = 0; i < 100; i++)
    {
        client.SendFrame("Hello");
        var hello = server.ReceiveFrameString();
        Assert.Equal("Hello", hello);

        server.SendFrame("World");
        var world = client.ReceiveFrameString();
        Assert.Equal("World", world);
    }
}
dxdjgl commented 1 year ago

Router socket seems to work fine, but be aware Dealer and Router socket does not behave in the same way. Check out RouterTests.cs for inspiration, below code is adjusted to Router socket bahaviour.

[Fact] public void CurveTest() { var serverPair = new NetMQCertificate(); using var server = new RouterSocket(); server.Options.CurveServer = true; server.Options.CurveCertificate = serverPair; server.Bind($"tcp://127.0.0.1:55367");

        var clientPair = new NetMQCertificate();
        using var client = new DealerSocket();
        client.Options.CurveServerKey = serverPair.PublicKey;
        client.Options.CurveCertificate = clientPair;
        client.Connect("tcp://127.0.0.1:55367");

        for (int i = 0; i < 100; i++)
        {
            client.SendFrame("Hello");
            var hello = server.ReceiveMultipartMessage();
            Assert.Equal("Hello", hello.Last.ConvertToString());

            var worldMsg = new NetMQMessage();
            worldMsg.Append(hello.First);
            worldMsg.Append(new NetMQFrame("World"));

            server.SendMultipartMessage(worldMsg);
            var world = client.ReceiveFrameString();
            Assert.Equal("World", world);
        }
    }