/// <summary> /// Notifies the OSCAR server that the new connection is ready to receive service-specific data /// </summary> /// <remarks> /// This SNAC must be sent within 30ish seconds of connection, or the connection will drop. /// This should not ever be a problem, barring a lost connection well below the level of this library. /// </remarks> public void SendReadyNotification(Connection conn) { // Build SNAC(01,02) SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_BOS_FAMILY; sh.FamilySubtypeID = BOS_CONNECTION_READY; ushort[] families = parent.Connections.GetFamilies(conn); FamilyManager fm = parent.Families; Array.Sort(families); Array.Reverse(families); bool isChatRoomConnection = false; bool isChatNavService = false; ByteStream stream = new ByteStream(); DataPacket[][] delayedframes = new DataPacket[families.Length][]; for (int i = 0; i < families.Length; i++) { ushort family = families[i]; delayedframes[i] = parent.Connections.GetDelayedPackets(family); stream.WriteUshort(family); stream.WriteUshort(fm.GetFamilyVersion(family)); stream.WriteUshort(fm.GetFamilyToolID(family)); stream.WriteUshort(fm.GetFamilyToolVersion(family)); if (family == 0x000D) { isChatNavService = true; } else if (family == 0x000E) { isChatRoomConnection = true; } } /* * The initial service connection has to send SNAC(01,1E) before it actually * sends SNAC(01,02), thus the check for the initial connection here * and after it gets sent. */ if (!parent.LoggedIn) { SetAvailableMessage(parent.Statuses.AvailableMessage); SetDCInfo(); SetExtendedICQStatus(parent.Statuses.ICQFlags, parent.Statuses.ICQStatus); } // The connection is done, so start sending keepalives conn.Connecting = false; conn.ReadyForData = true; DataPacket dp = Marshal.BuildDataPacket(parent, sh, stream); dp.ParentConnection = conn; SNACFunctions.BuildFLAP(dp); /* * If this is a new service connection, there is probably at least one * delayed packet. Process those packets. Additionally, if the new connection is * a chatroom connection, query the Rendezvous manager to see if it is the result * of an explict room creation (or implict, as in accepting a chat invitation). * If it was explict, notify the user that it's done */ if (parent.LoggedIn) { foreach (DataPacket[] list in delayedframes) { if (list == null) { continue; } foreach (DataPacket dp_delay in list) { dp_delay.ParentConnection = conn; SNACFunctions.DispatchToRateClass(dp_delay); } } if (isChatNavService) { parent.ChatRooms.OnChatNavServiceAvailable(); } else if (isChatRoomConnection) { ChatRoom chatRoom = parent.Connections.GetChatByConnection((ChatConnection)conn); parent.ChatRooms.OnChatRoomConnectionAvailable(chatRoom); } } }