示例#1
0
 public void Stop()
 {
     Started = false;
     foreach (var current in connects)
     {
         StreamConnectState state     = current.Value;
         ushort             client_id = current.Key;
         IStreamConnect     connect   = state.Connect;
         if (connect.IsDisconnected)
         {
             continue;
         }
         try
         {
             Close(client_id);
         }
         catch (Exception e)
         {
             Console.WriteLine(e.StackTrace);
         }
     }
     connects.Clear();
     allocated_client_id.Clear();
     allocated_stream_id.Clear();
     listener.Close();
 }
示例#2
0
        internal void SendMetadata(string app, string path, IStreamConnect self, bool flvHeader = false)
        {
            ushort             client_id;
            StreamConnectState state;
            IStreamConnect     connect;
            var uri = new Uri("http://127.0.0.1/" + path);
            var key = new Tuple <string, string>(app, uri.AbsolutePath);

            if (!clientRoute.TryGetValue(key, out client_id))
            {
                throw new KeyNotFoundException("Request Path Not Found");
            }
            if (!connects.TryGetValue(client_id, out state))
            {
                clientRoute.Remove(key);
                throw new KeyNotFoundException("Request Client Not Exists");
            }
            connect = state.Connect;
            if (connect.IsPublishing)
            {
                var flv_metadata = (Dictionary <string, object>)connect.FlvMetaData.MethodCall.Parameters[0];
                var has_audio    = flv_metadata.ContainsKey("audiocodecid");
                var has_video    = flv_metadata.ContainsKey("videocodecid");
                if (flvHeader)
                {
                    var header_buffer = Enumerable.Repeat <byte>(0x00, 13).ToArray <byte>();
                    header_buffer[0] = 0x46;
                    header_buffer[1] = 0x4C;
                    header_buffer[2] = 0x56;
                    header_buffer[3] = 0x01;
                    byte has_audio_flag = 0x01 << 2;
                    byte has_video_flag = 0x01;
                    byte type_flag      = 0x00;
                    if (has_audio)
                    {
                        type_flag |= has_audio_flag;
                    }
                    if (has_video)
                    {
                        type_flag |= has_video_flag;
                    }
                    header_buffer[4] = type_flag;
                    var data_offset = BitConverter.GetBytes((uint)9);
                    header_buffer[5] = data_offset[3];
                    header_buffer[6] = data_offset[2];
                    header_buffer[7] = data_offset[1];
                    header_buffer[8] = data_offset[0];
                    self.SendRawData(header_buffer);
                }
                self.SendAmf0Data(connect.FlvMetaData);
                if (has_audio)
                {
                    self.SendAmf0Data(connect.AACConfigureRecord);
                }
                if (has_video)
                {
                    self.SendAmf0Data(connect.AvCConfigureRecord);
                }
            }
        }
示例#3
0
        public void Close(ushort client_id)
        {
            allocated_client_id.Remove(client_id);
            allocated_stream_id.Remove(client_id);

            StreamConnectState state;

            connects.TryGetValue(client_id, out state);
            IStreamConnect connect = state.Connect;

            prepare_to_remove.Add(client_id);

            if (connect.IsPublishing)
            {
                UnRegisterPublish(client_id);
            }
            if (connect.IsPlaying)
            {
                var client_channels = routedClients.FindAll((t) => (t.Item1 == client_id || t.Item2 == client_id));
                routedClients.RemoveAll((t) => (t.Item1 == client_id));
                foreach (var i in client_channels)
                {
                    routedClients.Remove(i);
                }
            }
            connect.OnDisconnected(new ExceptionalEventArgs("disconnected"));
        }
示例#4
0
        void DisconnectSession(ushort client_id)
        {
            ClientSession clientSession;

            if (ClientSessions.TryGetValue(client_id, out clientSession))
            {
                if (clientSession != null)
                {
                    IStreamConnect client = clientSession.Connect;

                    if (client.IsPublishing)
                    {
                        UnRegisterPublish(client_id);
                    }

                    if (client.IsPlaying)
                    {
                        var client_channels = _routedClients.FindAll((t) => (t.Item1 == client_id || t.Item2 == client_id));
                        _routedClients.RemoveAll((t) => (t.Item1 == client_id));
                        foreach (var i in client_channels)
                        {
                            _routedClients.Remove(i);
                        }
                    }
                    client.OnDisconnected(new ExceptionalEventArgs("disconnected"));
                }
            }

            ClientSessions.Remove(client_id);
        }
