예제 #1
0
        static Task C2S2Async(Stream stream, byte[] randomBytes, CancellationTokenSource cts, Timer timer)
        {
            timer.Change(Timeout.Infinite, Timeout.Infinite);

            var s2 = new RtmpHandshake()
            {
                Time   = (uint)Environment.TickCount,
                Time2  = 0,
                Random = randomBytes
            };

            //c2
            Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { RtmpHandshake.Read(stream, false); }) }, 3000);
            //s2
            timer.Change(SendTimeout, Timeout.Infinite);
            return(RtmpHandshake.WriteAsync(stream, s2, false, cts.Token));
        }
예제 #2
0
        static Task WriteAsync(Stream stream, RtmpHandshake h, bool writeVersion, CancellationToken ct)
        {
            using (var memoryStream = new MemoryStream())
                using (var writer = new AmfWriter(memoryStream, null))
                {
                    if (writeVersion)
                    {
                        writer.WriteByte(h.Version);
                    }

                    writer.WriteUInt32(h.Time);
                    writer.WriteUInt32(h.Time2);
                    writer.WriteBytes(h.Random);

                    var buffer = memoryStream.ToArray();
                    return(stream.WriteAsync(buffer, 0, buffer.Length, ct));
                }
        }
예제 #3
0
        async void acceptCallback(IAsyncResult ar)
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket handler  = listener.EndAccept(ar);

            handler.NoDelay = true;
            // Signal the main thread to continue.
            _manualResetEvent.Set();
            try
            {
                await RtmpHandshake.HandshakeAsync(this, handler, this.GetNewClientId(), this.Certificate);
            }
            catch (TimeoutException)
            {
                handler.Close();
            }
            catch (AuthenticationException)
            {
                handler.Close();
                throw;
            }
        }
예제 #4
0
 static void C2S2(Stream stream)
 {
     RtmpHandshake.Read(stream, false);
 }
예제 #5
0
        /// <summary>
        /// rtmp握手逻辑
        /// HandshakeAsync2
        /// c01->s01->s2->c2
        /// </summary>
        /// <param name="server"></param>
        /// <param name="client_socket"></param>
        /// <param name="client_id"></param>
        /// <param name="cert"></param>
        /// <returns></returns>
        public static async Task <int> HandshakeAsync(RtmpServer server, Socket client_socket, ushort client_id, X509Certificate2 cert = null)
        {
            Stream stream;

            if (cert != null)
            {
                var temp_stream = new SslStream(new NetworkStream(client_socket));
                try
                {
                    await temp_stream.AuthenticateAsServerAsync(cert);
                }
                catch (AuthenticationException)
                {
                    temp_stream.Close();
                    throw;
                }
                stream = temp_stream;
            }
            else
            {
                stream = new NetworkStream(client_socket);
            }

            var random = new Random(Environment.TickCount);

            var randomBytes = new byte[1528];

            random.NextBytes(randomBytes);
            client_socket.NoDelay = true;

            CancellationTokenSource cts = new CancellationTokenSource();

            //over time cancel task
            Timer timer = new Timer((s) =>
            {
                cts.Cancel();
                throw new TimeoutException("rtmp 握手已超时!");
            }, null, ReceiveTimeout, Timeout.Infinite);


            //read c0 c1
            var c01 = await RtmpHandshake.ReadAsync(stream, true, cts.Token);

            timer.Change(Timeout.Infinite, Timeout.Infinite);

            //write s0 s1
            var s01 = new RtmpHandshake()
            {
                Version = 3,
                Time    = (uint)Environment.TickCount,
                Time2   = 0,
                Random  = randomBytes
            };

            timer.Change(ReceiveTimeout, Timeout.Infinite);
            await RtmpHandshake.WriteAsync(stream, s01, true, cts.Token);

            //write s2
            random.NextBytes(randomBytes);
            await C2S2Async(stream, randomBytes, cts, timer);

            timer.Change(Timeout.Infinite, Timeout.Infinite);


            // handshake check
            //if (!c0.Random.SequenceEqual(s2.Random))
            //throw new ProtocolViolationException();

            var connect = new RtmpConnect(client_socket, stream, server, client_id, server.Context, server.AmfEncoding, true);

            connect.ChannelDataReceived += server.SendDataHandler;

            server.ClientSessions.Add(client_id, new ClientSession()
            {
                Connect    = connect,
                LastPing   = DateTime.UtcNow,
                ReaderTask = null,
                WriterTask = null
            });

            return(client_id);
        }