private static void CorrectPluginMismatches(FetchPluginMetadataPacket mdPacket,
                                                    ref PluginActionPacket pluginActionPacket)
        {
            foreach (var remotePlugin in mdPacket.PluginList)
            {
                PluginAggregator.RemoteClientPlugin localPlugin = null;
                try
                {
                    localPlugin =
                        Globals.PluginAggregator.LoadedRemotePlugins.Find(
                            p => p.PluginGuid.Equals(remotePlugin.PluginGuid));
                }
                catch
                {
                }

                // Client has a plugin we don't, remove it
                if (localPlugin == null || !localPlugin.AssociatedServerPluginHost.Enabled)
                {
                    pluginActionPacket.Actions.Add(new PluginActionPacket.PluginActionData
                    {
                        Action        = PluginActionPacket.PluginAction.Remove,
                        PluginGuid    = remotePlugin.PluginGuid,
                        IntegrityHash = new byte[32],
                        PluginData    = new byte[] { 0 }
                    });
                }
                else if (!localPlugin.Hash.SequenceEquals(remotePlugin.IntegrityHash))
                {
                    pluginActionPacket.Actions.Add(new PluginActionPacket.PluginActionData
                    {
                        Action        = PluginActionPacket.PluginAction.Replace,
                        PluginGuid    = remotePlugin.PluginGuid,
                        IntegrityHash = localPlugin.Hash,
                        PluginData    = localPlugin.Data
                    });
                }
            }
        }
        public override void PacketReceived(IDataPacket packet, IChannel sender)
        {
            if (packet is FetchPluginMetadataPacket)
            {
                var retPacket = new FetchPluginMetadataPacket();
                // Send empty list if there are no plugins
                if (!File.Exists("plugins.blob"))
                {
                    SendPacket(retPacket);
                }
                else
                {
                    var blobReader = new PluginBlobReader("plugins.blob");
                    var md         = blobReader.ReadMetadata();
                    blobReader.Dispose();
                    foreach (var plugin in md.PluginTable)
                    {
                        retPacket.PluginList.Add(new PluginIntegrityPair(plugin.Key, plugin.Value.Hash));
                    }
                    SendPacket(retPacket);
                }
            }
            else if (packet is PluginActionPacket)
            {
                var actionPacket = packet as PluginActionPacket;

                var blobWriter = new PluginBlobWriter("plugins.blob");
                foreach (var action in actionPacket.Actions)
                {
                    switch (action.Action)
                    {
                    case PluginActionPacket.PluginAction.Add:
                        blobWriter.AppendPlugin(new BlobClientPlugin
                        {
                            Data       = action.PluginData,
                            Hash       = action.IntegrityHash,
                            Size       = action.PluginData.Length,
                            PluginGuid = action.PluginGuid
                        });
                        break;

                    case PluginActionPacket.PluginAction.Replace:
                        blobWriter.ReplacePlugin(action.PluginGuid, new BlobClientPlugin
                        {
                            Data       = action.PluginData,
                            Hash       = action.IntegrityHash,
                            Size       = action.PluginData.Length,
                            PluginGuid = action.PluginGuid
                        });
                        break;

                    case PluginActionPacket.PluginAction.Remove:
                        blobWriter.RemovePlugin(action.PluginGuid);
                        break;
                    }
                }
                blobWriter.WriteBlob();
                blobWriter.Dispose();
            }
            else if (packet is SynchronizationFinalizationPacket)
            {
                ActivatePlugins();
                SendPacket(new SynchronizationFinalizationPacket());
            }
        }