/// <summary> /// Processes a notification of e-mail information change -- SNAC(18,07) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(18,07)</param> public static void ProcessEmailInformation(DataPacket dp) { // There are 24 bytes of cookies prior to the TLV list, an 8-byte cookie // and a 16-byte cookie. The 16 byte cookie is identifying information // that may be useful byte[] cookie = dp.Data.ReadByteArray(8); byte[] idcookie = dp.Data.ReadByteArray(16); TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()); string alertTitle = tlvs.ReadString(0x0005, Encoding.ASCII); string url = tlvs.ReadString(0x0007, Encoding.ASCII); string alertUrl = tlvs.ReadString(0x000D, Encoding.ASCII); ushort numMessages = tlvs.ReadUshort(0x0080); byte unread = tlvs.ReadByte(0x0081); if (unread == 0) { numMessages = 0; } string domain = tlvs.ReadString(0x0082, Encoding.ASCII); ushort flags = tlvs.ReadUshort(0x0084); if (numMessages == 0xFFFF) { // If this message was received, at least one email message is available // even if TLV 0x0080 wasn't in the message numMessages = 1; } }
/// <summary> /// Processes a popup message sent by the server -- SNAC(08,02) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(08,02)</param> public static void ProcessPopupMessage(DataPacket dp) { TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd()); string message = tlvs.ReadString(0x0001, Encoding.ASCII); string url = tlvs.ReadString(0x0002, Encoding.ASCII); ushort width = tlvs.ReadUshort(0x0003); ushort height = tlvs.ReadUshort(0x0004); ushort delay = tlvs.ReadUshort(0x0005); dp.ParentSession.OnPopupMessage(width, height, delay, url, message); }
/// <summary> /// Processes the server response to a new family request -- SNAC(01,05) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(01,05)</param> public static void ProcessNewServiceResponse(DataPacket dp) { int startIndex = 0; byte[] SNACData = dp.Data.ReadByteArrayToEnd(); if (SNACData[0] == 0x00 && SNACData[1] == 0x06) { startIndex += 2; // What the heck is this...0x0006, some families, some of the time? } using (TlvBlock tlvs = new TlvBlock(SNACData, startIndex)) { ushort family = tlvs.ReadUshort(SERVICE_RESPONSE_FAMILY); string BOSaddress = tlvs.ReadString(SERVICE_RESPONSE_ADDRESS, Encoding.ASCII); byte[] cookie = tlvs.ReadByteArray(SERVICE_RESPONSE_COOKIE); Connection newconn = null; object store = dp.ParentSession.RetrieveRequestID(dp.SNAC.RequestID); if (family != 0x000E) { newconn = dp.ParentSession.Connections.CreateNewConnection(family); } else { ChatRoom roominfo = (ChatRoom)store; dp.ParentSession.Connections.CreateNewChatConnection(roominfo); newconn = roominfo.Connection; } string[] bosinfo = BOSaddress.Split(':'); int port = 0; if (bosinfo.Length == 2) { port = Int32.Parse(bosinfo[1]); } else { port = dp.ParentSession.LoginPort; } newconn.ServerConnectionCompleted += new ServerConnectionCompletedHandler(newconn_ServerConnnectionCompleted); newconn.Server = bosinfo[0]; newconn.Port = port; newconn.Cookie = new Cookie(cookie); newconn.ConnectToServer(); } // The connection process continues when the server sends SNAC(01,03) }
/// <summary> /// Reads the error code and subcode from a SNAC(XX,01) packet /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(XX,01)</param> /// <param name="errorCode">The main error code contained in the SNAC</param> /// <param name="subCode">The subcode contained in the SNAC, or 0 if there is no subcode present</param> public static void GetSNACErrorCodes(DataPacket dp, out ushort errorCode, out ushort subCode) { errorCode = dp.Data.ReadUshort(); subCode = 0; if (dp.Data.HasMoreData) { using (TlvBlock tlvs = dp.Data.ReadTlvBlockByLength(dp.Data.GetRemainingByteCount())) { if (tlvs.HasTlv(0x0008)) { subCode = tlvs.ReadUshort(0x0008); } } } }
/// <summary> /// Reads a <see cref="UserInfo"/> from the stream /// </summary> public UserInfo ReadUserInfo() { UserInfo retval = new UserInfo(); byte screenNameLength = ReadByte(); if (screenNameLength == 0) { return(null); } retval.ScreenName = ReadString(screenNameLength, Encoding.ASCII); retval.WarningLevel = ReadUshort(); using (TlvBlock tlvBlock = ReadTlvBlock(ReadUshort())) { retval.Class = (UserClass)tlvBlock.ReadUshort(0x0001); retval.CreateTime = tlvBlock.ReadDateTime(0x0002); retval.SignonTime = tlvBlock.ReadDateTime(0x0003); retval.IdleTime = tlvBlock.ReadUshort(0x0004); if (retval.IdleTime == 0xFFFF) { retval.IdleTime = 0; } retval.RegisterTime = tlvBlock.ReadDateTime(0x0005); retval.ICQUserStatus = tlvBlock.ReadUint(0x0006); retval.ExternalIPAddress = tlvBlock.ReadUint(0x000A); // Read the DC info from 0x000C retval.ClientCapabilities = CapabilityProcessor.ProcessCLSIDList(tlvBlock.ReadByteArray(0x000D)); retval.OnlineTime = tlvBlock.ReadUint(0x000F); if (tlvBlock.HasTlv(0x001D)) { ReadIconInfo(tlvBlock.ReadByteArray(0x001D), retval); } } return(retval); }
/// <summary> /// Processes a login response -- SNAC(17,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,03)</param> public static void ProcessLoginResponse(DataPacket dp) { // Pull apart SNAC(17,03) Cookie cookie; string BOSaddress; using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { if (tlvs.HasTlv(0x0008)) { ushort errorcode = tlvs.ReadUshort(0x0008); dp.ParentSession.OnLoginFailed((LoginErrorCode)errorcode); return; } BOSaddress = tlvs.ReadString(0x0005, Encoding.ASCII); cookie = Cookie.GetReceivedCookie(tlvs.ReadByteArray(0x0006)); } // Shut down the authorization connection // Socket shutdown is initiated by the server dp.ParentSession.OnLoginStatusUpdate("Authorized", 0.33); dp.ParentConnection.DisconnectFromServer(false); // Create a new connection to the BOS server Connection newconn = dp.ParentSession.Connections.CreateNewConnection(0x0001); string[] bosinfo = BOSaddress.Split(':'); newconn.ServerConnectionCompleted += new ServerConnectionCompletedHandler(newconn_ServerConnnectionCompleted); newconn.Server = bosinfo[0]; newconn.Port = Int32.Parse(bosinfo[1]); newconn.Cookie = cookie; newconn.ConnectToServer(); // The connection process continues when the server sends SNAC(01,03) }
/// <summary> /// Processes a login response -- SNAC(17,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(17,03)</param> internal void ProcessLoginResponse(DataPacket dp) { // Pull apart SNAC(17,03) Cookie cookie; string BOSaddress; using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { if (tlvs.HasTlv(0x0008)) { ushort errorcode = tlvs.ReadUshort(0x0008); parent.OnLoginFailed((LoginErrorCode)errorcode); return; } BOSaddress = tlvs.ReadString(0x0005, Encoding.ASCII); cookie = Cookie.GetReceivedCookie(tlvs.ReadByteArray(0x0006)); } // Shut down the authorization connection // Socket shutdown is initiated by the server parent.OnLoginStatusUpdate("Authorized", 0.33); dp.ParentConnection.DisconnectFromServer(false); // Create a new connection to the BOS server Connection newconn = parent.Connections.CreateNewConnection(0x0001); string[] bosinfo = BOSaddress.Split(':'); newconn.ServerConnectionCompleted += delegate(Connection conn) { conn.ReadyForData = true; conn.ReadHeader(); }; newconn.Server = bosinfo[0]; if (bosinfo.Length == 2) newconn.Port = Int32.Parse(bosinfo[1]); else newconn.Port = dp.ParentConnection.Port; Logging.WriteString("Connect to Server after auth. Address from dp: {0} - Address to connect: {1}:{2}", BOSaddress, newconn.Server, newconn.Port); newconn.Cookie = cookie; newconn.ConnectToServer(); // The login process continues when the server sends SNAC(01,03) on the new connection }
/// <summary> /// Processes the server response to a new family request -- SNAC(01,05) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object containing SNAC(01,05)</param> private void ProcessNewServiceResponse(DataPacket dp) { int startIndex = 0; byte[] SNACData = dp.Data.ReadByteArrayToEnd(); if (SNACData[0] == 0x00 && SNACData[1] == 0x06) { startIndex += 2; // What the heck is this...0x0006, some families, some of the time? } using (TlvBlock tlvs = new TlvBlock(SNACData, startIndex)) { ushort family = tlvs.ReadUshort(NEW_SERVICE_FAMILY); string BOSaddress = tlvs.ReadString(NEW_SERVICE_ADDRESS, Encoding.ASCII); byte[] cookie = tlvs.ReadByteArray(NEW_SERVICE_COOKIE); Connection newconn = null; object store = dp.ParentSession.RetrieveRequestID(dp.SNAC.RequestID); if (family != 0x000E) { newconn = dp.ParentSession.Connections.CreateNewConnection(family); } else { ChatRoom roominfo = (ChatRoom)store; newconn = dp.ParentSession.Connections.CreateNewChatConnection(roominfo); } string[] bosinfo = BOSaddress.Split(':'); int port = 0; if (bosinfo.Length == 2) { port = Int32.Parse(bosinfo[1]); } else { port = dp.ParentSession.ServerSettings.LoginPort; } newconn.ServerConnectionCompleted += delegate { newconn.ReadHeader(); }; newconn.Server = bosinfo[0]; newconn.Port = port; newconn.Cookie = new Cookie(cookie); newconn.ConnectToServer(); } // The connection process continues when the server sends SNAC(01,03) }
/// <summary> /// Processes the parameter information sent by the server -- SNAC(02,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(02,03)</param> private void ProcessLocationParameterList(DataPacket dp) { using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { maxCapabilities = tlvs.ReadUshort(PARAMETER_MAXCAPABILITIES); maxProfileLength = tlvs.ReadUshort(PARAMETER_PROFILELENGTH); } ReportClientCapabilities(); parent.ParameterSetArrived(); }
/// <summary> /// Processes the parameter information sent by the server -- SNAC(03,03) /// </summary> /// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,03)</param> private void ProcessBuddyParameterList(DataPacket dp) { using (TlvBlock tlvs = new TlvBlock(dp.Data.ReadByteArrayToEnd())) { maxBuddyListEntries = tlvs.ReadUshort(PARAMETER_MAXBUDDIES); maxWatcherListEntries = tlvs.ReadUshort(PARAMETER_MAXWATCHERS); maxNotifications = tlvs.ReadUshort(PARAMETER_MAXNOTIFICATIONS); } parent.ParameterSetArrived(); }
/// <summary> /// Processes the inner TLV list in TLV 0x0005 and returns a new DirectConnection /// </summary> private DirectConnection ProcessChannel2Tlv05(ByteStream stream, UserInfo ui, DataPacket dp) { byte[] invitemessage; Encoding encoding = Encoding.ASCII; string language = "en"; DirectConnection directconn = null; // Pull the type, cookie, and capability array RendezvousType rtype = RendezvousData.TypeFromUshort(stream.ReadUshort()); Cookie cookie = Cookie.GetReceivedCookie(stream.ReadByteArray(8)); byte[] capabilitiesArray = stream.ReadByteArray(16); Capabilities capabilities = CapabilityProcessor.ProcessCLSIDList(capabilitiesArray); // Create the correct type of connection based on the capability if (capabilities == Capabilities.SendFiles) { if ((directconn = parent.Connections.GetDirectConnectionByCookie(cookie)) == null) { directconn = parent.Connections.CreateNewFileTransferConnection( DirectConnectionMethod.Direct, DirectConnectRole.Receiver); } } else if (capabilities == Capabilities.DirectIM) { if ((directconn = parent.Connections.GetDirectConnectionByCookie(cookie)) == null) { directconn = parent.Connections.CreateNewDirectIMConnection( DirectConnectionMethod.Direct, DirectConnectRole.Receiver); } } else if (capabilities == Capabilities.Chat) { directconn = parent.Connections.CreateNewChatInvitationConnection(DirectConnectRole.Receiver); } else { // Currently unsupported parent.OnWarning(ServerErrorCode.UnknownRendezvousChannel, dp); return null; } directconn.Other = ui; directconn.Cookie = cookie; directconn.Type = rtype; ByteStream serviceData = null; Encoding serviceDataEncoding = Encoding.ASCII; // Process the inner TLV list using (TlvBlock tlvs = new TlvBlock(stream.ReadByteArrayToEnd())) { directconn.AOLProxyIP = tlvs.ReadIPAddress(DC_PROXY_IP_ADDRESS); // proxy ip directconn.ClientIP = tlvs.ReadIPAddress(DC_CLIENT_IP_ADDRESS); // internal ip directconn.VerifiedIP = tlvs.ReadIPAddress(0x0004); // external ip directconn.Port = tlvs.ReadUshort(DC_PORT); directconn.Sequence = RendezvousData.SequenceFromUshort(tlvs.ReadUshort(DC_SEQUENCE_NUMBER)); invitemessage = tlvs.ReadByteArray(DC_MESSAGE); if (tlvs.HasTlv(0x000D)) { encoding = Encoding.GetEncoding(tlvs.ReadString(0x000D, Encoding.ASCII)); } language = tlvs.ReadString(0x000E, Encoding.ASCII); directconn.Method = (tlvs.HasTlv(DC_USE_PROXY_FLAG)) ? DirectConnectionMethod.Proxied : DirectConnectionMethod.Direct; serviceData = new ByteStream(tlvs.ReadByteArray(0x2711)); if (tlvs.HasTlv(0x2712)) { serviceDataEncoding = Encoding.GetEncoding(tlvs.ReadString(0x2712, Encoding.ASCII)); } } if (invitemessage != null) { directconn.Message = encoding.GetString(invitemessage, 0, invitemessage.Length); } // Process the extra data, if necessary if (directconn is FileTransferConnection || directconn is DirectIMConnection) { ProcessDirectConnectionRequest(directconn, serviceData); } else if (directconn is ChatInvitationConnection) { ChatInvitationConnection cic = directconn as ChatInvitationConnection; cic.ChatInvite = new ChatInvitation(); cic.ChatInvite.Message = directconn.Message; cic.ChatInvite.Encoding = encoding; cic.ChatInvite.Language = language; ProcessChatInvitationRequest(cic, serviceData); } return directconn; }