diff --git a/FFXIVAPP.Client/Constants.cs b/FFXIVAPP.Client/Constants.cs index 39127a5c..755466d7 100644 --- a/FFXIVAPP.Client/Constants.cs +++ b/FFXIVAPP.Client/Constants.cs @@ -32,7 +32,7 @@ using System.Diagnostics; using System.Globalization; using FFXIVAPP.Client.Helpers; -using FFXIVAPP.Client.Models; +using FFXIVAPP.Common.Core.Constant; namespace FFXIVAPP.Client { @@ -69,7 +69,11 @@ public static partial class Constants public static Dictionary Actions { get { return _actions ?? (_actions = new Dictionary()); } - set { _actions = value; } + set + { + _actions = value; + ConstantsHelper.UpdatePluginConstants(); + } } public static Dictionary AutoTranslate diff --git a/FFXIVAPP.Client/FFXIVAPP.Client.csproj b/FFXIVAPP.Client/FFXIVAPP.Client.csproj index 201829ab..f80a22c2 100644 --- a/FFXIVAPP.Client/FFXIVAPP.Client.csproj +++ b/FFXIVAPP.Client/FFXIVAPP.Client.csproj @@ -147,13 +147,11 @@ - - @@ -181,6 +179,20 @@ + + + + + + + + + + + + + + @@ -190,15 +202,12 @@ Settings.settings - - - diff --git a/FFXIVAPP.Client/Helpers/ActorEntityHelper.cs b/FFXIVAPP.Client/Helpers/ActorEntityHelper.cs index 735e31a7..f168dbe0 100644 --- a/FFXIVAPP.Client/Helpers/ActorEntityHelper.cs +++ b/FFXIVAPP.Client/Helpers/ActorEntityHelper.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; +using System.Linq; using FFXIVAPP.Client.Delegates; using FFXIVAPP.Client.Memory; using FFXIVAPP.Client.Properties; @@ -189,6 +190,7 @@ public static ActorEntity ResolveActorFromBytes(byte[] source, bool isCurrentUse Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize); var statusEntry = new StatusEntry { + TargetEntity = entry, TargetName = entry.Name, StatusID = BitConverter.ToInt16(statusSource, 0x0), Stacks = statusSource[0x2], @@ -196,6 +198,19 @@ public static ActorEntity ResolveActorFromBytes(byte[] source, bool isCurrentUse CasterID = BitConverter.ToUInt32(statusSource, 0x8) }; try + { + var pc = PCWorkerDelegate.GetUniqueNPCEntities() + .FirstOrDefault(a => a.ID == statusEntry.CasterID); + var npc = NPCWorkerDelegate.GetUniqueNPCEntities() + .FirstOrDefault(a => a.NPCID2 == statusEntry.CasterID); + var monster = MonsterWorkerDelegate.GetUniqueNPCEntities() + .FirstOrDefault(a => a.ID == statusEntry.CasterID); + statusEntry.SourceEntity = (pc ?? npc) ?? monster; + } + catch (Exception ex) + { + } + try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); statusEntry.IsCompanyAction = statusInfo.CompanyAction; diff --git a/FFXIVAPP.Client/Helpers/AppContextHelper.cs b/FFXIVAPP.Client/Helpers/AppContextHelper.cs index 8e5df3fb..97c5ed54 100644 --- a/FFXIVAPP.Client/Helpers/AppContextHelper.cs +++ b/FFXIVAPP.Client/Helpers/AppContextHelper.cs @@ -33,6 +33,7 @@ using FFXIVAPP.Client.Delegates; using FFXIVAPP.Common.Core.Constant; using FFXIVAPP.Common.Core.Memory; +using FFXIVAPP.Common.Core.Network; using NLog; namespace FFXIVAPP.Client.Helpers @@ -214,5 +215,11 @@ public void RaiseNewInventoryEntries(List inventoryEntities) // THIRD PARTY PluginHost.Instance.RaiseNewInventoryEntries(inventoryEntities); } + + public void RaiseNewPacket(NetworkPacket networkPacket) + { + // THIRD PARTY + PluginHost.Instance.RaiseNewNetworkPacket(networkPacket); + } } } diff --git a/FFXIVAPP.Client/Helpers/ConstantsHelper.cs b/FFXIVAPP.Client/Helpers/ConstantsHelper.cs index c463e1c9..397eca63 100644 --- a/FFXIVAPP.Client/Helpers/ConstantsHelper.cs +++ b/FFXIVAPP.Client/Helpers/ConstantsHelper.cs @@ -44,6 +44,7 @@ public static void UpdatePluginConstants() AutoTranslate = Constants.AutoTranslate, CharacterName = Constants.CharacterName, ChatCodes = Constants.ChatCodes, + Actions = Constants.Actions, ChatCodesXml = Constants.ChatCodesXml, Colors = Constants.Colors, CultureInfo = Constants.CultureInfo, diff --git a/FFXIVAPP.Client/Initializer.cs b/FFXIVAPP.Client/Initializer.cs index d683c7a6..bb245e71 100644 --- a/FFXIVAPP.Client/Initializer.cs +++ b/FFXIVAPP.Client/Initializer.cs @@ -42,10 +42,12 @@ using FFXIVAPP.Client.Helpers; using FFXIVAPP.Client.Memory; using FFXIVAPP.Client.Models; +using FFXIVAPP.Client.Network; using FFXIVAPP.Client.Properties; using FFXIVAPP.Client.Utilities; using FFXIVAPP.Client.ViewModels; using FFXIVAPP.Client.Views; +using FFXIVAPP.Common.Core.Constant; using FFXIVAPP.Common.Helpers; using Newtonsoft.Json.Linq; using NLog; @@ -62,7 +64,6 @@ internal static class Initializer #region Declarations - private static ActionWorker _actionWorker; private static ActorWorker _actorWorker; private static ChatLogWorker _chatLogWorker; private static MonsterWorker _monsterWorker; @@ -70,6 +71,7 @@ internal static class Initializer private static TargetWorker _targetWorker; private static PartyInfoWorker _partyInfoWorker; private static InventoryWorker _inventoryWorker; + private static NetworkWorker _networkWorker; #endregion @@ -589,7 +591,6 @@ public static void CheckUpdates() updateCheck.BeginInvoke(null, null); } - /// /// public static void SetSignatures() @@ -792,8 +793,6 @@ public static void StartMemoryWorkers() MemoryHandler.Instance.SigScanner.LoadOffsets(AppViewModel.Instance.Signatures); _chatLogWorker = new ChatLogWorker(); _chatLogWorker.StartScanning(); - //_actionWorker = new ActionWorker(); - //_actionWorker.StartScanning(); _actorWorker = new ActorWorker(); _actorWorker.StartScanning(); _monsterWorker = new MonsterWorker(); @@ -806,6 +805,8 @@ public static void StartMemoryWorkers() _partyInfoWorker.StartScanning(); _inventoryWorker = new InventoryWorker(); _inventoryWorker.StartScanning(); + _networkWorker = new NetworkWorker(); + _networkWorker.StartScanning(); } public static void UpdatePluginConstants() @@ -822,11 +823,6 @@ public static void StopMemoryWorkers() _chatLogWorker.StopScanning(); _chatLogWorker.Dispose(); } - if (_actionWorker != null) - { - _actionWorker.StopScanning(); - _actionWorker.Dispose(); - } if (_actorWorker != null) { _actorWorker.StopScanning(); @@ -857,6 +853,11 @@ public static void StopMemoryWorkers() _inventoryWorker.StopScanning(); _inventoryWorker.Dispose(); } + if (_networkWorker != null) + { + _networkWorker.StopScanning(); + _networkWorker.Dispose(); + } } } } diff --git a/FFXIVAPP.Client/Memory/ActionWorker.cs b/FFXIVAPP.Client/Memory/ActionWorker.cs deleted file mode 100644 index c52e5982..00000000 --- a/FFXIVAPP.Client/Memory/ActionWorker.cs +++ /dev/null @@ -1,334 +0,0 @@ -// FFXIVAPP.Client -// ActionWorker.cs -// -// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of SyndicatedLife nor the names of its contributors may -// be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Timers; -using FFXIVAPP.Client.Properties; -using FFXIVAPP.Client.Utilities; -using FFXIVAPP.Common.Core.Memory.Enums; -using FFXIVAPP.Common.Utilities; -using NLog; - -namespace FFXIVAPP.Client.Memory -{ - internal class ActionWorker : INotifyPropertyChanged, IDisposable - { - #region Logger - - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - #endregion - - #region Property Bindings - - #endregion - - #region Declarations - - private readonly Timer _scanTimer; - private bool _isScanning; - - #endregion - - public ActionWorker() - { - _scanTimer = new Timer(5); - _scanTimer.Elapsed += ScanTimerElapsed; - } - - #region Timer Controls - - /// - /// - public void StartScanning() - { - _scanTimer.Enabled = true; - } - - /// - /// - public void StopScanning() - { - _scanTimer.Enabled = false; - } - - #endregion - - #region Threads - - public Stopwatch Stopwatch = new Stopwatch(); - - /// - /// - /// - /// - private void ScanTimerElapsed(object sender, ElapsedEventArgs e) - { - if (_isScanning) - { - return; - } - _isScanning = true; - double refresh = 5; - if (Double.TryParse(Settings.Default.ActionWorkerRefresh.ToString(CultureInfo.InvariantCulture), out refresh)) - { - _scanTimer.Interval = refresh; - } - Func scannerWorker = delegate - { - if (MemoryHandler.Instance.SigScanner.Locations.ContainsKey("GAMEMAIN")) - { - if (MemoryHandler.Instance.SigScanner.Locations.ContainsKey("CHARMAP")) - { - try - { - //Stopwatch.Reset(); - //Stopwatch.Start(); - - var characterAddressMap = MemoryHandler.Instance.SigScanner.Locations["CHARMAP"]; - var characterAddresses = MemoryHandler.Instance.GetStructure(characterAddressMap); - var sources = characterAddresses.Locations.Where(c => c.BaseAddress > 0) - .ToList() - .Select(c => MemoryHandler.Instance.GetByteArray(c.BaseAddress, 0x3F40)) - .ToList(); - foreach (var source in sources.AsParallel() - .Where(s => s.Count() > 0)) - { - var entryID = BitConverter.ToUInt32(source, 0x74); - var entryType = (Actor.Type) source[0x8A]; - var entryName = MemoryHandler.Instance.GetStringFromBytes(source, 48); - - #region FlyingText Handler - - try - { - var flyingTextEntries = new List(); - - switch (entryType) - { - case Actor.Type.Monster: - case Actor.Type.PC: - IntPtr flyingTextAddress; - if ((flyingTextAddress = MemoryHandler.Instance.ReadPointer((IntPtr) BitConverter.ToUInt32(source, 0x3194))) == IntPtr.Zero) - { - continue; - } - var limit = MemoryHandler.Instance.GetInt32(BitConverter.ToUInt32(source, 0x3198)); - //MemoryHandler.Instance.ReadInt32((IntPtr) characterAddress, 0x319C); - //MemoryHandler.Instance.ReadInt32((IntPtr) characterAddress, 0x31A0); - //MemoryHandler.Instance.ReadInt32((IntPtr) characterAddress, 0x31B0); - if (limit < 0x100) - { - for (var m = 0; m < limit; m++) - { - try - { - IntPtr ptr3; - if ((ptr3 = MemoryHandler.Instance.ReadPointer(IntPtr.Add(flyingTextAddress, m * 4))) == IntPtr.Zero) - { - continue; - } - IntPtr ptr4; - if ((ptr4 = MemoryHandler.Instance.ReadPointer(IntPtr.Add(ptr3, 4))) == IntPtr.Zero) - { - continue; - } - IntPtr ptr5; - if ((ptr5 = MemoryHandler.Instance.ReadPointer(IntPtr.Add(ptr4, 0))) == IntPtr.Zero) - { - continue; - } - IntPtr ptr6; - if ((ptr6 = MemoryHandler.Instance.ReadPointer(IntPtr.Add(ptr5, 4))) == IntPtr.Zero) - { - continue; - } - var flyingTextEntry = new FlyingTextEntry - { - ID = (uint) ptr3.ToInt64(), - Amount = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 0x10)), - ComboAmount = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 20)), - Type1 = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 4)), - Type2 = MemoryHandler.Instance.ReadInt32(ptr3), - SkillID = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 12)), - UNK1 = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6)), - UNK2 = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 8)), - UNK3 = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 0x18)), - UNK4 = MemoryHandler.Instance.ReadInt32(MemoryHandler.Instance.ReadPointer(ptr6, 0x1C)), - TargetID = entryID, - TargetName = entryName, - TargetType = entryType - }; - if (flyingTextEntry.SkillID > 0) - { - flyingTextEntries.Add(flyingTextEntry); - } - } - catch (Exception ex) - { - } - } - } - break; - } - } - catch (Exception ex) - { - } - - #endregion - - #region IncomingAction Handler - - var incomingActionEntries = new List(); - - try - { - switch (entryType) - { - case Actor.Type.Monster: - case Actor.Type.PC: - var sourceArray = new byte[0xBB8]; - Buffer.BlockCopy(source, 0x3480, sourceArray, 0, 0xBB8); - for (uint d = 0; d < 30; d++) - { - try - { - var destinationArray = new byte[100]; - var index = d * 100; - Array.Copy(sourceArray, index, destinationArray, 0, 100); - var incomingActionEntry = new IncomingActionEntry - { - Code = BitConverter.ToInt32(destinationArray, 0), - SequenceID = BitConverter.ToInt32(destinationArray, 4), - SkillID = BitConverter.ToInt32(destinationArray, 12), - SourceID = BitConverter.ToUInt32(destinationArray, 20), - Type = destinationArray[66], - Amount = BitConverter.ToInt16(destinationArray, 70), - TargetID = entryID, - TargetName = entryName, - TargetType = entryType - }; - if (incomingActionEntry.SequenceID > 0 && incomingActionEntry.SkillID > 0 && incomingActionEntry.SourceID > 0) - { - incomingActionEntries.Add(incomingActionEntry); - } - } - catch (Exception ex) - { - } - } - break; - } - } - catch (Exception ex) - { - } - - #endregion - - #region OutGoing Handler - - var outGoingActionEntries = new List(); - - try - { - switch (entryType) - { - case Actor.Type.Monster: - case Actor.Type.PC: - var sourceArray = new byte[0x108]; - Buffer.BlockCopy(source, 0x3334, sourceArray, 0, 0x108); - var outGoingActionEntry = new OutGoingActionEntry - { - Amount = 0, - SequenceID = BitConverter.ToInt32(sourceArray, 8), - SkillID = BitConverter.ToInt32(sourceArray, 0), - SourceID = entryID, - TargetID = BitConverter.ToUInt32(sourceArray, 12), - Type = source[0x8A] - }; - if (outGoingActionEntry.SequenceID > 0 && outGoingActionEntry.SkillID > 0 && outGoingActionEntry.SourceID > 0 && outGoingActionEntry.TargetID != 0xE0000000) - { - outGoingActionEntries.Add(outGoingActionEntry); - } - break; - } - } - catch (Exception ex) - { - } - - #endregion - } - - //Stopwatch.Stop(); - //Logging.Log(Logger, Stopwatch.ElapsedMilliseconds.ToString()); - } - catch (Exception ex) - { - Logging.Log(Logger, "", ex); - } - } - } - _isScanning = false; - return true; - }; - scannerWorker.BeginInvoke(delegate { }, scannerWorker); - } - - #endregion - - #region Implementation of INotifyPropertyChanged - - public event PropertyChangedEventHandler PropertyChanged = delegate { }; - - private void RaisePropertyChanged([CallerMemberName] string caller = "") - { - PropertyChanged(this, new PropertyChangedEventArgs(caller)); - } - - #endregion - - #region Implementation of IDisposable - - public void Dispose() - { - _scanTimer.Elapsed -= ScanTimerElapsed; - } - - #endregion - } -} diff --git a/FFXIVAPP.Client/Memory/TargetWorker.cs b/FFXIVAPP.Client/Memory/TargetWorker.cs index 239da32f..7e07dc9c 100644 --- a/FFXIVAPP.Client/Memory/TargetWorker.cs +++ b/FFXIVAPP.Client/Memory/TargetWorker.cs @@ -274,42 +274,30 @@ private void ScanTimerElapsed(object sender, ElapsedEventArgs e) continue; } if (PCWorkerDelegate.GetUniqueNPCEntities() - .Any()) - { - if (PCWorkerDelegate.GetUniqueNPCEntities() .Any(a => a.ID == enmityEntry.ID)) - { - enmityEntry.Name = PCWorkerDelegate.GetUniqueNPCEntities() - .First(a => a.ID == enmityEntry.ID) - .Name; - } + { + enmityEntry.Name = PCWorkerDelegate.GetUniqueNPCEntities() + .First(a => a.ID == enmityEntry.ID) + .Name; } if (String.IsNullOrWhiteSpace(enmityEntry.Name)) { if (NPCWorkerDelegate.GetUniqueNPCEntities() - .Any()) + .Any(a => a.NPCID2 == enmityEntry.ID)) { - if (NPCWorkerDelegate.GetUniqueNPCEntities() - .Any(a => a.ID == enmityEntry.ID)) - { - enmityEntry.Name = NPCWorkerDelegate.GetUniqueNPCEntities() - .First(a => a.NPCID2 == enmityEntry.ID) - .Name; - } + enmityEntry.Name = NPCWorkerDelegate.GetUniqueNPCEntities() + .First(a => a.NPCID2 == enmityEntry.ID) + .Name; } } if (String.IsNullOrWhiteSpace(enmityEntry.Name)) { if (MonsterWorkerDelegate.GetUniqueNPCEntities() - .Any()) - { - if (MonsterWorkerDelegate.GetUniqueNPCEntities() .Any(a => a.ID == enmityEntry.ID)) - { - enmityEntry.Name = MonsterWorkerDelegate.GetUniqueNPCEntities() - .First(a => a.ID == enmityEntry.ID) - .Name; - } + { + enmityEntry.Name = MonsterWorkerDelegate.GetUniqueNPCEntities() + .First(a => a.ID == enmityEntry.ID) + .Name; } } enmityEntries.Add(enmityEntry); diff --git a/FFXIVAPP.Client/Network/DNSHeader.cs b/FFXIVAPP.Client/Network/DNSHeader.cs new file mode 100644 index 00000000..90654121 --- /dev/null +++ b/FFXIVAPP.Client/Network/DNSHeader.cs @@ -0,0 +1,98 @@ +// FFXIVAPP.Client +// DNSHeader.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Globalization; +using System.IO; +using System.Net; + +namespace FFXIVAPP.Client.Network +{ + public class DNSHeader + { + private readonly ushort _flags; + private readonly ushort _identification; + private readonly ushort _totalAdditionalRR; + private readonly ushort _totalAnswerRR; + private readonly ushort _totalAuthorityRR; + private readonly ushort _totalQuestions; + + public DNSHeader(byte[] byBuffer, int nReceived) + { + try + { + using (var memoryStream = new MemoryStream(byBuffer, 0, nReceived)) + { + using (var binaryReader = new BinaryReader(memoryStream)) + { + _identification = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _flags = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _totalQuestions = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _totalAnswerRR = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _totalAuthorityRR = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _totalAdditionalRR = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + } + } + } + catch (Exception ex) + { + } + } + + public string Identification + { + get { return String.Format("0x{0:x2}", _identification); } + } + + public string Flags + { + get { return String.Format("0x{0:x2}", _flags); } + } + + public string TotalQuestions + { + get { return _totalQuestions.ToString(CultureInfo.InvariantCulture); } + } + + public string TotalAnswerRR + { + get { return _totalAnswerRR.ToString(CultureInfo.InvariantCulture); } + } + + public string TotalAuthorityRR + { + get { return _totalAuthorityRR.ToString(CultureInfo.InvariantCulture); } + } + + public string TotalAdditionalRR + { + get { return _totalAdditionalRR.ToString(CultureInfo.InvariantCulture); } + } + } +} diff --git a/FFXIVAPP.Client/Network/IPHeader.cs b/FFXIVAPP.Client/Network/IPHeader.cs new file mode 100644 index 00000000..91b9846d --- /dev/null +++ b/FFXIVAPP.Client/Network/IPHeader.cs @@ -0,0 +1,198 @@ +// FFXIVAPP.Client +// IPHeader.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; + +namespace FFXIVAPP.Client.Network +{ + public class IPHeader + { + private readonly byte _TTL; + private readonly short _checksum; + private readonly List _data = new List(); + private readonly uint _destinationIPAddress; + private readonly byte _differentiatedServices; + private readonly ushort _flags; + private readonly byte _headerLength; + private readonly ushort _identification; + private readonly byte _protocol; + private readonly uint _sourceIPAddress; + private readonly ushort _totalLength; + private readonly byte _versionAndHeaderLength; + + public IPHeader(byte[] byBuffer, int nReceived) + { + try + { + using (var memoryStream = new MemoryStream(byBuffer, 0, nReceived)) + { + using (var binaryReader = new BinaryReader(memoryStream)) + { + _versionAndHeaderLength = binaryReader.ReadByte(); + _differentiatedServices = binaryReader.ReadByte(); + _totalLength = (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _identification = (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _flags = (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _TTL = binaryReader.ReadByte(); + _protocol = binaryReader.ReadByte(); + _checksum = IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _sourceIPAddress = (uint)(binaryReader.ReadInt32()); + _destinationIPAddress = (uint)(binaryReader.ReadInt32()); + _headerLength = _versionAndHeaderLength; + _headerLength <<= 4; + _headerLength >>= 4; + _headerLength *= 4; + var tempData = new byte[_totalLength - _headerLength]; + Array.Copy(byBuffer, _headerLength, tempData, 0, _totalLength - _headerLength); + foreach (var b in tempData) + { + _data.Add(b); + } + } + } + } + catch (Exception ex) + { + } + } + + public string Version + { + get + { + switch ((_versionAndHeaderLength >> 4)) + { + case 4: + return "IP v4"; + case 6: + return "IP v6"; + default: + return "Unknown"; + } + } + } + + public string HeaderLength + { + get { return _headerLength.ToString(); } + } + + public ushort MessageLength + { + get { return (ushort) (_totalLength - _headerLength); } + } + + public string DifferentiatedServices + { + get { return String.Format("0x{0:x2} ({1})", _differentiatedServices, _differentiatedServices); } + } + + public string Flags + { + get + { + var newFlags = _flags >> 13; + switch (newFlags) + { + case 2: + return "Don't fragment"; + case 1: + return "More fragments to come"; + default: + return newFlags.ToString(CultureInfo.InvariantCulture); + } + } + } + + public string FragmentationOffset + { + get + { + var newOffset = _flags << 3; + newOffset >>= 3; + return newOffset.ToString(CultureInfo.InvariantCulture); + } + } + + public string TTL + { + get { return _TTL.ToString(CultureInfo.InvariantCulture); } + } + + public Protocol ProtocolType + { + get + { + switch (_protocol) + { + case 6: + return Protocol.TCP; + case 17: + return Protocol.UDP; + default: + return Protocol.Unknown; + } + } + } + + public string Checksum + { + get { return String.Format("0x{0:x2}", _checksum); } + } + + public IPAddress SourceAddress + { + get { return new IPAddress(_sourceIPAddress); } + } + + public IPAddress DestinationAddress + { + get { return new IPAddress(_destinationIPAddress); } + } + + public string TotalLength + { + get { return _totalLength.ToString(CultureInfo.InvariantCulture); } + } + + public string Identification + { + get { return _identification.ToString(CultureInfo.InvariantCulture); } + } + + public List Data + { + get { return _data; } + } + } +} diff --git a/FFXIVAPP.Client/Network/IPHelper.cs b/FFXIVAPP.Client/Network/IPHelper.cs new file mode 100644 index 00000000..028c986b --- /dev/null +++ b/FFXIVAPP.Client/Network/IPHelper.cs @@ -0,0 +1,75 @@ +// FFXIVAPP.Client +// IPHelper.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace FFXIVAPP.Client.Network +{ + public static class IPHelper + { + #region Public Methods + + public static TCPTable GetExtendedTCPTable(bool sorted) + { + var tcpRows = new List(); + var tcpTable = IntPtr.Zero; + var tcpTableLength = 0; + if (UnsafeNativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, 2, UnsafeNativeMethods.TCP_TABLE_CLASS.OWNER_PID_ALL) == 0) + { + return new TCPTable(tcpRows); + } + try + { + tcpTable = Marshal.AllocHGlobal(tcpTableLength); + if (UnsafeNativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, 2, UnsafeNativeMethods.TCP_TABLE_CLASS.OWNER_PID_ALL) == 0) + { + var table = (UnsafeNativeMethods.TCPTable) Marshal.PtrToStructure(tcpTable, typeof (UnsafeNativeMethods.TCPTable)); + var rowPtr = (IntPtr) ((long) tcpTable + Marshal.SizeOf(table.Length)); + for (var i = 0; i < table.Length; ++i) + { + tcpRows.Add(new TCPRow((UnsafeNativeMethods.TCPRow) Marshal.PtrToStructure(rowPtr, typeof (UnsafeNativeMethods.TCPRow)))); + rowPtr = (IntPtr) ((long) rowPtr + Marshal.SizeOf(typeof (UnsafeNativeMethods.TCPRow))); + } + } + } + finally + { + if (tcpTable != IntPtr.Zero) + { + Marshal.FreeHGlobal(tcpTable); + } + } + return new TCPTable(tcpRows); + } + + #endregion + } +} diff --git a/FFXIVAPP.Client/Utilities/OutGoingActionEntry.cs b/FFXIVAPP.Client/Network/NetworkConnection.cs similarity index 69% rename from FFXIVAPP.Client/Utilities/OutGoingActionEntry.cs rename to FFXIVAPP.Client/Network/NetworkConnection.cs index 5dacf6fd..f3cc6088 100644 --- a/FFXIVAPP.Client/Utilities/OutGoingActionEntry.cs +++ b/FFXIVAPP.Client/Network/NetworkConnection.cs @@ -1,5 +1,5 @@ // FFXIVAPP.Client -// OutGoingActionEntry.cs +// NetworkConnection.cs // // Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved // @@ -27,34 +27,21 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -#region Usings +using System; +using System.Collections.Generic; -using FFXIVAPP.Client.Helpers; -using FFXIVAPP.Common.Core.Memory.Enums; - -#endregion - -namespace FFXIVAPP.Client.Utilities +namespace FFXIVAPP.Client.Network { - public class OutGoingActionEntry + public class NetworkConnection : ServerConnection { - #region Memory Array Items - - public int SequenceID { get; set; } - public int SkillID { get; set; } - public uint SourceID { get; set; } - public byte Type { get; set; } - public int Amount { get; set; } - - #endregion - - public string SkillName - { - get { return ConstantsHelper.GetActionNameByID(SkillID); } - } - - public uint TargetID { get; set; } - public string TargetName { get; set; } - public Actor.Type TargetType { get; set; } + private const int NetworkBufferMax = 0x19000; + public DateTime LastGoodNetworkPacketTime = DateTime.MinValue; + public DateTime LastNetworkBufferUpdate = DateTime.Now; + public byte[] NetworkBuffer = new byte[0x19000]; + public object NetworkBufferLock = new object(); + public int NetworkBufferPosition; + public uint? NextTCPSequence; + public Dictionary StalePackets = new Dictionary(); + public object StalePacketsLock = new object(); } } diff --git a/FFXIVAPP.Client/Models/ActionInfo.cs b/FFXIVAPP.Client/Network/NetworkPacket.cs similarity index 75% rename from FFXIVAPP.Client/Models/ActionInfo.cs rename to FFXIVAPP.Client/Network/NetworkPacket.cs index 0cfce52f..3d7ec137 100644 --- a/FFXIVAPP.Client/Models/ActionInfo.cs +++ b/FFXIVAPP.Client/Network/NetworkPacket.cs @@ -1,5 +1,5 @@ // FFXIVAPP.Client -// ActionInfo.cs +// NetworkPacket.cs // // Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved // @@ -27,19 +27,12 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -namespace FFXIVAPP.Client.Models +namespace FFXIVAPP.Client.Network { - public class ActionInfo + public class NetworkPacket { - public string ZH { get; set; } - public string JA { get; set; } - public string EN { get; set; } - public string FR { get; set; } - public string DE { get; set; } - public string ZH_HelpLabel { get; set; } - public string JA_HelpLabel { get; set; } - public string EN_HelpLabel { get; set; } - public string FR_HelpLabel { get; set; } - public string DE_HelpLabel { get; set; } + public byte[] Buffer; + public bool Push; + public uint TCPSequence; } } diff --git a/FFXIVAPP.Client/Network/NetworkWorker.cs b/FFXIVAPP.Client/Network/NetworkWorker.cs new file mode 100644 index 00000000..e324cca9 --- /dev/null +++ b/FFXIVAPP.Client/Network/NetworkWorker.cs @@ -0,0 +1,575 @@ +// FFXIVAPP.Client +// NetworkWorker.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Text; +using FFXIVAPP.Client.Helpers; +using FFXIVAPP.Common.Helpers; +using NLog; + +namespace FFXIVAPP.Client.Network +{ + internal class NetworkWorker : INotifyPropertyChanged, IDisposable + { + #region Logger + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + #endregion + + #region Property Bindings + + #endregion + + #region Declarations + + private List ServerConnections = new List(); + private List Sockets = new List(); + private List DroppedConnections = new List(); + private object Lock = new object(); + + #endregion + + public NetworkWorker() + { + } + + #region Timer Controls + + /// + /// + public void StartScanning() + { + var interfaces = GetNetworkInterfaces(); + foreach (var item in interfaces.Where(x => !String.IsNullOrWhiteSpace(x)) + .Select(address => new SocketObject + { + IPAddress = address + })) + { + Sockets.Add(item); + } + UpdateConnectionList(); + foreach (var stateObject in Sockets) + { + try + { + stateObject.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); + stateObject.Socket.Bind(new IPEndPoint(IPAddress.Parse(stateObject.IPAddress), 0)); + stateObject.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true); + var isTrue = new byte[] + { + 3, 0, 0, 0 + }; + var isOut = new byte[] + { + 1, 0, 0, 0 + }; + stateObject.Socket.IOControl(IOControlCode.ReceiveAll, isTrue, isOut); + stateObject.Socket.ReceiveBufferSize = 0x7D000; + stateObject.Socket.BeginReceive(stateObject.Buffer, 0, stateObject.Buffer.Length, SocketFlags.None, OnReceive, stateObject); + } + catch (Exception ex) + { + } + } + } + + /// + /// + public void StopScanning() + { + foreach (var stateObject in Sockets) + { + try + { + if (stateObject == null) + { + continue; + } + if (stateObject.Socket != null) + { + stateObject.Socket.Shutdown(SocketShutdown.Both); + stateObject.Socket.Close(); + stateObject.Socket.Dispose(); + stateObject.Socket = null; + } + lock (stateObject.SocketLock) + { + stateObject.Connections = new List(); + } + } + catch (Exception ex) + { + } + } + Sockets.Clear(); + ServerConnections.Clear(); + DroppedConnections.Clear(); + } + + #endregion + + #region Threads + + private void OnReceive(IAsyncResult ar) + { + try + { + var asyncState = (SocketObject) ar.AsyncState; + int nReceived; + try + { + nReceived = asyncState.Socket.EndReceive(ar); + } + catch (Exception ex) + { + nReceived = 0; + } + if (nReceived > 0) + { + try + { + DispatcherHelper.Invoke(() => ParseData(asyncState, asyncState.Buffer, nReceived)); + } + catch (Exception ex) + { + } + } + asyncState.Socket.BeginReceive(asyncState.Buffer, 0, asyncState.Buffer.Length, SocketFlags.None, OnReceive, asyncState); + } + catch (ObjectDisposedException) + { + } + catch (Exception ex) + { + } + } + + #region Parsing + + private void ParseData(SocketObject asyncState, byte[] byteData, int nReceived) + { + if ((byteData == null) || (byteData[9] != 6)) + { + return; + } + var startIndex = (byte) ((byteData[0] & 15) * 4); + var lengthCheck = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(byteData, 2)); + if ((nReceived < lengthCheck) || (startIndex > lengthCheck)) + { + return; + } + var IP = new IPHeader(byteData, nReceived); + var TCP = new TCPHeader(byteData, nReceived); + var serverConnection = new ServerConnection + { + DestinationAddress = BitConverter.ToUInt32(IP.DestinationAddress.GetAddressBytes(), 0), + DestinationPort = Convert.ToUInt16(TCP.DestinationPort), + SourcePort = Convert.ToUInt16(TCP.SourcePort), + SourceAddress = BitConverter.ToUInt32(IP.SourceAddress.GetAddressBytes(), 0), + TimeStamp = DateTime.Now + }; + lock (Lock) + { + var found = Enumerable.Contains(ServerConnections, serverConnection); + if (!found) + { + if (Enumerable.Contains(DroppedConnections, serverConnection)) + { + found = true; + } + if (found) + { + return; + } + UpdateConnectionList(); + if (Enumerable.Contains(ServerConnections, serverConnection)) + { + found = true; + } + if (!found) + { + DroppedConnections.Add(serverConnection); + return; + } + } + } + if ((startIndex + 12) > nReceived) + { + return; + } + var nextTCPSequence = (uint) IPAddress.NetworkToHostOrder(BitConverter.ToInt32(byteData, startIndex + 4)); + var cut = (byte) (((byteData[startIndex + 12] & 240) >> 4) * 4); + var length = (nReceived - startIndex) - cut; + if ((length < 0) || (length > 0x10000)) + { + return; + } + lock (asyncState.SocketLock) + { + Func, bool> func = null; + Func predicate = x => x.Equals(serverConnection); + var connection = asyncState.Connections.FirstOrDefault(predicate); + if (connection == null) + { + connection = new NetworkConnection + { + SourceAddress = serverConnection.SourceAddress, + SourcePort = serverConnection.SourcePort, + DestinationAddress = serverConnection.DestinationAddress, + DestinationPort = serverConnection.DestinationPort + }; + asyncState.Connections.Add(connection); + } + if (length == 0) + { + return; + } + var destinationBuffer = new byte[length]; + Array.Copy(byteData, startIndex + cut, destinationBuffer, 0, length); + if (connection.StalePackets.ContainsKey(nextTCPSequence)) + { + connection.StalePackets.Remove(nextTCPSequence); + } + var packet = new NetworkPacket + { + TCPSequence = nextTCPSequence, + Buffer = destinationBuffer, + Push = (byteData[startIndex + 13] & 8) != 0 + }; + connection.StalePackets.Add(nextTCPSequence, packet); + if (!connection.NextTCPSequence.HasValue) + { + connection.NextTCPSequence = nextTCPSequence; + } + if (connection.StalePackets.Count == 1) + { + connection.LastGoodNetworkPacketTime = DateTime.Now; + } + if (!connection.StalePackets.Any(x => (x.Key <= connection.NextTCPSequence.Value))) + { + if (DateTime.Now.Subtract(connection.LastGoodNetworkPacketTime) + .TotalSeconds <= 10.0) + { + return; + } + connection.NextTCPSequence = connection.StalePackets.Min(x => x.Key); + } + while (connection.StalePackets.Any(x => x.Key <= connection.NextTCPSequence.Value)) + { + NetworkPacket stalePacket; + uint sequenceLength = 0; + if (connection.StalePackets.ContainsKey(connection.NextTCPSequence.Value)) + { + stalePacket = connection.StalePackets[connection.NextTCPSequence.Value]; + } + else + { + if (func == null) + { + func = x => x.Key <= connection.NextTCPSequence.Value; + } + stalePacket = (connection.StalePackets.Where(func) + .OrderBy(x => x.Key)).FirstOrDefault() + .Value; + sequenceLength = connection.NextTCPSequence.Value - stalePacket.TCPSequence; + } + connection.StalePackets.Remove(stalePacket.TCPSequence); + if (connection.NetworkBufferPosition == 0) + { + connection.LastNetworkBufferUpdate = DateTime.Now; + } + if (sequenceLength >= stalePacket.Buffer.Length) + { + continue; + } + connection.NextTCPSequence = stalePacket.TCPSequence + ((uint) stalePacket.Buffer.Length); + Array.Copy(stalePacket.Buffer, sequenceLength, connection.NetworkBuffer, connection.NetworkBufferPosition, stalePacket.Buffer.Length - sequenceLength); + connection.NetworkBufferPosition += stalePacket.Buffer.Length - ((int) sequenceLength); + if (stalePacket.Push) + { + ProcessNetworkBuffer(connection); + } + } + } + } + + #endregion + + #region Processing + + private void ProcessNetworkBuffer(NetworkConnection connection) + { + int messageLength; + InitialProcess: + if (connection.NetworkBufferPosition < 0x1C) + { + return; + } + uint bufferSize; + byte[] destinationArray; + lock (connection.NetworkBufferLock) + { + var indexes = new List + { + BitConverter.ToUInt32(connection.NetworkBuffer, 0), + BitConverter.ToUInt32(connection.NetworkBuffer, 4), + BitConverter.ToUInt32(connection.NetworkBuffer, 8), + BitConverter.ToUInt32(connection.NetworkBuffer, 12) + }; + if ((indexes[0] != 0x41A05252) && ((indexes.Any(x => x != 0)))) + { + AdjustNetworkBuffer(connection); + return; + } + bufferSize = BitConverter.ToUInt32(connection.NetworkBuffer, 0x18); + if ((bufferSize == 0) || (bufferSize > 0x10000)) + { + AdjustNetworkBuffer(connection); + return; + } + if (connection.NetworkBufferPosition < bufferSize) + { + if (DateTime.Now.Subtract(connection.LastNetworkBufferUpdate) + .Seconds <= 5) + { + return; + } + AdjustNetworkBuffer(connection); + return; + } + destinationArray = new byte[bufferSize]; + Array.Copy(connection.NetworkBuffer, destinationArray, bufferSize); + Array.Copy(connection.NetworkBuffer, bufferSize, connection.NetworkBuffer, 0L, connection.NetworkBufferPosition - bufferSize); + connection.NetworkBufferPosition -= (int) bufferSize; + connection.LastNetworkBufferUpdate = DateTime.Now; + } + if (bufferSize <= 40) + { + return; + } + var timeDifference = BitConverter.ToUInt64(destinationArray, 0x10); + var time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(timeDifference) + .ToLocalTime(); + int limiter = BitConverter.ToInt16(destinationArray, 30); + int code = BitConverter.ToInt16(destinationArray, 0x20); + var bytes = new byte[0x10000]; + switch (code) + { + case 0: + case 1: + messageLength = ((int) bufferSize) - 40; + for (var i = 0; i < ((bufferSize / 4) - 10); i++) + { + Array.Copy(BitConverter.GetBytes(BitConverter.ToUInt32(destinationArray, (i * 4) + 40)), 0, bytes, i * 4, 4); + } + goto SubProcess; + } + try + { + using (var destinationStream = new MemoryStream(destinationArray, 0x2A, destinationArray.Length - 0x2A)) + { + using (var decompressedStream = new DeflateStream(destinationStream, CompressionMode.Decompress)) + { + messageLength = decompressedStream.Read(bytes, 0, bytes.Length); + } + } + } + catch (Exception ex) + { + return; + } + SubProcess: + var position = 0; + try + { + for (var i = 0; i < limiter; i++) + { + if ((position + 4) > messageLength) + { + return; + } + var messageSize = BitConverter.ToUInt32(bytes, position); + if ((position + messageSize) > messageLength) + { + return; + } + if (messageSize > 0x18) + { + AppContextHelper.Instance.RaiseNewPacket(new Common.Core.Network.NetworkPacket + { + Key = BitConverter.ToUInt32(bytes, position + 0x10), + Buffer = bytes, + CurrentPosition = position, + MessageSize = (int) messageSize, + PacketDate = time + }); + } + position += (int) messageSize; + } + goto InitialProcess; + } + catch (Exception ex) + { + } + } + + #endregion + + #endregion + + #region Functions + + private IEnumerable GetNetworkInterfaces() + { + var source = new List(); + foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces()) + { + using (var enumerator = (networkInterface.GetIPProperties() + .UnicastAddresses.Select(x => x.Address.ToString())).GetEnumerator()) + { + while (enumerator.MoveNext()) + { + var ip = enumerator.Current; + if (((ip.Length <= 15) && ip.Contains('.')) && !source.Any(x => (x == ip))) + { + source.Add(ip); + } + } + } + } + return source; + } + + private void UpdateConnectionList() + { + var serverIPList = GetXIVServerIPList(); + if (serverIPList != null) + { + if (ServerConnections.Any()) + { + foreach (var server in serverIPList) + { + var serverIP = server; + foreach (var connection in ServerConnections.Where(connection => !serverIP.Equals(connection))) + { + ServerConnections.Add(server); + } + } + } + else + { + ServerConnections = serverIPList; + } + } + var removeFromDropped = new List(); + foreach (var connection in DroppedConnections) + { + if (DateTime.Now.Subtract(connection.TimeStamp) + .TotalMilliseconds > 30000.0) + { + removeFromDropped.Add(connection); + continue; + } + var found = Enumerable.Contains(ServerConnections, connection); + if (found) + { + removeFromDropped.Add(connection); + } + } + foreach (var connection in removeFromDropped) + { + DroppedConnections.Remove(connection); + } + } + + private static List GetXIVServerIPList() + { + var tables = IPHelper.GetExtendedTCPTable(true); + return (tables.Cast() + .Where(table => table.ProcessId == Constants.ProcessID) + .Select(table => new ServerConnection + { + SourceAddress = BitConverter.ToUInt32(table.RemoteEndPoint.Address.GetAddressBytes(), 0), + SourcePort = (ushort) table.RemoteEndPoint.Port, + DestinationAddress = BitConverter.ToUInt32(table.LocalEndPoint.Address.GetAddressBytes(), 0), + DestinationPort = (ushort) table.LocalEndPoint.Port + })).ToList(); + } + + private void AdjustNetworkBuffer(NetworkConnection connection) + { + var startIndex = 1; + while ((BitConverter.ToUInt32(connection.NetworkBuffer, startIndex) != 0x41A05252) && (startIndex < connection.NetworkBufferPosition)) + { + startIndex++; + } + if (startIndex >= connection.NetworkBufferPosition) + { + connection.NetworkBufferPosition = 0; + } + else + { + Array.Copy(connection.NetworkBuffer, startIndex, connection.NetworkBuffer, 0, connection.NetworkBufferPosition - startIndex); + connection.NetworkBufferPosition -= startIndex; + } + } + + #endregion + + #region Implementation of INotifyPropertyChanged + + public event PropertyChangedEventHandler PropertyChanged = delegate { }; + + private void RaisePropertyChanged([CallerMemberName] string caller = "") + { + PropertyChanged(this, new PropertyChangedEventArgs(caller)); + } + + #endregion + + #region Implementation of IDisposable + + public void Dispose() + { + } + + #endregion + } +} diff --git a/FFXIVAPP.Client/Network/Protocol.cs b/FFXIVAPP.Client/Network/Protocol.cs new file mode 100644 index 00000000..59e876be --- /dev/null +++ b/FFXIVAPP.Client/Network/Protocol.cs @@ -0,0 +1,38 @@ +// FFXIVAPP.Client +// Protocol.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +namespace FFXIVAPP.Client.Network +{ + public enum Protocol + { + TCP = 6, + UDP = 17, + Unknown = -1 + }; +} diff --git a/FFXIVAPP.Client/Network/ServerConnection.cs b/FFXIVAPP.Client/Network/ServerConnection.cs new file mode 100644 index 00000000..ae33b0a1 --- /dev/null +++ b/FFXIVAPP.Client/Network/ServerConnection.cs @@ -0,0 +1,63 @@ +// FFXIVAPP.Client +// XIVConnection.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Net; + +namespace FFXIVAPP.Client.Network +{ + public class ServerConnection + { + public uint DestinationAddress; + public ushort DestinationPort; + public uint SourceAddress; + public ushort SourcePort; + public DateTime TimeStamp; + + public override bool Equals(object obj) + { + var connection = obj as ServerConnection; + if (connection == null) + { + return false; + } + return ((SourceAddress == connection.SourceAddress) && (DestinationAddress == connection.DestinationAddress)); + } + + public override int GetHashCode() + { + return (int) (((SourceAddress ^ DestinationAddress) ^ SourcePort) ^ DestinationPort); + } + + public override string ToString() + { + return (new IPEndPoint(SourceAddress, (ushort) IPAddress.NetworkToHostOrder((short) SourcePort)) + " -> " + new IPEndPoint(DestinationAddress, (ushort) IPAddress.NetworkToHostOrder((short) DestinationPort))); + } + } +} diff --git a/FFXIVAPP.Client/Utilities/IncomingActionEntry.cs b/FFXIVAPP.Client/Network/SocketObject.cs similarity index 68% rename from FFXIVAPP.Client/Utilities/IncomingActionEntry.cs rename to FFXIVAPP.Client/Network/SocketObject.cs index efcffc23..1f08e89b 100644 --- a/FFXIVAPP.Client/Utilities/IncomingActionEntry.cs +++ b/FFXIVAPP.Client/Network/SocketObject.cs @@ -1,5 +1,5 @@ // FFXIVAPP.Client -// IncomingActionEntry.cs +// IFStateObject.cs // // Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved // @@ -27,31 +27,17 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -using FFXIVAPP.Client.Helpers; -using FFXIVAPP.Common.Core.Memory.Enums; +using System.Collections.Generic; +using System.Net.Sockets; -namespace FFXIVAPP.Client.Utilities +namespace FFXIVAPP.Client.Network { - public class IncomingActionEntry + public class SocketObject { - #region Memory Array Items - - public int Code { get; set; } - public int SequenceID { get; set; } - public int SkillID { get; set; } - public uint SourceID { get; set; } - public byte Type { get; set; } - public int Amount { get; set; } - - #endregion - - public string SkillName - { - get { return ConstantsHelper.GetActionNameByID(SkillID); } - } - - public uint TargetID { get; set; } - public string TargetName { get; set; } - public Actor.Type TargetType { get; set; } + public byte[] Buffer = new byte[0x20000]; + public object SocketLock = new object(); + public List Connections = new List(); + public string IPAddress; + public Socket Socket; } } diff --git a/FFXIVAPP.Client/Network/TCPHeader.cs b/FFXIVAPP.Client/Network/TCPHeader.cs new file mode 100644 index 00000000..ea47cd5e --- /dev/null +++ b/FFXIVAPP.Client/Network/TCPHeader.cs @@ -0,0 +1,178 @@ +// FFXIVAPP.Client +// TCPHeader.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; + +namespace FFXIVAPP.Client.Network +{ + public class TCPHeader + { + private readonly uint _acknowledgementNumber = 555; + private readonly short _checksum = 555; + private readonly List _data = new List(); + private readonly ushort _destinationPort; + private readonly ushort _flags = 555; + private readonly byte _headerLength; + private readonly ushort _messageLength; + private readonly uint _sequenceNumber = 555; + private readonly ushort _sourcePort; + private readonly ushort _urgentPointer; + private readonly ushort _window = 555; + + public TCPHeader(byte[] byBuffer, int nReceived) + { + try + { + using (var memoryStream = new MemoryStream(byBuffer, 0, nReceived)) + { + using (var binaryReader = new BinaryReader(memoryStream)) + { + _sourcePort = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _destinationPort = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _sequenceNumber = (uint) IPAddress.NetworkToHostOrder(binaryReader.ReadInt32()); + _acknowledgementNumber = (uint) IPAddress.NetworkToHostOrder(binaryReader.ReadInt32()); + _flags = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _window = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _checksum = (short) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _urgentPointer = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _headerLength = (byte) (_flags >> 12); + _headerLength *= 4; + _messageLength = (ushort) (nReceived - _headerLength); + var tempData = new byte[nReceived - _headerLength]; + Array.Copy(byBuffer, _headerLength, tempData, 0, nReceived - _headerLength); + foreach (var b in tempData) + { + _data.Add(b); + } + } + } + } + catch (Exception ex) + { + } + } + + public string SourcePort + { + get { return _sourcePort.ToString(CultureInfo.InvariantCulture); } + } + + public string DestinationPort + { + get { return _destinationPort.ToString(CultureInfo.InvariantCulture); } + } + + public string SequenceNumber + { + get { return _sequenceNumber.ToString(CultureInfo.InvariantCulture); } + } + + public string AcknowledgementNumber + { + get { return (_flags & 0x10) != 0 ? _acknowledgementNumber.ToString(CultureInfo.InvariantCulture) : ""; } + } + + public string HeaderLength + { + get { return _headerLength.ToString(CultureInfo.InvariantCulture); } + } + + public string WindowSize + { + get { return _window.ToString(CultureInfo.InvariantCulture); } + } + + public string UrgentPointer + { + get { return (_flags & 0x20) != 0 ? _urgentPointer.ToString(CultureInfo.InvariantCulture) : ""; } + } + + public string Flags + { + get + { + var newFlags = _flags & 0x3F; + var stringFlags = String.Format("0x{0:x2} (", newFlags); + if ((newFlags & 0x01) != 0) + { + stringFlags += "FIN, "; + } + if ((newFlags & 0x02) != 0) + { + stringFlags += "SYN, "; + } + if ((newFlags & 0x04) != 0) + { + stringFlags += "RST, "; + } + if ((newFlags & 0x08) != 0) + { + stringFlags += "PSH, "; + } + if ((newFlags & 0x10) != 0) + { + stringFlags += "ACK, "; + } + if ((newFlags & 0x20) != 0) + { + stringFlags += "URG"; + } + stringFlags += ")"; + if (stringFlags.Contains("()")) + { + stringFlags = stringFlags.Remove(stringFlags.Length - 3); + } + else if (stringFlags.Contains(", )")) + { + stringFlags = stringFlags.Remove(stringFlags.Length - 3, 2); + } + return stringFlags; + } + } + + public string Checksum + { + get { return String.Format("0x{0:x2}", _checksum); } + } + + public List Data + { + get { return _data; } + } + + public ushort MessageLength + { + get { return _messageLength; } + } + } +} diff --git a/FFXIVAPP.Client/Network/TCPRow.cs b/FFXIVAPP.Client/Network/TCPRow.cs new file mode 100644 index 00000000..48818d40 --- /dev/null +++ b/FFXIVAPP.Client/Network/TCPRow.cs @@ -0,0 +1,86 @@ +// FFXIVAPP.Client +// TCPRow.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System.Net; +using System.Net.NetworkInformation; + +namespace FFXIVAPP.Client.Network +{ + public class TCPRow + { + #region Private Fields + + private IPEndPoint localEndPoint; + private int processId; + private IPEndPoint remoteEndPoint; + private TcpState state; + + #endregion + + #region Constructors + + public TCPRow(UnsafeNativeMethods.TCPRow row) + { + state = row.State; + processId = row.ProcessID; + var localPort = (row.LocalPort1 << 8) + (row.LocalPort2) + (row.LocalPort3 << 24) + (row.LocalPort4 << 16); + long localAddress = row.LocalAddress; + localEndPoint = new IPEndPoint(localAddress, localPort); + var remotePort = (row.RemotePort1 << 8) + (row.RemotePort2) + (row.RemotePort3 << 24) + (row.RemotePort4 << 16); + long remoteAddress = row.RemoteAddress; + remoteEndPoint = new IPEndPoint(remoteAddress, remotePort); + } + + #endregion + + #region Public Properties + + public IPEndPoint LocalEndPoint + { + get { return localEndPoint; } + } + + public IPEndPoint RemoteEndPoint + { + get { return remoteEndPoint; } + } + + public TcpState State + { + get { return state; } + } + + public int ProcessId + { + get { return processId; } + } + + #endregion + } +} diff --git a/FFXIVAPP.Client/Utilities/FlyingTextEntry.cs b/FFXIVAPP.Client/Network/TCPTable.cs similarity index 66% rename from FFXIVAPP.Client/Utilities/FlyingTextEntry.cs rename to FFXIVAPP.Client/Network/TCPTable.cs index 205efeae..a919f29f 100644 --- a/FFXIVAPP.Client/Utilities/FlyingTextEntry.cs +++ b/FFXIVAPP.Client/Network/TCPTable.cs @@ -1,5 +1,5 @@ // FFXIVAPP.Client -// FlyingTextEntry.cs +// TCPTable.cs // // Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved // @@ -27,35 +27,53 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -using FFXIVAPP.Client.Helpers; -using FFXIVAPP.Common.Core.Memory.Enums; +using System.Collections; +using System.Collections.Generic; -namespace FFXIVAPP.Client.Utilities +namespace FFXIVAPP.Client.Network { - public class FlyingTextEntry + public class TCPTable : IEnumerable { - #region Memory Array Items - - public int Amount { get; set; } - public int ComboAmount { get; set; } - public uint ID { get; set; } - public int SkillID { get; set; } - public int Type1 { get; set; } - public int Type2 { get; set; } - public int UNK1 { get; set; } - public int UNK2 { get; set; } - public int UNK3 { get; set; } - public int UNK4 { get; set; } + #region Private Fields + + private IEnumerable rows; #endregion - public string SkillName + #region Constructors + + public TCPTable(IEnumerable rows) { - get { return ConstantsHelper.GetActionNameByID(SkillID); } + this.rows = rows; } - public uint TargetID { get; set; } - public string TargetName { get; set; } - public Actor.Type TargetType { get; set; } + #endregion + + #region Public Properties + + public IEnumerable Rows + { + get { return rows; } + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return rows.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() + { + return rows.GetEnumerator(); + } + + #endregion } } diff --git a/FFXIVAPP.Client/Network/UDPHeader.cs b/FFXIVAPP.Client/Network/UDPHeader.cs new file mode 100644 index 00000000..e5c5b6f8 --- /dev/null +++ b/FFXIVAPP.Client/Network/UDPHeader.cs @@ -0,0 +1,97 @@ +// FFXIVAPP.Client +// UDPHeader.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; + +namespace FFXIVAPP.Client.Network +{ + public class UDPHeader + { + private readonly short _checksum; + private readonly List _data = new List(); + private readonly ushort _destinationPort; + private readonly ushort _length; + private readonly ushort _sourcePort; + + public UDPHeader(byte[] byBuffer, int nReceived) + { + try + { + using (var memoryStream = new MemoryStream(byBuffer, 0, nReceived)) + { + using (var binaryReader = new BinaryReader(memoryStream)) + { + _sourcePort = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _destinationPort = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _length = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + _checksum = IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); + var tempData = new byte[nReceived - 8]; + Array.Copy(byBuffer, 8, tempData, 0, nReceived - 8); + foreach (var b in tempData) + { + _data.Add(b); + } + } + } + } + catch (Exception ex) + { + } + } + + public string SourcePort + { + get { return _sourcePort.ToString(CultureInfo.InvariantCulture); } + } + + public string DestinationPort + { + get { return _destinationPort.ToString(CultureInfo.InvariantCulture); } + } + + public string Length + { + get { return _length.ToString(CultureInfo.InvariantCulture); } + } + + public string Checksum + { + get { return String.Format("0x{0:x2}", _checksum); } + } + + public List Data + { + get { return _data; } + } + } +} diff --git a/FFXIVAPP.Client/Network/UnsafeNativeMethods.cs b/FFXIVAPP.Client/Network/UnsafeNativeMethods.cs new file mode 100644 index 00000000..441fcdfc --- /dev/null +++ b/FFXIVAPP.Client/Network/UnsafeNativeMethods.cs @@ -0,0 +1,79 @@ +// FFXIVAPP.Client +// UnsafeNativeMethods.cs +// +// Copyright © 2007 - 2015 Ryan Wilson - All Rights Reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of SyndicatedLife nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Net; +using System.Net.NetworkInformation; +using System.Runtime.InteropServices; + +namespace FFXIVAPP.Client.Network +{ + public static class UnsafeNativeMethods + { + [DllImport("iphlpapi.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TCP_TABLE_CLASS tcpTableClass, uint reserved = 0); + + [StructLayout(LayoutKind.Sequential)] + public struct TCPRow + { + public TcpState State; + public uint LocalAddress; + public byte LocalPort1; + public byte LocalPort2; + public byte LocalPort3; + public byte LocalPort4; + public uint RemoteAddress; + public byte RemotePort1; + public byte RemotePort2; + public byte RemotePort3; + public byte RemotePort4; + public int ProcessID; + } + + [StructLayout(LayoutKind.Sequential)] + public struct TCPTable + { + public uint Length; + private TCPRow Row; + } + + public enum TCP_TABLE_CLASS + { + BASIC_LISTENER, + BASIC_CONNECTIONS, + BASIC_ALL, + OWNER_PID_LISTENER, + OWNER_PID_CONNECTIONS, + OWNER_PID_ALL, + OWNER_MODULE_LISTENER, + OWNER_MODULE_CONNECTIONS, + OWNER_MODULE_ALL + } + } +} diff --git a/FFXIVAPP.Client/PluginHost.cs b/FFXIVAPP.Client/PluginHost.cs index ebc3baf3..95bb29e1 100644 --- a/FFXIVAPP.Client/PluginHost.cs +++ b/FFXIVAPP.Client/PluginHost.cs @@ -34,11 +34,13 @@ using System.Reflection; using System.Windows; using System.Xml.Linq; +using FFXIVAPP.Client.Delegates; using FFXIVAPP.Client.Helpers; using FFXIVAPP.Client.Models; using FFXIVAPP.Client.Reflection; using FFXIVAPP.Common.Core.Constant; using FFXIVAPP.Common.Core.Memory; +using FFXIVAPP.Common.Core.Network; using FFXIVAPP.Common.Helpers; using FFXIVAPP.Common.Models; using FFXIVAPP.Common.Utilities; @@ -253,6 +255,8 @@ public void PopupMessage(string pluginName, PopupContent popupContent) public event EventHandler NewInventoryEntries = delegate { }; + public event EventHandler NewNetworkPacket = delegate { }; + public virtual void RaiseNewConstantsEntity(ConstantsEntity e) { var constantsEntityEvent = new ConstantsEntityEvent(this, e); @@ -343,6 +347,16 @@ public virtual void RaiseNewInventoryEntries(List e) } } + public virtual void RaiseNewNetworkPacket(NetworkPacket e) + { + var networkPacketEvent = new NetworkPacketEvent(this, e); + var handler = NewNetworkPacket; + if (handler != null) + { + handler(this, networkPacketEvent); + } + } + #endregion } } diff --git a/distribution/FFXIVAPP.Client.exe b/distribution/FFXIVAPP.Client.exe index 483f97d7..f26ecfc5 100644 Binary files a/distribution/FFXIVAPP.Client.exe and b/distribution/FFXIVAPP.Client.exe differ diff --git a/distribution/FFXIVAPP.Common.dll b/distribution/FFXIVAPP.Common.dll index c064b4aa..6de9fee3 100644 Binary files a/distribution/FFXIVAPP.Common.dll and b/distribution/FFXIVAPP.Common.dll differ diff --git a/distribution/FFXIVAPP.IPluginInterface.dll b/distribution/FFXIVAPP.IPluginInterface.dll index d633ec33..f85df884 100644 Binary files a/distribution/FFXIVAPP.IPluginInterface.dll and b/distribution/FFXIVAPP.IPluginInterface.dll differ diff --git a/distribution/FFXIVAPP.Updater.exe b/distribution/FFXIVAPP.Updater.exe index eba3f97a..cdea62ab 100644 Binary files a/distribution/FFXIVAPP.Updater.exe and b/distribution/FFXIVAPP.Updater.exe differ