Пример #1
0
        /// <summary>
        /// Воссоздает объект FLAPHeader из массива байтов с заголовком в начале.
        /// </summary>
        /// <param name="buffer">Массив для обработки</param>
        /// <param name="flapDataLength">Сообщает размер тела FLAP, следующих за заголовком.</param>
        /// <param name="checkIDByte">
        /// Ожидаемое значение FLAPHeader.ID для этого приложения; при нарушении создается исключение.
        /// </param>
        public static FLAPHeader FromBytes(byte[] buffer, out ushort flapDataLength, byte checkIDByte)
        {
            var flapHeader = new FLAPHeader
            {
                ID = buffer[0],
                Channel = buffer[1],
                SequenceNumber = XBitConvert.ToUInt16(buffer, 2)
            };
            flapDataLength = XBitConvert.ToUInt16(buffer, 4);

            if (flapHeader.ID != checkIDByte)
            {
                if (Misc.CompareByteArrays(buffer, InvalidHeaderBytes))
                    throw new System.IO.IOException("Received invalid/empty FLAP header; or Receive data failed.");
                else
                    throw new System.Net.ProtocolViolationException("Unexpected FLAPHeader.ID value: " + flapHeader +
                        ". Expected: " + checkIDByte);
            }

            return flapHeader;
        }
Пример #2
0
 public static void Make(ref FLAPHeader flap, ref byte[] packet, sSNACType type, TLVChain tlvs, uint requestID = 0, eSNACFlags snacFlags = eSNACFlags.None)
 {
     flap.Channel = (byte)eFLAPChannel.SNACPacket;
     var snac = new SNAC(type, requestID, snacFlags);
     snac.Data = (byte[])tlvs;
     packet = (byte[])snac;
 }
Пример #3
0
 public static void SRV_HELLO_VALIDATE(ICQClient client, ref FLAPHeader flap, byte[] packet)
 {
     if ((eFLAPChannel)flap.Channel != eFLAPChannel.NewConnection)
         throw new ProtocolViolationException("Unexpected server welcoming packet received; expected: SRV_HELLO");
     else if (packet.Length != 4 || XBitConvert.ToUInt32(packet, 0) != 1)
         client.LogWrite("[WARNING] SRV_HELLO has unexpected body value or body length...");
 }
Пример #4
0
            public static void CLI_HELLO(ref FLAPHeader flap, ref byte[] packet)
            {
                if (packet == null || packet.Length != 12)
                    packet =  new byte[12];

                XBitConvert.ToBytes((uint)0x00000001,   packet, 0);
                XBitConvert.ToBytes((ushort)0x8003,     packet, 4);
                XBitConvert.ToBytes((ushort)0x0004,     packet, 6);
                XBitConvert.ToBytes((uint)0x00100000,   packet, 8);

                flap.Channel = (byte)eFLAPChannel.NewConnection;
            }
Пример #5
0
            public static void CLI_HELLO_BOSS(ref FLAPHeader flap, ref byte[] packet, byte[] bossCookie)
            {
                var tlvs = new TLVChain(4)
                {
                // BOSS cookie
                new TLV { TypeID = 0x0006, Value = bossCookie },
                #if false
                Следующие данные идентификации клиента уже не обязательны (изменение 2011 года).
                0003 // Метка блока данных со строкой идентификации клиента
                    0024 // Длина строки идентификации клиента
                        TestBuddy AOL Instant Messenger (SM)  // Строка идентификации клиента
                0017 // Метка блока данных с мажорной версией клиента
                    0002 // Длина данных о мажорной версии
                        0001 // Номер мажорной версии: 1
                0018 // Метка блока данных о минорной версии клиента
                    0002 // Длина данных о минорной версии
                        0000 // Номер минорной версии: 0
                0019 // Метка блока данных о меньшей версии клиента
                    0002 // Длина данных о меньшей версии
                        0000 // Номер меньшей версии: 0
                001a // Метка блока данных о номере сборки клиента
                    0002 // Длина данных номера сборки
                        0001 // Номер сборки клиента: 1
                0016 // Метка блока данных идентификатора клиента
                    0002 // Длина данных идентификатора
                        010e // Идентификатор клиента (значение: 270)
                000f // Метка блока данных о языке клиента
                    0002 // Длина данных о языке
                        656e // Язык клиента (значение: en)
                000e // Метка блока данных о стране клиента
                    0002 // Длина данных о стране
                        7573 // Страна клиента (значение: us)
                #endif
                // Unknown TLV, required,
                new TLV { TypeID = 0x8003, Value = XBitConvert.GetBytes((uint)0x00100000) },
                // BOSS reconnect support flag (false?)
                new TLV { TypeID = 0x0094, Value = new byte[1] { 0x00 } },
                // Multiconnections with same UIN support by this client flag (true?)
                new TLV { TypeID = 0x004a, Value = new byte[1] { 0x01 } },
                #if false
                Дополнения в клиенте ICQ 7
                ICQ Client Key=gu19PNBblQjCdbMU // Строка идентификации клиента
                00a2 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0005 // Неизвестные данные ^
                00a3 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0009 // Неизвестные данные ^
                00a4 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0002 // Неизвестные данные ^
                00a5 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        195c // Неизвестные данные ^
                008b // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0002 // Неизвестные данные ^
                008a // Метка неизвестного блока данных ^
                    0020 // Длина данных
                        7488383beec35874a13a74d64dad6b192fca547335976defd1da9fd985db5a32
                009e // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0002 // Неизвестные данные ^
                009f // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0001 // Неизвестные данные ^
                00a0 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        0000 // Неизвестные данные ^
                00a1 // Метка неизвестного блока данных ^
                    0002 // Длина данных
                        09a2 // Неизвестные данные ^
                00b0 // Метка неизвестного блока данных ^
                    0000 // Длина данных
                00ac // Метка неизвестного блока данных ^
                    0001 // Длина данных
                        00 // Неизвестные данные ^

                Дополнения в клиенте AIM:
                imApp key=ak1TRvqg3Srh_U_F // Строка идентификации клиента
                00b4 // Метка неизвестного блока данных ^
                    0012 // Длина данных 1
                        0010 // Длина данных 2
                            36594535383633354345332438343863 // Неизвестные данные ^
                #endif
                };

                using (var mem = new MemoryStream(100))
                {
                    // Flag we're connecting to ICQ network (dword, = 1)
                    mem.Write(XBitConvert.GetBytes((uint)1), 0, 4);

                    var tlvsBytes = (byte[])tlvs;
                    mem.Write(tlvsBytes, 0, tlvsBytes.Length);

                    packet = mem.ToArray();
                }
                flap.Channel = (byte)eFLAPChannel.NewConnection;
            }
Пример #6
0
 private void CheckIncomingPacketSequence(ref FLAPHeader flap)
 {
     // Check remote sequence
     if (m_remoteSequence != 0)
     {
         if (m_remoteSequence++ != flap.SequenceNumber)
             throw new ProtocolViolationException("Remote client violated its expected packet sequence number.");
     }
     else
         m_remoteSequence = (ushort)(flap.SequenceNumber + 1);
 }
Пример #7
0
 /// <summary>
 /// Send packet to Socket.
 /// </summary>
 /// <param name="to"></param>
 /// <param name="flap"></param>
 /// <param name="data"></param>
 protected void sendPacket(EndPoint to, ref FLAPHeader flap, byte[] data)
 {
     var header = new byte[FLAPHeader.FullLength];
     flap.ToBytes(header, data.Length);
     m_socket.SendTo(header, to);
     m_socket.SendTo(data, to);
 }
Пример #8
0
        /// <summary>
        /// Try read packet from Socket.
        /// </summary>
        /// <param name="flap"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        protected bool readPacket(ref FLAPHeader flap, out byte[] data)
        {
            if (m_socket.Available >= FLAPHeader.FullLength)
            {
                // Read header
                var header = new byte[FLAPHeader.FullLength];
                m_socket.Receive(header, FLAPHeader.FullLength, SocketFlags.None);
                ushort flapDataLength = 0;
                flap = FLAPHeader.FromBytes(header, out flapDataLength, AppIDByte);

                // Read data
                data = new byte[flapDataLength];
                if (flapDataLength > 0)
                {
                    int read = 0;
                    while (read < flapDataLength)
                        read += m_socket.Receive(data, read, flapDataLength - read, SocketFlags.None);
                }

                // Done
                return true;
            }

            // Nothing to read
            data = null;
            return false;
        }
Пример #9
0
        /// <summary>
        /// Добавляет пакет в очередь для отправки, если OSCAR в асинхронном режиме.
        /// В другом случае, немедленно отправляет пакет.
        /// </summary>
        /// <param name="flap">Заголовок FLAP</param>
        /// <param name="data">Тело пакета FLAP</param>
        public virtual void Send(ref FLAPHeader flap, byte[] data)
        {
            flap.ID = AppIDByte;
            flap.SequenceNumber = (m_localSequence++);

            if (m_customSocket || this.IsAsync)
            {
                // Buffer send
                m_sendBuffer.Enqueue(new OSCARQueueEntity
                {
                    FLAP = flap,
                    Data = data
                });
            }
            else
            {
                // Send right now
                sendPacket(m_remote, ref flap, data);
            }
        }
Пример #10
0
        /// <summary>
        /// Получает пакет из соединения.
        /// </summary>
        /// <param name="flap">Заголовок FLAP</param>
        /// <param name="data">Тело пакета FLAP</param>
        /// <param name="block">True, если нужно ждать пакет, даже если он еще недоступен.</param>
        /// <param name="blockTimeOut">При разрешении блокирования задает тайм-аут ожидания.</param>
        public virtual bool Receive(ref FLAPHeader flap, out byte[] data, bool block, int blockTimeOut = -1)
        {
            #if DEBUG
            if (this.IsAsync)
                throw new InvalidOperationException("This OSCAR instance is working in async mode. You cannot use Receive().");
            #endif
            var blockEnter = Environment.TickCount;

            // Receive
            recv:
            bool receiveOK = readPacket(ref flap, out data);

            // Block?
            if (!receiveOK)
            {
                if (block && this.IsConnected
                    && (blockTimeOut == Timeout.Infinite || (Environment.TickCount - blockEnter) <= blockTimeOut))
                {
                    Thread.Sleep(10);
                    goto recv;
                }
            }

            // Check if received
            if(receiveOK)
                CheckIncomingPacketSequence(ref flap);

            return receiveOK;
        }