示例#5
0
        internal void ConnectToClient(string app, string path, ushort self_id, ChannelType channel_type)
        {
            StreamConnectState state;
            ushort             client_id;
            var uri = new Uri("http://127.0.0.1/" + path);
            var key = new Tuple <string, string>(app, uri.AbsolutePath);

            if (!clientRoute.TryGetValue(key, out client_id))
            {
                throw new KeyNotFoundException("Request Path Not Found");
            }
            if (!connects.TryGetValue(client_id, out state))
            {
                IStreamConnect connect = state.Connect;
                clientRoute.Remove(key);
                throw new KeyNotFoundException("Request Client Not Exists");
            }

            routedClients.Add(new Tuple <ushort, ushort, ChannelType>(self_id, client_id, channel_type));
        }
示例#6
0
        public void Stop()
        {
            try
            {
                Started = false;

                ClientSessionDictionary nClientSessions = null;

                lock (_locker)
                {
                    nClientSessions = ClientSessions.Clone() as ClientSessionDictionary;
                }

                foreach (var current in nClientSessions)
                {
                    ClientSession  state     = current.Value;
                    ushort         client_id = current.Key;
                    IStreamConnect connect   = state.Connect;
                    if (connect.IsDisconnected)
                    {
                        continue;
                    }
                    try
                    {
                        DisconnectSession(client_id);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.StackTrace);
                    }
                }
                lock (_locker)
                {
                    ClientSessions.Clear();
                }
                _listener.Close();
            }
            catch { }
        }
示例#7
0
        internal bool UnRegisterPublish(ushort clientId)
        {
            var key = clientRoute.First(x => x.Value == clientId).Key;
            StreamConnectState state;

            if (clientRoute.ContainsKey(key))
            {
                if (connects.TryGetValue(clientId, out state))
                {
                    IStreamConnect connect = state.Connect;
                    connect.ChannelDataReceived -= sendDataHandler;

                    var clients = routedClients.FindAll(t => t.Item2 == clientId);
                    foreach (var i in clients)
                    {
                        Close(i.Item1);
                    }
                    routedClients.RemoveAll(t => t.Item2 == clientId);
                }
                clientRoute.Remove(key);
                return(true);
            }
            return(false);
        }
示例#8
0
        internal void ConnectToClient(string liveChannel, string path, ushort clientID, ChannelType channel_type)
        {
            ClientSession clientSession;

            ushort cachedClientID;

            var uri = new Uri("http://127.0.0.1/" + path);

            var key = new Tuple <string, string>(liveChannel, uri.AbsolutePath);

            if (!_clientRouteTable.TryGetValue(key, out cachedClientID))
            {
                throw new KeyNotFoundException("请求地址不存在~");
            }

            if (!ClientSessions.TryGetValue(cachedClientID, out clientSession))
            {
                IStreamConnect connect = clientSession.Connect;
                _clientRouteTable.Remove(key);
                throw new KeyNotFoundException("请求客户端不存在~");
            }

            _routedClients.Add(new Tuple <ushort, ushort, ChannelType>(clientID, cachedClientID, channel_type));
        }
