public static void ProcessSNAC(DataPacket dp) { switch ((SNACFamily)dp.SNAC.FamilyServiceID) { case SNACFamily.DirectoryUserSearch: { DirectorySearch sub = (DirectorySearch)dp.SNAC.FamilySubtypeID; switch (sub) { case DirectorySearch.ClientServerError: // 0x0001 SNACFunctions.ProcessErrorNotification(dp); break; case DirectorySearch.SearchUserResponse: // 0x0003 SNAC0F.ProcessSearchResults(dp); break; case DirectorySearch.InterestsListResponse: // 0x0005 SNAC0F.ProcessInterestList(dp); break; } } break; case SNACFamily.LocationService: { LocationServices sub = (LocationServices)dp.SNAC.FamilySubtypeID; switch (sub) { case LocationServices.ClientServerError: // 0x0001 SNACFunctions.ProcessErrorNotification(dp); break; case LocationServices.UpdateDirectoryInfoResponse: // 0x000A SNAC02.ProcessUpdateResult(dp); break; case LocationServices.SNAC020BReply: SNAC02.ProcessSelfLocationReply(dp); // 0x000C break; case LocationServices.UpdateInterestsResponse: // 0x0010 SNAC02.ProcessUpdateResult(dp); break; default: break; } } break; case SNACFamily.PrivacyManagementService: { PrivacyManagementService sub = (PrivacyManagementService)dp.SNAC.FamilySubtypeID; switch (sub) { case PrivacyManagementService.ClientServerError: // 0x0001 SNACFunctions.ProcessErrorNotification(dp); break; case PrivacyManagementService.ServiceParametersRequest: // 0x0002 SNAC09.ProcessParametersListRequest(dp); break; case PrivacyManagementService.ServiceParametersResponse: // 0x0003 SNAC09.ProcessParametersList(dp); break; case PrivacyManagementService.ServiceError: break; default: break; } } break; case SNACFamily.SSIService: { SSIService sub = (SSIService)dp.SNAC.FamilySubtypeID; switch (sub) { case SSIService.ClientServerError: // 0x0001 SNACFunctions.ProcessErrorNotification(dp); break; case SSIService.ServiceParametersResponse: // 0x0003 SNAC13.ProcessParametersList(dp); break; case SSIService.ContactListResponse: // 0x0006 SNAC13.ProcessBuddyList(dp); break; case SSIService.SSIEditAddItems: // 0x0008 SNAC13.ProcessItemsAdded(dp); break; case SSIService.SSIEditUpdateGroupHeader: // 0x0009 SNAC13.ProcessItemsModified(dp); break; case SSIService.SSIEditRemoveItem: // 0x000A SNAC13.ProcessItemsRemoved(dp); break; case SSIService.SSIEditAcknowledge: // 0x000E SNAC13.ProcessSSIUpdateResponse(dp); break; case SSIService.LocalSSIUpToDate: // 0x000F SNAC13.ProcessSSIUpToDate(dp); break; case SSIService.YouWereAddedMessage: // 0x001C SNAC13.ProcessAddedMessage(dp); break; case SSIService.AuthorizationResponse: // 0x001B SNAC13.ProcessAuthorizationResponse(dp); break; case SSIService.FutureAuthorizationGranted: // 0x0015 SNAC13.ProcessFutureAuthorizationGrant(dp); break; case SSIService.AuthorizationRequest: //0x0019 SNAC13.ProcessAuthorizationRequest(dp); break; default: break; } } break; default: StringBuilder sb = new StringBuilder(); sb.AppendFormat( System.Globalization.CultureInfo.CurrentCulture.NumberFormat, "Unknown SNAC: ({0:x4},{1:x4}), flags = {2:x4}, requestID = {3:x8}", dp.SNAC.FamilyServiceID, dp.SNAC.FamilySubtypeID, dp.SNAC.Flags, dp.SNAC.RequestID); Logging.DumpFLAP(dp.Data.GetBytes(), sb.ToString()); break; } }
/// <summary> /// Processes the asynchronous receipt of a FLAP /// </summary> /// <param name="res">The <see cref="IAsyncResult"/> of a BeginReceive call</param> private void ProcessFLAP(IAsyncResult res) { int bytesreceived = 0; int receiveindex = 0; byte[] flapbuffer = null; try { lock (socket) { bytesreceived = socket.EndRead(res); if (bytesreceived == 0) { throw new Exception("Socket receive returned 0 bytes read"); } flapbuffer = (byte[])res.AsyncState; receiveindex = bytesreceived; while (receiveindex < flapbuffer.Length) { bytesreceived = socket.Read(flapbuffer, receiveindex, flapbuffer.Length - receiveindex); if (bytesreceived == 0) { throw new Exception("Socket receive returned 0 bytes read"); } receiveindex += bytesreceived; } } } catch (Exception ex) { if (!isDisconnecting) { Logging.WriteString("Receive error in ProcessFLAP: {0}, connection {1}", ex.Message, ID); DisconnectFromServer(true); } return; } if (flapbuffer[0] == 0xFF) { int badcount = 0; for (badcount = 0; badcount < flapbuffer.Length && flapbuffer[badcount] == 0xFF; badcount++) { ; } // SOMEHOW there are two bytes of 0xFF occuring when requesting // SNAC family 0x10 and receiving SNAC(01,03). So that has to stop for (int i = badcount; i < flapbuffer.Length; i++) { flapbuffer[i - badcount] = flapbuffer[i]; } socket.Read(flapbuffer, flapbuffer.Length - badcount, badcount); } // Get the FLAP header out of the async result FLAPHeader flap = GetFLAPHeader(flapbuffer); ByteStream stream = ReadPacket(flap.DataSize); if (stream == null) { return; } // The full packet is here, so we can chuck it out for processing DataPacket dp; switch (flap.Channel) { case 0x01: // New connection negotiation // This will not occur, FLAP 0x01 is handled in ConnectToServer break; case 0x02: // SNAC data if (stream.GetByteCount() < 10) { break; // Don't return, don't disconnect, just keep on keeping on } dp = stream.CreateDataPacket(); dp.FLAP = flap; dp.ParentConnection = this; dp.ParentSession = parent; Processor.Enqueue(dp); break; case 0x03: // FLAP error // Session error: FLAP error, bailing out Logging.WriteString("Received error FLAP"); DisconnectFromServer(true); return; case 0x04: // Close connection negotiation //KSD-SYSTEMS - added at 27.11.2009 if (stream.GetByteCount() > 10) { dp = stream.CreateDataPacket(); if (((SNACFamily)dp.SNAC.FamilyServiceID) == SNACFamily.PrivacyManagementService) { PrivacyManagementService sub = (PrivacyManagementService)dp.SNAC.FamilySubtypeID; if (sub == PrivacyManagementService.ServiceParametersRequest) { parent.OnError(ServerErrorCode.ExternalClientRequest, dp); } } } Logging.WriteString("Received close connection FLAP"); DisconnectFromServer(false); return; case 0x05: // Keepalive packet Logging.WriteString("Received keepalive FLAP"); SendKeepalive(null); break; default: break; } // Shine on, you crazy connection keepAliveTimer.Change(60000, Timeout.Infinite); ReadHeader(); }