/// <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(); }