示例#9
0
        public RtmpServer(
            SerializationContext context,
            X509Certificate2 cert                      = null,
            ObjectEncoding object_encoding             = ObjectEncoding.Amf0,
            ParameterAuthCallback publishParameterAuth = null,
            ParameterAuthCallback playParameterAuth    = null,
            string bindIp         = "0.0.0.0",
            int bindRtmpPort      = 1935,
            int bindWebsocketPort = -1
            )
        {
            this.context   = context;
            objectEncoding = object_encoding;
            if (bindWebsocketPort != -1)
            {
                var server = new WebSocketServer("ws://" + bindIp.ToString() + ":" + bindWebsocketPort.ToString());
                if (cert != null)
                {
                    this.cert                  = cert;
                    server.Certificate         = cert;
                    server.EnabledSslProtocols = SslProtocols.Default;
                }
                server.ListenerSocket.NoDelay = true;
                server.Start(socket =>
                {
                    socket.OnOpen = () =>
                    {
                        var path = socket.ConnectionInfo.Path.Split('/');
                        if (path.Length != 3)
                        {
                            socket.Close();
                        }
                        ushort client_id       = GetNewClientId();
                        IStreamConnect connect = new WebsocketConnect(socket, context, object_encoding);
                        lock (connects)
                        {
                            connects.Add(client_id, new StreamConnectState()
                            {
                                Connect    = connect,
                                LastPing   = DateTime.UtcNow,
                                ReaderTask = null,
                                WriterTask = null
                            });
                        }
                        try
                        {
                            SendMetadata(path[1], path[2], connect, flvHeader: true);

                            ConnectToClient(path[1], path[2], client_id, ChannelType.Audio);
                            ConnectToClient(path[1], path[2], client_id, ChannelType.Video);
                        }
                        catch { Close(client_id); }
                    };
                    socket.OnPing = b => socket.SendPong(b);
                });
            }

            if (publishParameterAuth != null)
            {
                this.publishParameterAuth = publishParameterAuth;
            }
            if (playParameterAuth != null)
            {
                this.playParameterAuth = playParameterAuth;
            }
            ioThread = new Thread(() =>
            {
                while (true)
                {
                    foreach (var current in connects)
                    {
                        StreamConnectState state = current.Value;
                        ushort client_id         = current.Key;
                        IStreamConnect connect   = state.Connect;
                        if (connect.IsDisconnected)
                        {
                            Close(client_id);
                            continue;
                        }
                        try
                        {
                            if (state.WriterTask == null || state.WriterTask.IsCompleted)
                            {
                                state.WriterTask = connect.WriteOnceAsync();
                            }
                            if (state.WriterTask.IsCanceled || state.WriterTask.IsFaulted)
                            {
                                throw state.WriterTask.Exception;
                            }
                            if (state.LastPing == null || DateTime.UtcNow - state.LastPing >= new TimeSpan(0, 0, PingPeriod))
                            {
                                connect.PingAsync(PingTimeout);
                                state.LastPing = DateTime.UtcNow;
                            }


                            if (state.ReaderTask == null || state.ReaderTask.IsCompleted)
                            {
                                state.ReaderTask = connect.ReadOnceAsync();
                            }
                            if (state.ReaderTask.IsCanceled || state.ReaderTask.IsFaulted)
                            {
                                throw state.ReaderTask.Exception;
                            }
                        }
                        catch
                        {
                            Close(client_id);
                            continue;
                        }
                    }
                    var prepare_add_length = prepare_to_add.Count;
                    if (prepare_add_length != 0)
                    {
                        for (int i = 0; i < prepare_add_length; i++)
                        {
                            var current = prepare_to_add[0];
                            connects.Add(current.Key, current.Value);
                            prepare_to_add.RemoveAt(0);
                        }
                    }


                    var prepare_remove_length = prepare_to_remove.Count;
                    if (prepare_remove_length != 0)
                    {
                        for (int i = 0; i < prepare_remove_length; i++)
                        {
                            var current = prepare_to_remove[0];
                            connects.Remove(current);
                            prepare_to_remove.RemoveAt(0);
                        }
                    }
                }
            })
            {
                IsBackground = true
            };

            ioThread.Start();

            listener         = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listener.NoDelay = true;
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(bindIp), bindRtmpPort);

            listener.Bind(localEndPoint);
            listener.Listen(10);
        }
