Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Pull create request] Listener logic #225

Open
notgiven688 opened this issue Apr 26, 2018 · 2 comments
Open

[Pull create request] Listener logic #225

notgiven688 opened this issue Apr 26, 2018 · 2 comments

Comments

@notgiven688
Copy link
Contributor

notgiven688 commented Apr 26, 2018

Hello!

At the moment we have some rather unnecessary "RestartAfterListenError" property in the code. In my opionion this is horrible. This property was patched in because the server socket stopped listening if an error occurred during a client connection being established.

Let us see why this happens:

(1) In WebsocketServer.cs in the Start() function we call ListenForClients(); This initiates the whole "accept new clients" logic.
(2) In ListenForClients() we call ListenerSocket.Accept(..) which itself calls the Accept method in the SocketWrapper class. Let's take a look into the corresponding code:

        public Task<ISocket> Accept(Action<ISocket> callback, Action<Exception> error)
        {
            Func<IAsyncResult, ISocket> end = r => _tokenSource.Token.IsCancellationRequested ? null : new SocketWrapper(_socket.EndAccept(r));
            var task = _taskFactory.FromAsync(_socket.BeginAccept, end, null);
            task.ContinueWith(t => callback(t.Result), TaskContinuationOptions.OnlyOnRanToCompletion)
                .ContinueWith(t => error(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
            task.ContinueWith(t => error(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
            return task;
        }

Whenever a new client connects, the client is accepted by the socket. If this succeeds we call the callback passed to this method. If it fails we call the error callback. We also call the error callback if the callback throws an error itself. Quite complicated, isn't it?

(3) okay, if everything went fine, "callback" is called after a new socket was accepted. We should now proceed to accept new/more clients. How do we do that? We call ListenForClients() within the callback method - which brings us to the beginning of this circle (2).

The flaws of this (1),(2),(3) step method is that it is rather complicated and error prone. The whole logic fails if for example an error is thrown in the callback method itself (note that the current code does not differentiate between errors from accepting new clients and errors thrown in the callback called afterwards). An example for such an error is in the line

FleckLog.Debug(String.Format("Client connected from {0}:{1}", clientSocket.RemoteIpAddress, clientSocket.RemotePort.ToString()));

in OnClientConnect() (which is the actual callback-function used). Under some circumstances clientSocket.RemoteIpAddress can throw an exception - and kills the complete server-logic. We throw an error and restart the listener socket although there was nothing wrong with the listener socket - it is just a client which maybe closed a connection really early.

Since I am too stupid to create real pull-requests someone has to do it for me. Here are my proposed changes:
https://github.com/notgiven688/Fleck/commit/79a4f995fb5aaa6204605ab641a069a8cf6a2764

and this

https://github.com/notgiven688/Fleck/commit/b3bfaa69e6edfe7788ac182b79e8d2d87f6291a2

@statianzo
Copy link
Owner

This is a great call out. I agree this is a cleaner approach than throwing away the listener for a client error. I don't have a .net environment to build this out, but would definitely accept a pull request from any other contributors. Thanks for your contribution, @notgiven688.

@darkl
Copy link
Collaborator

darkl commented Apr 27, 2018

Created pull request #226.

This was referenced Apr 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants