简体   繁体   中英

wss WebSocket server in Mono C# : SslStream gives me no data but Stream do

Since days I'm trying to get (JS)wss/(c#)SslStream connection to work in order to create a wss server in mono c#.

My Problem : When an incomming secure WebSocket connection is accepted by the server, I can't get data from it in order to begin the handshake process.

What I did so far :

  1. I setup a TCPListener that accept the client giving me a TCPClient instance.
  2. I get the stream from the TCPClient and create a SslStream from it.
  3. I synchronously authenticate it with AuthenticateAsServer(X509Certificate2)
  4. I unsuccessfully try to read data

Other details :

  1. I note that if I use a Stream object instead of an SslStream one, I succed in getting data from it (but crypted as expected)
  2. I tested to connect my WebSoket to same adress/port to Fleck (built on my box with Monodevelop too) using the same pfx certificate and got it working properly
  3. I note also that Fleck throw messages saying it recieve 0 byte, then it close the connection and (in some way) reconnect it and get data properly from Socket/SslStream.
  4. I don't get any error, SslStream seem to be correctly authenticated
  5. I correctly connect clients in https and deal with requests on an another port in the same program

My Configuration :

  • OS : ArchLinux
  • C# : Mono .Net Framework 4.7
  • Browsers (Chromium & Firefox)

    Despite of all my research so far I've not found the solution , maybe someone can help me to wonder what I miss here ...

Thanks in advance for any help !

The listen code :

   public void AudioListen ()
    {
        audioComListener.Start ();
        while (isAudioActive) {
            TcpClient s = audioComListener.AcceptTcpClient ();
            Stream clientStream;
            string hellostr;

            clientStream = getClientStream(s);

            if(debugCommuncation)
            {
                logToFileLine("(KEY) HandShaking begins with "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
            }

            if(!WebSocketHandshake(clientStream))
            {
                if(debugCommuncation)
                {
                    logToFileLine("(KEY) (X) HandShake read 0 byte from "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
                }

                s.Close();

                return;
            }
            else
            {
                logToFileLine("(KEY) HandShaking OK with "+s.Client.RemoteEndPoint.ToString ().Split (':') [0]);
            }

            hellostr=streamReadLine(clientStream);

            if(hellostr.IndexOf("hello:")==0)
            {
                string usrstr=hellostr.Split(':')[1];
                User usr= Users.GetUser(usrstr);


                if(usr!=null)
                {
                    usr.TcpC=s;

                    User usrdest=usr.corresp;

                    if( usrdest!=null && 
                        usrdest.ByPass==null && 
                        usrdest.TcpC!=null)
                    {
                        Stream clientStream2 = getClientStream(usrdest.TcpC);
                        usr.ByPass=new TCPByPass(clientStream,clientStream2);
                        usrdest.ByPass=usr.ByPass;
                    }                       

                }
            }

            Thread.Sleep (1);
        };
    }

Function to get the SslStream :

        private Stream getClientStream(TcpClient s,bool forceHTTP=false)
    {
        Stream clientStream;
        if(isSSL && !forceHTTP)
        {
            clientStream = new SslStream (s.GetStream ());
            ((SslStream)clientStream).AuthenticateAsServer(SrvCert);
            // Set timeouts for the read and write to 5 seconds.
            /**/clientStream.ReadTimeout = 5000;
            clientStream.WriteTimeout = 5000;

            //SecuDiag.MakeAllDiag(((SslStream)clientStream));
        }
        else
        {
            clientStream=s.GetStream ();
        }     

        return clientStream;   
    }

Function that try to get data for hanshake purpose :

    public bool WebSocketHandshake(Stream clientStream)
    {
        string hellostr;

        // Here I test trying to get data (Also tried to use Stream.ReadByte())
        Byte[] toto=new Byte[2048];

        ((SslStream)clientStream).Read(toto,0,2048);

        if(toto[0]==0)return false;

        Console.WriteLine("#############################################");
        Console.WriteLine("toto array is {0} bytes long",toto.Length);
        for(int t =0;t<10;t++)
        {
            for(int u =0;u<10;u++)
            {
                Console.Write(toto[t*10+u].ToString());
            }
            Console.WriteLine(";");
        }
        Console.WriteLine("#############################################");

        // Trying to get data

        //hellostr=streamReadLine(clientStream);     

        //Console.WriteLine(hellostr);

        return true;
    }

I think I solved the problem. I don't understand why, but I think its necessary to close the accepted connection just after accepting it iaoi the connection is wss. The the websocket wil automagically reconnect :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM