public void Send(OSCARUdp self, ref FLAPHeader f) { var tlvs = new TLVChain(2) { new TLV { TypeID = SvcLayer.TLV_TYPE, Value = new byte[1] { SvcLayer.TYPE_CONNECT_REQST }}, new TLV{TypeID = SvcLayer.TLV_CONNECT_HASH, Value = Hash } }; self.queuePacket(ref self.m_svcFlap, (byte[])tlvs, Host); AttemptsTaken++; LastSent = Environment.TickCount; }
private void HandlePacket(ref FLAPHeader flap, byte[] data, IPEndPoint from) { var tlvs = (TLVChain)data; var type = tlvs[SvcLayer.TLV_TYPE].Value[0]; switch(type) { case SvcLayer.TYPE_USER_DATA: if (Connections.Contains(from)) m_events.TriggerPacketReceived(this, new PacketEventArgs(from, ref flap, tlvs[SvcLayer.TLV_USER_DATA].Value)); break; case SvcLayer.TYPE_CONNECT_ACCEPT: if (IsConnecting && m_connReq.Host.Equals(from) && Misc.CompareByteArrays(m_connReq.Hash, tlvs[SvcLayer.TLV_CONNECT_HASH].Value)) { m_connReq = null; Connections.Add(from); m_events.Connected(this, new HostConnectEventArgs(from, true)); } break; case SvcLayer.TYPE_CONNECT_REQST: if (m_acceptsIncomingConnections && (!this.IsConnecting || m_connReq.Host != from) && m_events.AuthorizeIncomingConnection(this, new HostEventArgs(from)) && !this.Connections.Contains(from)) { var tosend = new TLVChain(2) { new TLV { TypeID = SvcLayer.TLV_TYPE, Value = new byte[1] { SvcLayer.TYPE_CONNECT_ACCEPT } }, new TLV { TypeID = SvcLayer.TLV_CONNECT_HASH, Value = tlvs[SvcLayer.TLV_CONNECT_HASH].Value } }; sendPacket(from, ref flap, (byte[])tosend); Connections.Add(from); m_events.Connected(this, new HostConnectEventArgs(from, false)); } break; } }
/// <summary> /// Выполняет попытку входа в сеть ICQ. /// </summary> public void SignIn() { if (m_signInAsync != null) throw new InvalidAsynchronousStateException("SignIn/BeginSignIn/SignInAsync was already called and is not finished."); else if (string.IsNullOrWhiteSpace(m_icqConfig.UserLogin)) throw new ArgumentNullException("ICQClientConfiguration.UserLogin", "Value is null, empty, or consisting only from white-space characters."); else if (string.IsNullOrWhiteSpace(m_icqConfig.UserPassword)) throw new ArgumentNullException("ICQClientConfiguration.UserPassword", "Value is null, empty, or consisting only from white-space characters."); else if (!m_icqConfig.LoginServer.IsValid) throw new ArgumentException("Invalid ICQClientConfiguration.LoginServer value specified."); try { // Set state to Connecting this.changeState(ICQClientState.Connecting); LogWrite("SignIn starting for Host({0}), UserLogin({1}), UserPassword.Length({2})", m_icqConfig.LoginServer, m_icqConfig.UserLogin, m_icqConfig.UserPassword.Length); // Connect to login server this.Connection.Connect(m_icqConfig.LoginServer.EndPoint, false); LogWrite("OSCAR is connected to host({0})", m_icqConfig.LoginServer.Address); // Define our packet read timeout const int readTimeout = (int) TimeSpan.TicksPerSecond * 10; // Expect: SRV_HELLO var flap = FLAPHeader.Empty; byte[] packet = null; if (!this.Connection.Receive(ref flap, out packet, true, readTimeout)) throw new TimeoutException("Server did not reply in proper time, expected: SRV_HELLO"); ICQ.Packets.SRV_HELLO_VALIDATE(this, ref flap, packet); // Reply with: CLI_HELLO ICQ.Packets.CLI_HELLO(ref flap, ref packet); this.Connection.Send(ref flap, packet); // Send: CLI_CHALLENGE_REQUEST byte[] userLoginBytes = Encoding.UTF8.GetBytes(m_icqConfig.UserLogin); var tlvs = new TLVChain(3) { new TLV { TypeID = 0x01, Value = userLoginBytes }, new TLV { TypeID = 0x4B, Value = OSCAR.EmptyData }, new TLV { TypeID = 0x5A, Value = OSCAR.EmptyData }, }; ICQ.Packets.Make(ref flap, ref packet, ICQ.Packets.CLI_CHALLENGE_REQUEST, tlvs); this.Connection.Send(ref flap, packet); // Set state to Authorizing this.changeState(ICQClientState.Authorizing); byte[] auth_challenge = null; // Expect: SRV_CHALLENGE_REPLY or SRV_AUTH_RESPONSE if (!this.Connection.Receive(ref flap, out packet, true, readTimeout)) throw new TimeoutException("Server did not reply in proper time, expected: SRV_CHALLENGE_REPLY or SRV_AUTH_RESPONSE"); else if (!flap.IsSNAC) throw new ProtocolViolationException("Expected SNAC, got packet: " + flap); var snac = (SNAC)packet; if (snac.Type == ICQ.Packets.SRV_CHALLENGE_RESPONSE) { // We have challenge now, read it (TLV without TypeID) var challengeLength = XBitConvert.ToUInt16(snac.Data, 0); auth_challenge = new byte[challengeLength]; Array.Copy(snac.Data, 2, auth_challenge, 0, challengeLength); } else if (snac.Type == ICQ.Packets.SRV_AUTH_RESPONSE) { // Most likely login rejected goto handleAuthResponse; } else throw new ProtocolViolationException("Expected SNAC: SRV_AUTH_RESPONSE or SRV_CHALLENGE_RESPONSE, got: " + snac); // Send: CLI_AUTH_REQUEST byte[] protectedAuthRequest = ICQ.AimPasswordHashFunction(auth_challenge, m_icqConfig.UserPassword, "AOL Instant Messenger (SM)"); tlvs = new TLVChain(3) { new TLV { TypeID = 0x01, Value = userLoginBytes }, new TLV { TypeID = 0x25, Value = protectedAuthRequest }, new TLV { TypeID = 0x4C, Value = OSCAR.EmptyData }, }; ICQ.Packets.Make(ref flap, ref packet, ICQ.Packets.CLI_AUTH_REQUEST, tlvs); this.Connection.Send(ref flap, packet); #if IMadering Следующие данные идентификации клиента уже не обязательны (изменение 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) Дополнения пакета: 0014 // Метка блока данных с "Client distribution number" 0004 // Длина данных в блоке 00000150 // Client distribution number (значение: 336) 004a // Метка блока поддержки мультиподключений к серверу с одним UIN 0001 // Длина данных 01 // Флаг поддержки мультиподключений #endif // Expect: SRV_AUTH_RESPONSE if (!this.Connection.Receive(ref flap, out packet, true, readTimeout)) throw new TimeoutException("Server did not reply in proper time, expected: SRV_AUTH_RESPONSE"); else if (!flap.IsSNAC) throw new ProtocolViolationException("Expected SNAC, got packet: " + flap); snac = (SNAC)packet; if (snac.Type != ICQ.Packets.SRV_AUTH_RESPONSE) throw new ProtocolViolationException("Expected SNAC: SRV_AUTH_RESPONSE, got: " + snac); handleAuthResponse: // Construct TLVChain from SNAC packet data tlvs = (TLVChain)snac.Data; // Connection is not needed anymore this.Connection.Disconnect(0); // Did authorization fail? if ( tlvs.Contains(0x08) ) { // Do we have reason/error code TLV? ushort errorCode = 0; if (tlvs.Contains(0x0008)) { // Get reason/error code errorCode = XBitConvert.ToUInt16(tlvs[0x0008].Value, 0); } else this.LogWrite("[WARNING] (SRV_AUTH_RESPONSE:AUTH_FAIL) does not contain error code (tlv:0x0008)!"); // Is there any string helpUrl = null; if (tlvs.Contains(0x04)) helpUrl = Encoding.ASCII.GetString(tlvs[0x04].Value); else this.LogWrite("[WARNING] (SRV_AUTH_RESPONSE:AUTH_FAIL) does not contain Help Url (tlv:0x04)."); // Event: throw new ICQException(this, "Authorization failed.", helpUrl, errorCode); } else { // Anything is fine! if (!tlvs.Contains(0x05) || !tlvs.Contains(0x06)) throw new ProtocolViolationException("Received invalid/unsupported SRV_AUTH_RESPONSE packet (no required info...)."); // Get BOSS info byte[] bossCookie = tlvs[0x06].Value; string bossHost = Encoding.UTF8.GetString(tlvs[0x05].Value); // Continue SignIn this.LogWrite("Authorization complete, received bossCookie(length: {0}) and bossHost({1})", bossCookie.Length, bossHost); this.changeState(ICQClientState.Authorized); this.ConnectInitSession(new NetworkHost(bossHost, 5190), bossCookie); } throw new NotImplementedException(); } catch (Exception ex) { LogWrite("SignIn exception: {0}", ex); this.changeState(ICQClientState.Idle, ex); } }
/// <summary> /// Отправляет данные на подключенный хост. Он должен быть подключен к текущему пиру. /// </summary> /// <param name="to">Адресат доставки</param> /// <param name="data">Данные для отправки</param> public void Send(EndPoint to, byte[] data) { #if DEBUG if (!Connections.Contains(to)) throw new ArgumentException('\"' + to.ToString() + "' is not connected peer."); #endif var tlvs = new TLVChain(2) { new TLV { TypeID = SvcLayer.TLV_TYPE, Value = new byte[1] { SvcLayer.TYPE_USER_DATA } }, new TLV { TypeID = SvcLayer.TLV_USER_DATA, Value = data}, }; m_sendBuffer.Enqueue(new OSCARQueueEntity { Host = to, FLAP = m_svcFlap, Data = (byte[])tlvs }); }
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; }