public bool Connect()
        {
            PingReply pingReply = null;

            try
            {
                pingReply = new Ping().Send("live.bilibili.com");
            }
            catch (Exception)
            {
            }
            if (pingReply == null || pingReply.Status != IPStatus.Success)
            {
                ConnectionFailed?.Invoke("网络连接失败");
                return(false);
            }

            DanmakuServer danmakuServer = GetDanmakuServer(RoomId);

            if (danmakuServer == null)
            {
                return(false);
            }

            switch (Protocol)
            {
            case Protocols.Tcp:
                DanmakuTcpClient = GetTcpConnection(danmakuServer);
                Stream stream = DanmakuTcpClient.GetStream();

                stream.ReadTimeout  = 30 * 1000 + 1000;
                stream.WriteTimeout = 30 * 1000 + 1000;

                PackReader = new BiliPackReader(stream);
                PackWriter = new BiliPackWriter(stream);
                break;

            case Protocols.Ws:
                DanmakuWebSocket = GetWsConnection(danmakuServer);
                PackReader       = new BiliPackReader(DanmakuWebSocket);
                PackWriter       = new BiliPackWriter(DanmakuWebSocket);
                break;

            case Protocols.Wss:
                DanmakuWebSocket = GetWssConnection(danmakuServer);
                PackReader       = new BiliPackReader(DanmakuWebSocket);
                PackWriter       = new BiliPackWriter(DanmakuWebSocket);
                break;
            }

            if (!InitConnection(danmakuServer))
            {
                Disconnect();
                return(false);
            }

            StartEventListener();
            StartHeartbeatSender();

            Connected?.Invoke();
            return(true);
        }
Example #2
0
        public IPack[] ReadPacksAsync()
        {
            if (BaseWebSocket != null)
            {
                ArraySegment <byte>    buffer = new ArraySegment <byte>(new byte[4096]);
                WebSocketReceiveResult webSocketReceiveResult = BaseWebSocket.ReceiveAsync(buffer, CancellationToken.None).GetAwaiter().GetResult();
                BaseStream.Position = 0;
                BaseStream.Write(buffer.Array, 0, webSocketReceiveResult.Count);
                BaseStream.Position = 0;
            }

            // Pack length (4)
            byte[] packLengthBuffer = ReadTcpStream(BaseStream, 4);
            int    packLength       = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(packLengthBuffer, 0));

            if (packLength < 16)
            {
                BaseStream.Flush();
                // TODO : 包长度过短
                throw new Exception();
            }

            // Header length (2)
            byte[] headerLengthBuffer = ReadTcpStream(BaseStream, 2);
            int    headerLength       = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(headerLengthBuffer, 0));

            if (headerLength != 16)
            {
                BaseStream.Flush();
                // TODO : 头部长度异常
                throw new Exception();
            }

            // Data type (2)
            byte[]    dataTypeBuffer = ReadTcpStream(BaseStream, 2);
            int       dataTypeCode   = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(dataTypeBuffer, 0));
            DataTypes dataType;

            if (Enum.IsDefined(typeof(DataTypes), dataTypeCode))
            {
                dataType = (DataTypes)Enum.ToObject(typeof(DataTypes), dataTypeCode);
            }
            else
            {
                dataType = DataTypes.Unknow;
            }


            // Read pack type (4)
            byte[]    packTypeBuffer = ReadTcpStream(BaseStream, 4);
            int       packTypeCode   = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(packTypeBuffer, 0));
            PackTypes packType;

            if (Enum.IsDefined(typeof(PackTypes), packTypeCode))
            {
                packType = (PackTypes)Enum.ToObject(typeof(PackTypes), packTypeCode);
            }
            else
            {
                packType = PackTypes.Unknow;
            }

            // Read split (4)
            byte[] splitBuffer = ReadTcpStream(BaseStream, 4);

            // Read payload
            int payloadLength = packLength - headerLength;

            byte[] payloadBuffer = ReadTcpStream(BaseStream, payloadLength);

            // Return
            switch (dataType)
            {
            case DataTypes.Plain:
                switch (packType)
                {
                case PackTypes.Command:
                    return(new CommandPack[] { new CommandPack(payloadBuffer) });

                default:
                    // TODO : 未知包类型
                    throw new Exception();
                }

            case DataTypes.Bin:
                switch (packType)
                {
                case PackTypes.Popularity:
                    return(new PopularityPack[] { new PopularityPack(payloadBuffer) });

                case PackTypes.Heartbeat:
                    return(new HeartbeatPack[] { new HeartbeatPack(payloadBuffer) });

                default:
                    // TODO : 未知包类型
                    throw new Exception();
                }

            case DataTypes.Gz:
                List <IPack> packs = new List <IPack>();
                using (MemoryStream compressedStream = new MemoryStream(payloadBuffer))
                {
                    using (GZipStream gZipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
                    {
                        using (MemoryStream decompressedStream = new MemoryStream())
                        {
                            gZipStream.CopyTo(decompressedStream);
                            decompressedStream.Position = 0;

                            while (decompressedStream.Position != decompressedStream.Length)
                            {
                                IPack[] innerPackes = new BiliPackReader(decompressedStream).ReadPacksAsync();
                                packs.AddRange(innerPackes);
                            }
                        }
                    }
                }
                return(packs.ToArray());

            default:
                // TODO : 未知数据类型
                throw new Exception();
            }
        }