示例#10
0
        /// <summary>
        /// 启动连接状态检查线程
        /// 执行rtmp的读写异步任务
        /// </summary>
        void ClientWorkHandler()
        {
            _clientWorkThread = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        if (ClientSessions.Count() < 1)
                        {
                            Thread.Sleep(1);
                            continue;
                        }

                        ClientSessionDictionary nclientSessions = null;

                        lock (_locker)
                        {
                            nclientSessions = ClientSessions.Clone() as ClientSessionDictionary;
                        }

                        Parallel.ForEach(nclientSessions, current =>
                        {
                            ClientSession state    = current.Value;
                            ushort client_id       = current.Key;
                            IStreamConnect connect = state.Connect;

                            try
                            {
                                if (connect.IsDisconnected)
                                {
                                    DisconnectSession(client_id);
                                }
                                else
                                {
                                    if (state.WriterTask == null)
                                    {
                                        state.WriterTask = connect.WriteOnceAsync();
                                    }
                                    else
                                    {
                                        if (state.WriterTask.IsCompleted)
                                        {
                                            state.WriterTask = connect.WriteOnceAsync();
                                        }
                                        if (state.WriterTask.IsCanceled || state.WriterTask.IsFaulted)
                                        {
                                            this.DisconnectSession(current.Key);
                                            //throw state.WriterTask.Exception;
                                        }
                                        if (state.LastPing == null || DateTime.UtcNow - state.LastPing >= new TimeSpan(0, 0, _pingPeriod))
                                        {
                                            connect.PingAsync(_pingTimeout);
                                            state.LastPing = DateTime.UtcNow;
                                        }

                                        if (state.ReaderTask == null || state.ReaderTask.IsCompleted)
                                        {
                                            state.ReaderTask = connect.ReadOnceAsync();
                                        }

                                        if (state.ReaderTask.IsCanceled || state.ReaderTask.IsFaulted)
                                        {
                                            this.DisconnectSession(current.Key);
                                            //throw state.ReaderTask.Exception;
                                        }
                                    }
                                }
                            }
                            catch
                            {
                                DisconnectSession(client_id);
                            }
                        });
                    }
                    catch (Exception ex)
                    {
                        FleckLog.Error("ConnectStateCheckUp.Thread.Error", ex);
                    }
                }
            })
            {
                IsBackground = true
            };
            _clientWorkThread.Start();
        }
示例#11
0
        /// <summary>
        /// 将发布者的媒体的meta发给播放者
        /// </summary>
        /// <param name="liveChannel"></param>
        /// <param name="path"></param>
        /// <param name="self"></param>
        /// <param name="flvHeader"></param>
        internal void SendMetadataToPlayer(string liveChannel, string path, IStreamConnect self, bool flvHeader = false)
        {
            ushort publisherID;

            IStreamConnect publisher;

            ClientSession publisherState;

            var uri = new Uri("http://127.0.0.1/" + path);
            var key = new Tuple <string, string>(liveChannel, uri.AbsolutePath);

            if (!_clientRouteTable.TryGetValue(key, out publisherID))
            {
                throw new KeyNotFoundException("请求地址不存在~");
            }
            if (!ClientSessions.TryGetValue(publisherID, out publisherState))
            {
                _clientRouteTable.Remove(key);
                throw new KeyNotFoundException("请求客户端不存在~");
            }
            publisher = publisherState.Connect;
            if (publisher.IsPublishing)
            {
                var flv_metadata = (Dictionary <string, object>)publisher.FlvMetaData.MethodCall.Parameters[0];
                var has_audio    = flv_metadata.ContainsKey("audiocodecid");
                var has_video    = flv_metadata.ContainsKey("videocodecid");
                if (flvHeader)
                {
                    var header_buffer = Enumerable.Repeat <byte>(0x00, 13).ToArray <byte>();
                    header_buffer[0] = 0x46;
                    header_buffer[1] = 0x4C;
                    header_buffer[2] = 0x56;
                    header_buffer[3] = 0x01;
                    byte has_audio_flag = 0x01 << 2;
                    byte has_video_flag = 0x01;
                    byte type_flag      = 0x00;
                    if (has_audio)
                    {
                        type_flag |= has_audio_flag;
                    }
                    if (has_video)
                    {
                        type_flag |= has_video_flag;
                    }
                    header_buffer[4] = type_flag;
                    var data_offset = BitConverter.GetBytes((uint)9);
                    header_buffer[5] = data_offset[3];
                    header_buffer[6] = data_offset[2];
                    header_buffer[7] = data_offset[1];
                    header_buffer[8] = data_offset[0];
                    self.SendRawData(header_buffer);
                }
                self.SendAmf0Data(publisher.FlvMetaData);
                if (has_audio)
                {
                    self.SendAmf0Data(publisher.AACConfigureRecord);
                }
                if (has_video)
                {
                    self.SendAmf0Data(publisher.AvCConfigureRecord);
                }
            }
        }