Example #1
0
        public RtmpConnect(Socket client_socket, Stream stream, RtmpServer server, ushort clientID, SerializationContext context, ObjectEncoding objectEncoding = ObjectEncoding.Amf0, bool asyncMode = false)
        {
            ClientID = clientID;

            this._clientSocket = client_socket;

            this._server         = server;
            this._objectEncoding = objectEncoding;

            Writer = new RtmpPacketWriter(new AmfWriter(stream, context, ObjectEncoding.Amf0, asyncMode), ObjectEncoding.Amf0);
            Reader = new RtmpPacketReader(new AmfReader(stream, context, asyncMode));

            Reader.EventReceived += EventReceivedCallback;
            Reader.Disconnected  += OnPacketProcessorDisconnected;
            Writer.Disconnected  += OnPacketProcessorDisconnected;

            _callbackManager = new TaskCallbackManager <int, object>();
        }
        /// <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);
        }