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

Corrupted message from IE11, Edge when the content is larger than 1MB and sent multiple times #15

Open
Peter-Optiway opened this issue Jan 22, 2018 · 11 comments
Labels

Comments

@Peter-Optiway
Copy link

Peter-Optiway commented Jan 22, 2018

I'm using your WebSocketListener the following way:

class Program
{
    static void Main(string[] args)
    {
        CancellationTokenSource cancellation = new CancellationTokenSource();
            
        var task = Task.Run(() => RunServer(cancellation.Token));
        Console.WriteLine("Press any key to stop");
        Console.ReadKey(true);
        cancellation.Cancel();
        task.Wait();
        Console.ReadKey(true);
    }

    static async Task RunServer(CancellationToken cancellationToken)
    {
        try
        {
            var options = new WebSocketListenerOptions();
            options.Logger = new WebSocketLogger();
            options.Standards.RegisterRfc6455();
            var server = new WebSocketListener(new IPEndPoint(IPAddress.Any, 1234), options);
            await server.StartAsync();
            while (!cancellationToken.IsCancellationRequested)
            {
                var client = await server.AcceptWebSocketAsync(cancellationToken);
                Console.WriteLine("Client connected");
                while (client.IsConnected)
                {
                    var content = await client.ReadStringAsync(cancellationToken);
                    if (content == null)
                    {
                        //client disconnected
                        continue;
                    }
                    Console.WriteLine("Message received");
                    //validate content!
                    if (!Regex.IsMatch(content, @"^([0-9a-zA-Z+])*$"))
                    {
                        await client.WriteStringAsync("Content was invalid", cancellationToken);
                        Console.WriteLine("Content was invalid!");
                    }
                    else
                    {
                        await client.WriteStringAsync("Content was valid", cancellationToken);
                    }
                }
                Console.WriteLine("Client disconnected");
            }
            await server.StopAsync();
        }
        catch(Exception ex)
        {
            Console.WriteLine("Error occurred, " + ex.ToString());
        }
        finally
        {
            Console.WriteLine("Exited event loop");
        }
    }
}

class WebSocketLogger : vtortola.WebSockets.ILogger
{

    public bool IsDebugEnabled
    {
        get
        {
            return true;
        }
    }

    public bool IsWarningEnabled
    {
        get
        {
            return true;
        }
    }

    public bool IsErrorEnabled
    {
        get
        {
            return true;
        }
    }

    public void Debug(string message, Exception error = null)
    {
        Console.WriteLine(DateTime.Now.ToString("G") + " Debug " + message);
        if (error != null)
            Console.WriteLine(error.ToString());
    }

    public void Warning(string message, Exception error = null)
    {
        Console.WriteLine(DateTime.Now.ToString("G") + " Warn " + message);
        if (error != null)
            Console.WriteLine(error.ToString());
    }

    public void Error(string message, Exception error = null)
    {
        Console.WriteLine(DateTime.Now.ToString("G") + " Error " + message);
        if (error != null)
            Console.WriteLine(error.ToString());
    }
}

Then i have the following page

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Websocket tester!</title>
    <script src="assets/js/jquery.slim.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="assets/css/bootstrap.min.css" />
    <link rel="stylesheet" href="assets/css/bootstrap-theme.min.css" />
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-sm-12">
          <form id="openForm" class="form-horizontal">
            <div class="form-group">
              <label for="dataFile" class="col-sm-2 control-label">Data to spam:</label>
              <div class="col-sm-10">
                <input type="file" class="control-label" id="dataFile" />
              </div>
            </div>
              <div class="form-group">
                <label for="count" class="col-sm-2 control-label">count:</label>
                <div class="col-sm-10">
                  <input type="text" class="control-label" id="count" />
                </div>
              </div>
            <div>
              <div class="col-sm-offset-2 col-sm-10">
                <button id="send" type="submit" class="btn btn-default">Send</button>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
    <script src="assets/js/index.js"></script>
  </body>
</html>

and the following javascript file:

var openFormElement = $('#openForm');
var dataFileElement = $('#dataFile').get(0);
var countElement = $('#count');
var sendButton = $('#send');

var socket;

sendButton.click(function(e) {
  if (dataFileElement.files.length === 1) {
    var dataReader = new FileReader();
    dataReader.onload = function(dataEvent) {
      var data = dataEvent.target.result;
      //now we have the data to spam send!
      if (socket) {
        socket.close();
      }
      socket = new WebSocket("ws://localhost:1234/");
      socket.onopen = function(event) {
        console.log('connected');
        //Now we can spam!
        var count = parseInt(countElement.val());
        for (var i = 0; i < count; i++) {
          console.log('sending data');
          socket.send(data);
        }
      };
      socket.onmessage = function(event) {
        console.log('onmessage', event);
      };
      socket.onclose = function(event) {
        console.log('closed', event);
      };
      socket.onerror = function(event) {
        console.log('error', event);
      };
    };
    dataReader.readAsText(dataFileElement.files[0]);
  }
  e.stopPropagation();
  return false;
});

If i in IE or Edge:
Select the Random1MB.txt and enter 10 in the count and press send it works.
But if i use Random1.5MB.txt instead it crashes after 6 messages and the following is logged by the WebSocketListener. (Also the content is corrupted.)

2018-01-22 13:17:37 Debug (BAB87) An error occurred while async awaiting header.
vtortola.WebSockets.WebSocketException: Frame header is malformed.
   at vtortola.WebSockets.Rfc6455.WebSocketConnectionRfc6455.<ParseHeaderAsync>d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at vtortola.WebSockets.Rfc6455.WebSocketConnectionRfc6455.<AwaitHeaderAsync>d__36.MoveNext()
2018-01-22 13:17:37 Debug (BAB87) [FRAME->] ConnectionClose, len: 2, key: 0, flags: FIN
Error occurred, vtortola.WebSockets.WebSocketException: Frame header is malformed.
   at vtortola.WebSockets.Rfc6455.WebSocketConnectionRfc6455.<ParseHeaderAsync>d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at vtortola.WebSockets.Rfc6455.WebSocketConnectionRfc6455.<AwaitHeaderAsync>d__36.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at vtortola.WebSockets.Rfc6455.WebSocketConnectionRfc6455.<AwaitHeaderAsync>d__36.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at vtortola.WebSockets.Rfc6455.WebSocketRfc6455.<ReadMessageAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at vtortola.WebSockets.WebSocketStringExtensions.<ReadStringAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at WebSocketServerTest.Program.<RunServer>d__1.MoveNext() in ...\WebSocketServerTest\Program.cs:line 43

Do you have any idea what is wrong, or what i could do about it? (I'm using IE11 and Edge, but it seems to work correctly in Chrome)

Example.zip

@Peter-Optiway
Copy link
Author

It seems Edge is even more picky and crashes on everything above 0.25MB.

@deniszykov
Copy link
Owner

Hi Peter! Thanks for report, I will check it.

@Peter-Optiway
Copy link
Author

I tried the 4.1.5-alpha version and it has the same issue.

@deniszykov
Copy link
Owner

deniszykov commented Jan 24, 2018

It is ping related. As temporary workaround you could disable pings with options.PingMode = PingMode.Manual. I will investigate further.

@Peter-Optiway
Copy link
Author

Your correct, are there any downsides to not having the ping?

@deniszykov
Copy link
Owner

Without ping feature you wont notice lost client until TCP connection is terminated and error popped. TCP connection timeout varies from 30secs to 2mins,

@Peter-Optiway
Copy link
Author

Could this happen if send and receive at the same time or is this a ping specific error?

@deniszykov
Copy link
Owner

deniszykov commented Jan 24, 2018

this a ping specific error

Somehow inbound data is being corrupted when ping is sent(or pong is received). Other operations are fine.

@deniszykov deniszykov added the bug label Feb 16, 2018
@Peter-Optiway
Copy link
Author

Peter-Optiway commented Sep 25, 2018

Have you managed to find a solution for this issue?

@deniszykov
Copy link
Owner

Actually my last investigations end up here - hoaproject/Websocket#33 (comment).
There is no remedy for IE11.

@deniszykov
Copy link
Owner

But somehow default System.Net.WebSockets works fine with your example code. I will try to find implementation code for them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants