├── .gitignore ├── LICENSE ├── Packet Sender.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Packet Sender ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── GCDAsyncSocket.h ├── GCDAsyncSocket.m ├── GCDAsyncUdpSocket.h ├── GCDAsyncUdpSocket.m ├── HRToast+UIView.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── pslogo29.png │ │ ├── pslogo29@2x-1.png │ │ ├── pslogo29@2x.png │ │ ├── pslogo29@3x.png │ │ ├── pslogo40.png │ │ ├── pslogo40@2x-1.png │ │ ├── pslogo40@2x.png │ │ ├── pslogo40@3x.png │ │ ├── pslogo60@2x.png │ │ ├── pslogo60@3x.png │ │ ├── pslogo76.png │ │ └── pslogo76@2x.png ├── Info.plist ├── Packet.swift ├── PacketCell.swift ├── PacketDetailsController.swift ├── PacketNetwork.swift ├── Packet_Sender-Bridging-Header.h ├── Packet_Sender.xcdatamodeld │ ├── .xccurrentversion │ └── Packet_Sender.xcdatamodel │ │ └── contents ├── PacketsViewController.swift ├── SettingsViewController.swift ├── TrafficViewCell.swift ├── TrafficViewController.swift └── assetsraw │ ├── applogo_bw.png │ ├── applogo_notagline.png │ ├── applogo_tagline.png │ ├── ic_action_import_export30.png │ ├── ic_action_import_export30@2x.png │ ├── ic_action_settings30.png │ ├── ic_action_settings30@2x.png │ ├── ic_action_settings48.png │ ├── ic_action_settings96.png │ ├── moveupdown.png │ ├── pslogo29.png │ ├── pslogo29@2x.png │ ├── pslogo29@3x.png │ ├── pslogo30.png │ ├── pslogo30@2x.png │ ├── pslogo30@3x.png │ ├── pslogo40.png │ ├── pslogo40@2x.png │ ├── pslogo40@3x.png │ ├── pslogo60.png │ ├── pslogo60@2x.png │ ├── pslogo60@3x.png │ ├── pslogo76.png │ ├── pslogo76@2x.png │ ├── pslogo76@3x.png │ ├── rx30.png │ ├── rx30@2x.png │ ├── rx75.png │ ├── rx_tcp30.png │ ├── rx_tcp30@2x.png │ ├── rx_tcp75.png │ ├── rx_udp30.png │ ├── rx_udp30@2x.png │ ├── rx_udp75.png │ ├── rx_white30.png │ ├── rx_white30@2x.png │ ├── rx_white75.png │ ├── rx_yellow30.png │ ├── rx_yellow30@2x.png │ ├── rx_yellow75.png │ ├── tx30.png │ ├── tx30@2x.png │ ├── tx75.png │ ├── tx_tcp30.png │ ├── tx_tcp30@2x.png │ ├── tx_tcp75.png │ ├── tx_udp30.png │ ├── tx_udp30@2x.png │ └── tx_udp75.png ├── Packet SenderTests ├── Info.plist └── Packet_SenderTests.swift ├── README.md └── screenshots └── iphone-screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | .DS_Store 21 | 22 | 23 | # CocoaPods 24 | # 25 | # We recommend against adding the Pods directory to your .gitignore. However 26 | # you should judge for yourself, the pros and cons are mentioned at: 27 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 28 | # 29 | # Pods/ 30 | 31 | # Carthage 32 | # 33 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 34 | # Carthage/Checkouts 35 | 36 | Carthage/Build 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dan Nagle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Packet Sender.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5F2283491A7891910063199E /* rx_tcp30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283391A7891910063199E /* rx_tcp30.png */; }; 11 | 5F22834A1A7891910063199E /* rx_tcp30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833A1A7891910063199E /* rx_tcp30@2x.png */; }; 12 | 5F22834B1A7891910063199E /* rx_udp30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833B1A7891910063199E /* rx_udp30.png */; }; 13 | 5F22834C1A7891910063199E /* rx_udp30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833C1A7891910063199E /* rx_udp30@2x.png */; }; 14 | 5F22834D1A7891910063199E /* rx_white30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833D1A7891910063199E /* rx_white30.png */; }; 15 | 5F22834E1A7891910063199E /* rx_white30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833E1A7891910063199E /* rx_white30@2x.png */; }; 16 | 5F22834F1A7891910063199E /* rx_yellow30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22833F1A7891910063199E /* rx_yellow30.png */; }; 17 | 5F2283501A7891910063199E /* rx_yellow30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283401A7891910063199E /* rx_yellow30@2x.png */; }; 18 | 5F2283511A7891910063199E /* rx30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283411A7891910063199E /* rx30.png */; }; 19 | 5F2283521A7891910063199E /* rx30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283421A7891910063199E /* rx30@2x.png */; }; 20 | 5F2283531A7891910063199E /* tx_tcp30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283431A7891910063199E /* tx_tcp30.png */; }; 21 | 5F2283541A7891910063199E /* tx_tcp30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283441A7891910063199E /* tx_tcp30@2x.png */; }; 22 | 5F2283551A7891910063199E /* tx_udp30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283451A7891910063199E /* tx_udp30.png */; }; 23 | 5F2283561A7891910063199E /* tx_udp30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283461A7891910063199E /* tx_udp30@2x.png */; }; 24 | 5F2283571A7891910063199E /* tx30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283471A7891910063199E /* tx30.png */; }; 25 | 5F2283581A7891910063199E /* tx30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283481A7891910063199E /* tx30@2x.png */; }; 26 | 5F22835B1A78920D0063199E /* pslogo30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283591A78920D0063199E /* pslogo30@2x.png */; }; 27 | 5F22835C1A78920D0063199E /* pslogo30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22835A1A78920D0063199E /* pslogo30.png */; }; 28 | 5F22835F1A7895170063199E /* ic_action_settings30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22835D1A7895170063199E /* ic_action_settings30@2x.png */; }; 29 | 5F2283601A7895170063199E /* ic_action_settings30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F22835E1A7895170063199E /* ic_action_settings30.png */; }; 30 | 5F2283631A7896B50063199E /* ic_action_import_export30@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283611A7896B50063199E /* ic_action_import_export30@2x.png */; }; 31 | 5F2283641A7896B50063199E /* ic_action_import_export30.png in Resources */ = {isa = PBXBuildFile; fileRef = 5F2283621A7896B50063199E /* ic_action_import_export30.png */; }; 32 | 5F38BF7F1A52FAB70043ADED /* TrafficViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F38BF7E1A52FAB70043ADED /* TrafficViewCell.swift */; }; 33 | 5F38F0911A336F96005F59ED /* PacketsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F38F0901A336F96005F59ED /* PacketsViewController.swift */; }; 34 | 5F38F0931A336FF7005F59ED /* TrafficViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F38F0921A336FF7005F59ED /* TrafficViewController.swift */; }; 35 | 5F38F0951A33700A005F59ED /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F38F0941A33700A005F59ED /* SettingsViewController.swift */; }; 36 | 5F47B37B1A4E11E000BC35C4 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F47B3781A4E11E000BC35C4 /* GCDAsyncSocket.m */; }; 37 | 5F47B37C1A4E11E000BC35C4 /* GCDAsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F47B37A1A4E11E000BC35C4 /* GCDAsyncUdpSocket.m */; }; 38 | 5F4AFBF01A7F0DD000DF8416 /* HRToast+UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4AFBEF1A7F0DD000DF8416 /* HRToast+UIView.swift */; }; 39 | 5FB545721A4672FA004E34E0 /* PacketNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FB545711A4672FA004E34E0 /* PacketNetwork.swift */; }; 40 | 5FCE8BA91A33677F00D586E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FCE8BA81A33677F00D586E0 /* AppDelegate.swift */; }; 41 | 5FCE8BAC1A33677F00D586E0 /* Packet_Sender.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 5FCE8BAA1A33677F00D586E0 /* Packet_Sender.xcdatamodeld */; }; 42 | 5FCE8BB11A33677F00D586E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5FCE8BAF1A33677F00D586E0 /* Main.storyboard */; }; 43 | 5FCE8BB31A33677F00D586E0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5FCE8BB21A33677F00D586E0 /* Images.xcassets */; }; 44 | 5FCE8BB61A33677F00D586E0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FCE8BB41A33677F00D586E0 /* LaunchScreen.xib */; }; 45 | 5FCE8BC21A33677F00D586E0 /* Packet_SenderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FCE8BC11A33677F00D586E0 /* Packet_SenderTests.swift */; }; 46 | 5FDDB0841A7B10EE00CE465E /* PacketCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FDDB0831A7B10EE00CE465E /* PacketCell.swift */; }; 47 | 5FE253971A7B2DE800A3F890 /* PacketDetailsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FE253961A7B2DE800A3F890 /* PacketDetailsController.swift */; }; 48 | 5FFEF5BF1A33A92B00ECCF3E /* Packet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FFEF5BE1A33A92B00ECCF3E /* Packet.swift */; }; 49 | /* End PBXBuildFile section */ 50 | 51 | /* Begin PBXContainerItemProxy section */ 52 | 5FCE8BBC1A33677F00D586E0 /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = 5FCE8B9B1A33677F00D586E0 /* Project object */; 55 | proxyType = 1; 56 | remoteGlobalIDString = 5FCE8BA21A33677F00D586E0; 57 | remoteInfo = "Packet Sender"; 58 | }; 59 | /* End PBXContainerItemProxy section */ 60 | 61 | /* Begin PBXFileReference section */ 62 | 5F2283391A7891910063199E /* rx_tcp30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = rx_tcp30.png; path = "Packet Sender/assetsraw/rx_tcp30.png"; sourceTree = ""; }; 63 | 5F22833A1A7891910063199E /* rx_tcp30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "rx_tcp30@2x.png"; path = "Packet Sender/assetsraw/rx_tcp30@2x.png"; sourceTree = ""; }; 64 | 5F22833B1A7891910063199E /* rx_udp30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = rx_udp30.png; path = "Packet Sender/assetsraw/rx_udp30.png"; sourceTree = ""; }; 65 | 5F22833C1A7891910063199E /* rx_udp30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "rx_udp30@2x.png"; path = "Packet Sender/assetsraw/rx_udp30@2x.png"; sourceTree = ""; }; 66 | 5F22833D1A7891910063199E /* rx_white30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = rx_white30.png; path = "Packet Sender/assetsraw/rx_white30.png"; sourceTree = ""; }; 67 | 5F22833E1A7891910063199E /* rx_white30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "rx_white30@2x.png"; path = "Packet Sender/assetsraw/rx_white30@2x.png"; sourceTree = ""; }; 68 | 5F22833F1A7891910063199E /* rx_yellow30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = rx_yellow30.png; path = "Packet Sender/assetsraw/rx_yellow30.png"; sourceTree = ""; }; 69 | 5F2283401A7891910063199E /* rx_yellow30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "rx_yellow30@2x.png"; path = "Packet Sender/assetsraw/rx_yellow30@2x.png"; sourceTree = ""; }; 70 | 5F2283411A7891910063199E /* rx30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = rx30.png; path = "Packet Sender/assetsraw/rx30.png"; sourceTree = ""; }; 71 | 5F2283421A7891910063199E /* rx30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "rx30@2x.png"; path = "Packet Sender/assetsraw/rx30@2x.png"; sourceTree = ""; }; 72 | 5F2283431A7891910063199E /* tx_tcp30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tx_tcp30.png; path = "Packet Sender/assetsraw/tx_tcp30.png"; sourceTree = ""; }; 73 | 5F2283441A7891910063199E /* tx_tcp30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "tx_tcp30@2x.png"; path = "Packet Sender/assetsraw/tx_tcp30@2x.png"; sourceTree = ""; }; 74 | 5F2283451A7891910063199E /* tx_udp30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tx_udp30.png; path = "Packet Sender/assetsraw/tx_udp30.png"; sourceTree = ""; }; 75 | 5F2283461A7891910063199E /* tx_udp30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "tx_udp30@2x.png"; path = "Packet Sender/assetsraw/tx_udp30@2x.png"; sourceTree = ""; }; 76 | 5F2283471A7891910063199E /* tx30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tx30.png; path = "Packet Sender/assetsraw/tx30.png"; sourceTree = ""; }; 77 | 5F2283481A7891910063199E /* tx30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "tx30@2x.png"; path = "Packet Sender/assetsraw/tx30@2x.png"; sourceTree = ""; }; 78 | 5F2283591A78920D0063199E /* pslogo30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pslogo30@2x.png"; path = "Packet Sender/assetsraw/pslogo30@2x.png"; sourceTree = ""; }; 79 | 5F22835A1A78920D0063199E /* pslogo30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pslogo30.png; path = "Packet Sender/assetsraw/pslogo30.png"; sourceTree = ""; }; 80 | 5F22835D1A7895170063199E /* ic_action_settings30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ic_action_settings30@2x.png"; path = "Packet Sender/assetsraw/ic_action_settings30@2x.png"; sourceTree = ""; }; 81 | 5F22835E1A7895170063199E /* ic_action_settings30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_action_settings30.png; path = "Packet Sender/assetsraw/ic_action_settings30.png"; sourceTree = ""; }; 82 | 5F2283611A7896B50063199E /* ic_action_import_export30@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ic_action_import_export30@2x.png"; path = "Packet Sender/assetsraw/ic_action_import_export30@2x.png"; sourceTree = ""; }; 83 | 5F2283621A7896B50063199E /* ic_action_import_export30.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_action_import_export30.png; path = "Packet Sender/assetsraw/ic_action_import_export30.png"; sourceTree = ""; }; 84 | 5F38BF7E1A52FAB70043ADED /* TrafficViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrafficViewCell.swift; sourceTree = ""; }; 85 | 5F38F0901A336F96005F59ED /* PacketsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketsViewController.swift; sourceTree = ""; }; 86 | 5F38F0921A336FF7005F59ED /* TrafficViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrafficViewController.swift; sourceTree = ""; }; 87 | 5F38F0941A33700A005F59ED /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; 88 | 5F47B3761A4E0A2800BC35C4 /* Packet_Sender-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Packet_Sender-Bridging-Header.h"; sourceTree = ""; }; 89 | 5F47B3771A4E11E000BC35C4 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; 90 | 5F47B3781A4E11E000BC35C4 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; 91 | 5F47B3791A4E11E000BC35C4 /* GCDAsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncUdpSocket.h; sourceTree = ""; }; 92 | 5F47B37A1A4E11E000BC35C4 /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncUdpSocket.m; sourceTree = ""; }; 93 | 5F4AFBEF1A7F0DD000DF8416 /* HRToast+UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HRToast+UIView.swift"; sourceTree = ""; }; 94 | 5FB545711A4672FA004E34E0 /* PacketNetwork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketNetwork.swift; sourceTree = ""; }; 95 | 5FCE8BA31A33677F00D586E0 /* Packet Sender.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Packet Sender.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 96 | 5FCE8BA71A33677F00D586E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 97 | 5FCE8BA81A33677F00D586E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 98 | 5FCE8BAB1A33677F00D586E0 /* Packet_Sender.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Packet_Sender.xcdatamodel; sourceTree = ""; }; 99 | 5FCE8BB01A33677F00D586E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 100 | 5FCE8BB21A33677F00D586E0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 101 | 5FCE8BB51A33677F00D586E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 102 | 5FCE8BBB1A33677F00D586E0 /* Packet SenderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Packet SenderTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 103 | 5FCE8BC01A33677F00D586E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 104 | 5FCE8BC11A33677F00D586E0 /* Packet_SenderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Packet_SenderTests.swift; sourceTree = ""; }; 105 | 5FDDB0831A7B10EE00CE465E /* PacketCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketCell.swift; sourceTree = ""; }; 106 | 5FE253961A7B2DE800A3F890 /* PacketDetailsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketDetailsController.swift; sourceTree = ""; }; 107 | 5FFEF5BE1A33A92B00ECCF3E /* Packet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Packet.swift; sourceTree = ""; }; 108 | /* End PBXFileReference section */ 109 | 110 | /* Begin PBXFrameworksBuildPhase section */ 111 | 5FCE8BA01A33677F00D586E0 /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | 5FCE8BB81A33677F00D586E0 /* Frameworks */ = { 119 | isa = PBXFrameworksBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXFrameworksBuildPhase section */ 126 | 127 | /* Begin PBXGroup section */ 128 | 5FCE8B9A1A33677F00D586E0 = { 129 | isa = PBXGroup; 130 | children = ( 131 | 5FCE8BA51A33677F00D586E0 /* Packet Sender */, 132 | 5F2283611A7896B50063199E /* ic_action_import_export30@2x.png */, 133 | 5F2283621A7896B50063199E /* ic_action_import_export30.png */, 134 | 5F22835D1A7895170063199E /* ic_action_settings30@2x.png */, 135 | 5F22835E1A7895170063199E /* ic_action_settings30.png */, 136 | 5F2283591A78920D0063199E /* pslogo30@2x.png */, 137 | 5F22835A1A78920D0063199E /* pslogo30.png */, 138 | 5F2283391A7891910063199E /* rx_tcp30.png */, 139 | 5F22833A1A7891910063199E /* rx_tcp30@2x.png */, 140 | 5F22833B1A7891910063199E /* rx_udp30.png */, 141 | 5F22833C1A7891910063199E /* rx_udp30@2x.png */, 142 | 5F22833D1A7891910063199E /* rx_white30.png */, 143 | 5F22833E1A7891910063199E /* rx_white30@2x.png */, 144 | 5F22833F1A7891910063199E /* rx_yellow30.png */, 145 | 5F2283401A7891910063199E /* rx_yellow30@2x.png */, 146 | 5F2283411A7891910063199E /* rx30.png */, 147 | 5F2283421A7891910063199E /* rx30@2x.png */, 148 | 5F2283431A7891910063199E /* tx_tcp30.png */, 149 | 5F2283441A7891910063199E /* tx_tcp30@2x.png */, 150 | 5F2283451A7891910063199E /* tx_udp30.png */, 151 | 5F2283461A7891910063199E /* tx_udp30@2x.png */, 152 | 5F2283471A7891910063199E /* tx30.png */, 153 | 5F2283481A7891910063199E /* tx30@2x.png */, 154 | 5FCE8BBE1A33677F00D586E0 /* Packet SenderTests */, 155 | 5FCE8BA41A33677F00D586E0 /* Products */, 156 | ); 157 | sourceTree = ""; 158 | }; 159 | 5FCE8BA41A33677F00D586E0 /* Products */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 5FCE8BA31A33677F00D586E0 /* Packet Sender.app */, 163 | 5FCE8BBB1A33677F00D586E0 /* Packet SenderTests.xctest */, 164 | ); 165 | name = Products; 166 | sourceTree = ""; 167 | }; 168 | 5FCE8BA51A33677F00D586E0 /* Packet Sender */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 5F4AFBEF1A7F0DD000DF8416 /* HRToast+UIView.swift */, 172 | 5FCE8BAF1A33677F00D586E0 /* Main.storyboard */, 173 | 5F38F0901A336F96005F59ED /* PacketsViewController.swift */, 174 | 5FE253961A7B2DE800A3F890 /* PacketDetailsController.swift */, 175 | 5F38F0921A336FF7005F59ED /* TrafficViewController.swift */, 176 | 5F38F0941A33700A005F59ED /* SettingsViewController.swift */, 177 | 5FFEF5BE1A33A92B00ECCF3E /* Packet.swift */, 178 | 5F38BF7E1A52FAB70043ADED /* TrafficViewCell.swift */, 179 | 5FDDB0831A7B10EE00CE465E /* PacketCell.swift */, 180 | 5FB545711A4672FA004E34E0 /* PacketNetwork.swift */, 181 | 5F47B3771A4E11E000BC35C4 /* GCDAsyncSocket.h */, 182 | 5F47B3781A4E11E000BC35C4 /* GCDAsyncSocket.m */, 183 | 5F47B3791A4E11E000BC35C4 /* GCDAsyncUdpSocket.h */, 184 | 5F47B37A1A4E11E000BC35C4 /* GCDAsyncUdpSocket.m */, 185 | 5FCE8BA81A33677F00D586E0 /* AppDelegate.swift */, 186 | 5FCE8BAA1A33677F00D586E0 /* Packet_Sender.xcdatamodeld */, 187 | 5FCE8BB21A33677F00D586E0 /* Images.xcassets */, 188 | 5FCE8BB41A33677F00D586E0 /* LaunchScreen.xib */, 189 | 5F47B3761A4E0A2800BC35C4 /* Packet_Sender-Bridging-Header.h */, 190 | 5FCE8BA61A33677F00D586E0 /* Supporting Files */, 191 | ); 192 | path = "Packet Sender"; 193 | sourceTree = ""; 194 | }; 195 | 5FCE8BA61A33677F00D586E0 /* Supporting Files */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 5FCE8BA71A33677F00D586E0 /* Info.plist */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | 5FCE8BBE1A33677F00D586E0 /* Packet SenderTests */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | 5FCE8BC11A33677F00D586E0 /* Packet_SenderTests.swift */, 207 | 5FCE8BBF1A33677F00D586E0 /* Supporting Files */, 208 | ); 209 | path = "Packet SenderTests"; 210 | sourceTree = ""; 211 | }; 212 | 5FCE8BBF1A33677F00D586E0 /* Supporting Files */ = { 213 | isa = PBXGroup; 214 | children = ( 215 | 5FCE8BC01A33677F00D586E0 /* Info.plist */, 216 | ); 217 | name = "Supporting Files"; 218 | sourceTree = ""; 219 | }; 220 | /* End PBXGroup section */ 221 | 222 | /* Begin PBXNativeTarget section */ 223 | 5FCE8BA21A33677F00D586E0 /* Packet Sender */ = { 224 | isa = PBXNativeTarget; 225 | buildConfigurationList = 5FCE8BC51A33677F00D586E0 /* Build configuration list for PBXNativeTarget "Packet Sender" */; 226 | buildPhases = ( 227 | 5FCE8B9F1A33677F00D586E0 /* Sources */, 228 | 5FCE8BA01A33677F00D586E0 /* Frameworks */, 229 | 5FCE8BA11A33677F00D586E0 /* Resources */, 230 | ); 231 | buildRules = ( 232 | ); 233 | dependencies = ( 234 | ); 235 | name = "Packet Sender"; 236 | productName = "Packet Sender"; 237 | productReference = 5FCE8BA31A33677F00D586E0 /* Packet Sender.app */; 238 | productType = "com.apple.product-type.application"; 239 | }; 240 | 5FCE8BBA1A33677F00D586E0 /* Packet SenderTests */ = { 241 | isa = PBXNativeTarget; 242 | buildConfigurationList = 5FCE8BC81A33677F00D586E0 /* Build configuration list for PBXNativeTarget "Packet SenderTests" */; 243 | buildPhases = ( 244 | 5FCE8BB71A33677F00D586E0 /* Sources */, 245 | 5FCE8BB81A33677F00D586E0 /* Frameworks */, 246 | 5FCE8BB91A33677F00D586E0 /* Resources */, 247 | ); 248 | buildRules = ( 249 | ); 250 | dependencies = ( 251 | 5FCE8BBD1A33677F00D586E0 /* PBXTargetDependency */, 252 | ); 253 | name = "Packet SenderTests"; 254 | productName = "Packet SenderTests"; 255 | productReference = 5FCE8BBB1A33677F00D586E0 /* Packet SenderTests.xctest */; 256 | productType = "com.apple.product-type.bundle.unit-test"; 257 | }; 258 | /* End PBXNativeTarget section */ 259 | 260 | /* Begin PBXProject section */ 261 | 5FCE8B9B1A33677F00D586E0 /* Project object */ = { 262 | isa = PBXProject; 263 | attributes = { 264 | LastUpgradeCheck = 0610; 265 | ORGANIZATIONNAME = "Dan Nagle"; 266 | TargetAttributes = { 267 | 5FCE8BA21A33677F00D586E0 = { 268 | CreatedOnToolsVersion = 6.1.1; 269 | DevelopmentTeam = Q9Q4KPBMXW; 270 | }; 271 | 5FCE8BBA1A33677F00D586E0 = { 272 | CreatedOnToolsVersion = 6.1.1; 273 | TestTargetID = 5FCE8BA21A33677F00D586E0; 274 | }; 275 | }; 276 | }; 277 | buildConfigurationList = 5FCE8B9E1A33677F00D586E0 /* Build configuration list for PBXProject "Packet Sender" */; 278 | compatibilityVersion = "Xcode 3.2"; 279 | developmentRegion = English; 280 | hasScannedForEncodings = 0; 281 | knownRegions = ( 282 | en, 283 | Base, 284 | ); 285 | mainGroup = 5FCE8B9A1A33677F00D586E0; 286 | productRefGroup = 5FCE8BA41A33677F00D586E0 /* Products */; 287 | projectDirPath = ""; 288 | projectRoot = ""; 289 | targets = ( 290 | 5FCE8BA21A33677F00D586E0 /* Packet Sender */, 291 | 5FCE8BBA1A33677F00D586E0 /* Packet SenderTests */, 292 | ); 293 | }; 294 | /* End PBXProject section */ 295 | 296 | /* Begin PBXResourcesBuildPhase section */ 297 | 5FCE8BA11A33677F00D586E0 /* Resources */ = { 298 | isa = PBXResourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | 5F22834E1A7891910063199E /* rx_white30@2x.png in Resources */, 302 | 5FCE8BB11A33677F00D586E0 /* Main.storyboard in Resources */, 303 | 5F2283571A7891910063199E /* tx30.png in Resources */, 304 | 5F22834C1A7891910063199E /* rx_udp30@2x.png in Resources */, 305 | 5F2283501A7891910063199E /* rx_yellow30@2x.png in Resources */, 306 | 5F22834A1A7891910063199E /* rx_tcp30@2x.png in Resources */, 307 | 5F22834F1A7891910063199E /* rx_yellow30.png in Resources */, 308 | 5F22835B1A78920D0063199E /* pslogo30@2x.png in Resources */, 309 | 5F2283631A7896B50063199E /* ic_action_import_export30@2x.png in Resources */, 310 | 5F2283581A7891910063199E /* tx30@2x.png in Resources */, 311 | 5F2283551A7891910063199E /* tx_udp30.png in Resources */, 312 | 5F2283641A7896B50063199E /* ic_action_import_export30.png in Resources */, 313 | 5F2283521A7891910063199E /* rx30@2x.png in Resources */, 314 | 5FCE8BB61A33677F00D586E0 /* LaunchScreen.xib in Resources */, 315 | 5F22835F1A7895170063199E /* ic_action_settings30@2x.png in Resources */, 316 | 5F22835C1A78920D0063199E /* pslogo30.png in Resources */, 317 | 5F2283561A7891910063199E /* tx_udp30@2x.png in Resources */, 318 | 5F2283491A7891910063199E /* rx_tcp30.png in Resources */, 319 | 5F2283511A7891910063199E /* rx30.png in Resources */, 320 | 5F2283601A7895170063199E /* ic_action_settings30.png in Resources */, 321 | 5F2283531A7891910063199E /* tx_tcp30.png in Resources */, 322 | 5F2283541A7891910063199E /* tx_tcp30@2x.png in Resources */, 323 | 5F22834B1A7891910063199E /* rx_udp30.png in Resources */, 324 | 5F22834D1A7891910063199E /* rx_white30.png in Resources */, 325 | 5FCE8BB31A33677F00D586E0 /* Images.xcassets in Resources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | 5FCE8BB91A33677F00D586E0 /* Resources */ = { 330 | isa = PBXResourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | /* End PBXResourcesBuildPhase section */ 337 | 338 | /* Begin PBXSourcesBuildPhase section */ 339 | 5FCE8B9F1A33677F00D586E0 /* Sources */ = { 340 | isa = PBXSourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | 5FB545721A4672FA004E34E0 /* PacketNetwork.swift in Sources */, 344 | 5F38F0931A336FF7005F59ED /* TrafficViewController.swift in Sources */, 345 | 5FCE8BAC1A33677F00D586E0 /* Packet_Sender.xcdatamodeld in Sources */, 346 | 5FCE8BA91A33677F00D586E0 /* AppDelegate.swift in Sources */, 347 | 5F38BF7F1A52FAB70043ADED /* TrafficViewCell.swift in Sources */, 348 | 5FFEF5BF1A33A92B00ECCF3E /* Packet.swift in Sources */, 349 | 5F4AFBF01A7F0DD000DF8416 /* HRToast+UIView.swift in Sources */, 350 | 5FDDB0841A7B10EE00CE465E /* PacketCell.swift in Sources */, 351 | 5F47B37C1A4E11E000BC35C4 /* GCDAsyncUdpSocket.m in Sources */, 352 | 5F47B37B1A4E11E000BC35C4 /* GCDAsyncSocket.m in Sources */, 353 | 5F38F0951A33700A005F59ED /* SettingsViewController.swift in Sources */, 354 | 5FE253971A7B2DE800A3F890 /* PacketDetailsController.swift in Sources */, 355 | 5F38F0911A336F96005F59ED /* PacketsViewController.swift in Sources */, 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | 5FCE8BB71A33677F00D586E0 /* Sources */ = { 360 | isa = PBXSourcesBuildPhase; 361 | buildActionMask = 2147483647; 362 | files = ( 363 | 5FCE8BC21A33677F00D586E0 /* Packet_SenderTests.swift in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | /* End PBXSourcesBuildPhase section */ 368 | 369 | /* Begin PBXTargetDependency section */ 370 | 5FCE8BBD1A33677F00D586E0 /* PBXTargetDependency */ = { 371 | isa = PBXTargetDependency; 372 | target = 5FCE8BA21A33677F00D586E0 /* Packet Sender */; 373 | targetProxy = 5FCE8BBC1A33677F00D586E0 /* PBXContainerItemProxy */; 374 | }; 375 | /* End PBXTargetDependency section */ 376 | 377 | /* Begin PBXVariantGroup section */ 378 | 5FCE8BAF1A33677F00D586E0 /* Main.storyboard */ = { 379 | isa = PBXVariantGroup; 380 | children = ( 381 | 5FCE8BB01A33677F00D586E0 /* Base */, 382 | ); 383 | name = Main.storyboard; 384 | sourceTree = ""; 385 | }; 386 | 5FCE8BB41A33677F00D586E0 /* LaunchScreen.xib */ = { 387 | isa = PBXVariantGroup; 388 | children = ( 389 | 5FCE8BB51A33677F00D586E0 /* Base */, 390 | ); 391 | name = LaunchScreen.xib; 392 | sourceTree = ""; 393 | }; 394 | /* End PBXVariantGroup section */ 395 | 396 | /* Begin XCBuildConfiguration section */ 397 | 5FCE8BC31A33677F00D586E0 /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | ALWAYS_SEARCH_USER_PATHS = NO; 401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 402 | CLANG_CXX_LIBRARY = "libc++"; 403 | CLANG_ENABLE_MODULES = YES; 404 | CLANG_ENABLE_OBJC_ARC = YES; 405 | CLANG_WARN_BOOL_CONVERSION = YES; 406 | CLANG_WARN_CONSTANT_CONVERSION = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_EMPTY_BODY = YES; 409 | CLANG_WARN_ENUM_CONVERSION = YES; 410 | CLANG_WARN_INT_CONVERSION = YES; 411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 412 | CLANG_WARN_UNREACHABLE_CODE = YES; 413 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 414 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 415 | COPY_PHASE_STRIP = NO; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | GCC_C_LANGUAGE_STANDARD = gnu99; 418 | GCC_DYNAMIC_NO_PIC = NO; 419 | GCC_OPTIMIZATION_LEVEL = 0; 420 | GCC_PREPROCESSOR_DEFINITIONS = ( 421 | "DEBUG=1", 422 | "$(inherited)", 423 | ); 424 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 425 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 426 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 427 | GCC_WARN_UNDECLARED_SELECTOR = YES; 428 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 429 | GCC_WARN_UNUSED_FUNCTION = YES; 430 | GCC_WARN_UNUSED_VARIABLE = YES; 431 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 432 | MTL_ENABLE_DEBUG_INFO = YES; 433 | ONLY_ACTIVE_ARCH = YES; 434 | SDKROOT = iphoneos; 435 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 436 | TARGETED_DEVICE_FAMILY = "1,2"; 437 | }; 438 | name = Debug; 439 | }; 440 | 5FCE8BC41A33677F00D586E0 /* Release */ = { 441 | isa = XCBuildConfiguration; 442 | buildSettings = { 443 | ALWAYS_SEARCH_USER_PATHS = NO; 444 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 445 | CLANG_CXX_LIBRARY = "libc++"; 446 | CLANG_ENABLE_MODULES = YES; 447 | CLANG_ENABLE_OBJC_ARC = YES; 448 | CLANG_WARN_BOOL_CONVERSION = YES; 449 | CLANG_WARN_CONSTANT_CONVERSION = YES; 450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 451 | CLANG_WARN_EMPTY_BODY = YES; 452 | CLANG_WARN_ENUM_CONVERSION = YES; 453 | CLANG_WARN_INT_CONVERSION = YES; 454 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 455 | CLANG_WARN_UNREACHABLE_CODE = YES; 456 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 457 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 458 | COPY_PHASE_STRIP = YES; 459 | ENABLE_NS_ASSERTIONS = NO; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | GCC_C_LANGUAGE_STANDARD = gnu99; 462 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 463 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 464 | GCC_WARN_UNDECLARED_SELECTOR = YES; 465 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 466 | GCC_WARN_UNUSED_FUNCTION = YES; 467 | GCC_WARN_UNUSED_VARIABLE = YES; 468 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 469 | MTL_ENABLE_DEBUG_INFO = NO; 470 | SDKROOT = iphoneos; 471 | TARGETED_DEVICE_FAMILY = "1,2"; 472 | VALIDATE_PRODUCT = YES; 473 | }; 474 | name = Release; 475 | }; 476 | 5FCE8BC61A33677F00D586E0 /* Debug */ = { 477 | isa = XCBuildConfiguration; 478 | buildSettings = { 479 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 480 | CODE_SIGN_IDENTITY = "iPhone Developer"; 481 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 482 | INFOPLIST_FILE = "Packet Sender/Info.plist"; 483 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | PROVISIONING_PROFILE = ""; 487 | SWIFT_OBJC_BRIDGING_HEADER = "Packet Sender/Packet_Sender-Bridging-Header.h"; 488 | }; 489 | name = Debug; 490 | }; 491 | 5FCE8BC71A33677F00D586E0 /* Release */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | CODE_SIGN_IDENTITY = "iPhone Developer"; 496 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 497 | INFOPLIST_FILE = "Packet Sender/Info.plist"; 498 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | PROVISIONING_PROFILE = ""; 502 | SWIFT_OBJC_BRIDGING_HEADER = "Packet Sender/Packet_Sender-Bridging-Header.h"; 503 | }; 504 | name = Release; 505 | }; 506 | 5FCE8BC91A33677F00D586E0 /* Debug */ = { 507 | isa = XCBuildConfiguration; 508 | buildSettings = { 509 | BUNDLE_LOADER = "$(TEST_HOST)"; 510 | FRAMEWORK_SEARCH_PATHS = ( 511 | "$(SDKROOT)/Developer/Library/Frameworks", 512 | "$(inherited)", 513 | ); 514 | GCC_PREPROCESSOR_DEFINITIONS = ( 515 | "DEBUG=1", 516 | "$(inherited)", 517 | ); 518 | INFOPLIST_FILE = "Packet SenderTests/Info.plist"; 519 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Packet Sender.app/Packet Sender"; 522 | }; 523 | name = Debug; 524 | }; 525 | 5FCE8BCA1A33677F00D586E0 /* Release */ = { 526 | isa = XCBuildConfiguration; 527 | buildSettings = { 528 | BUNDLE_LOADER = "$(TEST_HOST)"; 529 | FRAMEWORK_SEARCH_PATHS = ( 530 | "$(SDKROOT)/Developer/Library/Frameworks", 531 | "$(inherited)", 532 | ); 533 | INFOPLIST_FILE = "Packet SenderTests/Info.plist"; 534 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 535 | PRODUCT_NAME = "$(TARGET_NAME)"; 536 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Packet Sender.app/Packet Sender"; 537 | }; 538 | name = Release; 539 | }; 540 | /* End XCBuildConfiguration section */ 541 | 542 | /* Begin XCConfigurationList section */ 543 | 5FCE8B9E1A33677F00D586E0 /* Build configuration list for PBXProject "Packet Sender" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | 5FCE8BC31A33677F00D586E0 /* Debug */, 547 | 5FCE8BC41A33677F00D586E0 /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | 5FCE8BC51A33677F00D586E0 /* Build configuration list for PBXNativeTarget "Packet Sender" */ = { 553 | isa = XCConfigurationList; 554 | buildConfigurations = ( 555 | 5FCE8BC61A33677F00D586E0 /* Debug */, 556 | 5FCE8BC71A33677F00D586E0 /* Release */, 557 | ); 558 | defaultConfigurationIsVisible = 0; 559 | defaultConfigurationName = Release; 560 | }; 561 | 5FCE8BC81A33677F00D586E0 /* Build configuration list for PBXNativeTarget "Packet SenderTests" */ = { 562 | isa = XCConfigurationList; 563 | buildConfigurations = ( 564 | 5FCE8BC91A33677F00D586E0 /* Debug */, 565 | 5FCE8BCA1A33677F00D586E0 /* Release */, 566 | ); 567 | defaultConfigurationIsVisible = 0; 568 | defaultConfigurationName = Release; 569 | }; 570 | /* End XCConfigurationList section */ 571 | 572 | /* Begin XCVersionGroup section */ 573 | 5FCE8BAA1A33677F00D586E0 /* Packet_Sender.xcdatamodeld */ = { 574 | isa = XCVersionGroup; 575 | children = ( 576 | 5FCE8BAB1A33677F00D586E0 /* Packet_Sender.xcdatamodel */, 577 | ); 578 | currentVersion = 5FCE8BAB1A33677F00D586E0 /* Packet_Sender.xcdatamodel */; 579 | path = Packet_Sender.xcdatamodeld; 580 | sourceTree = ""; 581 | versionGroupType = wrapper.xcdatamodel; 582 | }; 583 | /* End XCVersionGroup section */ 584 | }; 585 | rootObject = 5FCE8B9B1A33677F00D586E0 /* Project object */; 586 | } 587 | -------------------------------------------------------------------------------- /Packet Sender.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Packet Sender/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 19 | // Override point for customization after application launch. 20 | return true 21 | } 22 | 23 | func applicationWillResignActive(application: UIApplication) { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | 27 | } 28 | 29 | func applicationDidEnterBackground(application: UIApplication) { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | func applicationWillEnterForeground(application: UIApplication) { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | func applicationDidBecomeActive(application: UIApplication) { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | func applicationWillTerminate(application: UIApplication) { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | // Saves changes in the application's managed object context before the application terminates. 45 | self.saveContext() 46 | } 47 | 48 | // MARK: - Core Data stack 49 | 50 | lazy var applicationDocumentsDirectory: NSURL = { 51 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.packetsender.Packet_Sender" in the application's documents Application Support directory. 52 | let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) 53 | return urls[urls.count-1] as! NSURL 54 | }() 55 | 56 | lazy var managedObjectModel: NSManagedObjectModel = { 57 | // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. 58 | let modelURL = NSBundle.mainBundle().URLForResource("Packet_Sender", withExtension: "momd")! 59 | return NSManagedObjectModel(contentsOfURL: modelURL)! 60 | }() 61 | 62 | lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { 63 | // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 64 | // Create the coordinator and store 65 | var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 66 | let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("Packet_Sender.sqlite") 67 | var error: NSError? = nil 68 | var failureReason = "There was an error creating or loading the application's saved data." 69 | if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil { 70 | coordinator = nil 71 | // Report any error we got. 72 | let dict = NSMutableDictionary() 73 | dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 74 | dict[NSLocalizedFailureReasonErrorKey] = failureReason 75 | dict[NSUnderlyingErrorKey] = error 76 | error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject]) 77 | // Replace this with code to handle the error appropriately. 78 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 79 | NSLog("Unresolved error \(error), \(error!.userInfo)") 80 | abort() 81 | } 82 | 83 | return coordinator 84 | }() 85 | 86 | lazy var managedObjectContext: NSManagedObjectContext? = { 87 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. 88 | let coordinator = self.persistentStoreCoordinator 89 | if coordinator == nil { 90 | return nil 91 | } 92 | var managedObjectContext = NSManagedObjectContext() 93 | managedObjectContext.persistentStoreCoordinator = coordinator 94 | return managedObjectContext 95 | }() 96 | 97 | // MARK: - Core Data Saving support 98 | 99 | func saveContext () { 100 | if let moc = self.managedObjectContext { 101 | var error: NSError? = nil 102 | if moc.hasChanges && !moc.save(&error) { 103 | // Replace this implementation with code to handle the error appropriately. 104 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 105 | NSLog("Unresolved error \(error), \(error!.userInfo)") 106 | abort() 107 | } 108 | } 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /Packet Sender/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Packet Sender/GCDAsyncUdpSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDAsyncUdpSocket 3 | // 4 | // This class is in the public domain. 5 | // Originally created by Robbie Hanson of Deusty LLC. 6 | // Updated and maintained by Deusty LLC and the Apple development community. 7 | // 8 | // https://github.com/robbiehanson/CocoaAsyncSocket 9 | // 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | extern NSString *const GCDAsyncUdpSocketException; 17 | extern NSString *const GCDAsyncUdpSocketErrorDomain; 18 | 19 | extern NSString *const GCDAsyncUdpSocketQueueName; 20 | extern NSString *const GCDAsyncUdpSocketThreadName; 21 | 22 | enum GCDAsyncUdpSocketError 23 | { 24 | GCDAsyncUdpSocketNoError = 0, // Never used 25 | GCDAsyncUdpSocketBadConfigError, // Invalid configuration 26 | GCDAsyncUdpSocketBadParamError, // Invalid parameter was passed 27 | GCDAsyncUdpSocketSendTimeoutError, // A send operation timed out 28 | GCDAsyncUdpSocketClosedError, // The socket was closed 29 | GCDAsyncUdpSocketOtherError, // Description provided in userInfo 30 | }; 31 | typedef enum GCDAsyncUdpSocketError GCDAsyncUdpSocketError; 32 | 33 | /** 34 | * You may optionally set a receive filter for the socket. 35 | * A filter can provide several useful features: 36 | * 37 | * 1. Many times udp packets need to be parsed. 38 | * Since the filter can run in its own independent queue, you can parallelize this parsing quite easily. 39 | * The end result is a parallel socket io, datagram parsing, and packet processing. 40 | * 41 | * 2. Many times udp packets are discarded because they are duplicate/unneeded/unsolicited. 42 | * The filter can prevent such packets from arriving at the delegate. 43 | * And because the filter can run in its own independent queue, this doesn't slow down the delegate. 44 | * 45 | * - Since the udp protocol does not guarantee delivery, udp packets may be lost. 46 | * Many protocols built atop udp thus provide various resend/re-request algorithms. 47 | * This sometimes results in duplicate packets arriving. 48 | * A filter may allow you to architect the duplicate detection code to run in parallel to normal processing. 49 | * 50 | * - Since the udp socket may be connectionless, its possible for unsolicited packets to arrive. 51 | * Such packets need to be ignored. 52 | * 53 | * 3. Sometimes traffic shapers are needed to simulate real world environments. 54 | * A filter allows you to write custom code to simulate such environments. 55 | * The ability to code this yourself is especially helpful when your simulated environment 56 | * is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router), 57 | * or the system tools to handle this aren't available (e.g. on a mobile device). 58 | * 59 | * @param data - The packet that was received. 60 | * @param address - The address the data was received from. 61 | * See utilities section for methods to extract info from address. 62 | * @param context - Out parameter you may optionally set, which will then be passed to the delegate method. 63 | * For example, filter block can parse the data and then, 64 | * pass the parsed data to the delegate. 65 | * 66 | * @returns - YES if the received packet should be passed onto the delegate. 67 | * NO if the received packet should be discarded, and not reported to the delegete. 68 | * 69 | * Example: 70 | * 71 | * GCDAsyncUdpSocketReceiveFilterBlock filter = ^BOOL (NSData *data, NSData *address, id *context) { 72 | * 73 | * MyProtocolMessage *msg = [MyProtocol parseMessage:data]; 74 | * 75 | * *context = response; 76 | * return (response != nil); 77 | * }; 78 | * [udpSocket setReceiveFilter:filter withQueue:myParsingQueue]; 79 | * 80 | **/ 81 | typedef BOOL (^GCDAsyncUdpSocketReceiveFilterBlock)(NSData *data, NSData *address, id *context); 82 | 83 | /** 84 | * You may optionally set a send filter for the socket. 85 | * A filter can provide several interesting possibilities: 86 | * 87 | * 1. Optional caching of resolved addresses for domain names. 88 | * The cache could later be consulted, resulting in fewer system calls to getaddrinfo. 89 | * 90 | * 2. Reusable modules of code for bandwidth monitoring. 91 | * 92 | * 3. Sometimes traffic shapers are needed to simulate real world environments. 93 | * A filter allows you to write custom code to simulate such environments. 94 | * The ability to code this yourself is especially helpful when your simulated environment 95 | * is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router), 96 | * or the system tools to handle this aren't available (e.g. on a mobile device). 97 | * 98 | * @param data - The packet that was received. 99 | * @param address - The address the data was received from. 100 | * See utilities section for methods to extract info from address. 101 | * @param tag - The tag that was passed in the send method. 102 | * 103 | * @returns - YES if the packet should actually be sent over the socket. 104 | * NO if the packet should be silently dropped (not sent over the socket). 105 | * 106 | * Regardless of the return value, the delegate will be informed that the packet was successfully sent. 107 | * 108 | **/ 109 | typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address, long tag); 110 | 111 | 112 | @interface GCDAsyncUdpSocket : NSObject 113 | 114 | /** 115 | * GCDAsyncUdpSocket uses the standard delegate paradigm, 116 | * but executes all delegate callbacks on a given delegate dispatch queue. 117 | * This allows for maximum concurrency, while at the same time providing easy thread safety. 118 | * 119 | * You MUST set a delegate AND delegate dispatch queue before attempting to 120 | * use the socket, or you will get an error. 121 | * 122 | * The socket queue is optional. 123 | * If you pass NULL, GCDAsyncSocket will automatically create its own socket queue. 124 | * If you choose to provide a socket queue, the socket queue must not be a concurrent queue, 125 | * then please see the discussion for the method markSocketQueueTargetQueue. 126 | * 127 | * The delegate queue and socket queue can optionally be the same. 128 | **/ 129 | - (id)init; 130 | - (id)initWithSocketQueue:(dispatch_queue_t)sq; 131 | - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq; 132 | - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq; 133 | 134 | #pragma mark Configuration 135 | 136 | - (id)delegate; 137 | - (void)setDelegate:(id)delegate; 138 | - (void)synchronouslySetDelegate:(id)delegate; 139 | 140 | - (dispatch_queue_t)delegateQueue; 141 | - (void)setDelegateQueue:(dispatch_queue_t)delegateQueue; 142 | - (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue; 143 | 144 | - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr; 145 | - (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 146 | - (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 147 | 148 | /** 149 | * By default, both IPv4 and IPv6 are enabled. 150 | * 151 | * This means GCDAsyncUdpSocket automatically supports both protocols, 152 | * and can send to IPv4 or IPv6 addresses, 153 | * as well as receive over IPv4 and IPv6. 154 | * 155 | * For operations that require DNS resolution, GCDAsyncUdpSocket supports both IPv4 and IPv6. 156 | * If a DNS lookup returns only IPv4 results, GCDAsyncUdpSocket will automatically use IPv4. 157 | * If a DNS lookup returns only IPv6 results, GCDAsyncUdpSocket will automatically use IPv6. 158 | * If a DNS lookup returns both IPv4 and IPv6 results, then the protocol used depends on the configured preference. 159 | * If IPv4 is preferred, then IPv4 is used. 160 | * If IPv6 is preferred, then IPv6 is used. 161 | * If neutral, then the first IP version in the resolved array will be used. 162 | * 163 | * Starting with Mac OS X 10.7 Lion and iOS 5, the default IP preference is neutral. 164 | * On prior systems the default IP preference is IPv4. 165 | **/ 166 | - (BOOL)isIPv4Enabled; 167 | - (void)setIPv4Enabled:(BOOL)flag; 168 | 169 | - (BOOL)isIPv6Enabled; 170 | - (void)setIPv6Enabled:(BOOL)flag; 171 | 172 | - (BOOL)isIPv4Preferred; 173 | - (BOOL)isIPv6Preferred; 174 | - (BOOL)isIPVersionNeutral; 175 | 176 | - (void)setPreferIPv4; 177 | - (void)setPreferIPv6; 178 | - (void)setIPVersionNeutral; 179 | 180 | /** 181 | * Gets/Sets the maximum size of the buffer that will be allocated for receive operations. 182 | * The default maximum size is 9216 bytes. 183 | * 184 | * The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535. 185 | * The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295. 186 | * 187 | * Since the OS/GCD notifies us of the size of each received UDP packet, 188 | * the actual allocated buffer size for each packet is exact. 189 | * And in practice the size of UDP packets is generally much smaller than the max. 190 | * Indeed most protocols will send and receive packets of only a few bytes, 191 | * or will set a limit on the size of packets to prevent fragmentation in the IP layer. 192 | * 193 | * If you set the buffer size too small, the sockets API in the OS will silently discard 194 | * any extra data, and you will not be notified of the error. 195 | **/ 196 | - (uint16_t)maxReceiveIPv4BufferSize; 197 | - (void)setMaxReceiveIPv4BufferSize:(uint16_t)max; 198 | 199 | - (uint32_t)maxReceiveIPv6BufferSize; 200 | - (void)setMaxReceiveIPv6BufferSize:(uint32_t)max; 201 | 202 | /** 203 | * User data allows you to associate arbitrary information with the socket. 204 | * This data is not used internally in any way. 205 | **/ 206 | - (id)userData; 207 | - (void)setUserData:(id)arbitraryUserData; 208 | 209 | #pragma mark Diagnostics 210 | 211 | /** 212 | * Returns the local address info for the socket. 213 | * 214 | * The localAddress method returns a sockaddr structure wrapped in a NSData object. 215 | * The localHost method returns the human readable IP address as a string. 216 | * 217 | * Note: Address info may not be available until after the socket has been binded, connected 218 | * or until after data has been sent. 219 | **/ 220 | - (NSData *)localAddress; 221 | - (NSString *)localHost; 222 | - (uint16_t)localPort; 223 | 224 | - (NSData *)localAddress_IPv4; 225 | - (NSString *)localHost_IPv4; 226 | - (uint16_t)localPort_IPv4; 227 | 228 | - (NSData *)localAddress_IPv6; 229 | - (NSString *)localHost_IPv6; 230 | - (uint16_t)localPort_IPv6; 231 | 232 | /** 233 | * Returns the remote address info for the socket. 234 | * 235 | * The connectedAddress method returns a sockaddr structure wrapped in a NSData object. 236 | * The connectedHost method returns the human readable IP address as a string. 237 | * 238 | * Note: Since UDP is connectionless by design, connected address info 239 | * will not be available unless the socket is explicitly connected to a remote host/port. 240 | * If the socket is not connected, these methods will return nil / 0. 241 | **/ 242 | - (NSData *)connectedAddress; 243 | - (NSString *)connectedHost; 244 | - (uint16_t)connectedPort; 245 | 246 | /** 247 | * Returns whether or not this socket has been connected to a single host. 248 | * By design, UDP is a connectionless protocol, and connecting is not needed. 249 | * If connected, the socket will only be able to send/receive data to/from the connected host. 250 | **/ 251 | - (BOOL)isConnected; 252 | 253 | /** 254 | * Returns whether or not this socket has been closed. 255 | * The only way a socket can be closed is if you explicitly call one of the close methods. 256 | **/ 257 | - (BOOL)isClosed; 258 | 259 | /** 260 | * Returns whether or not this socket is IPv4. 261 | * 262 | * By default this will be true, unless: 263 | * - IPv4 is disabled (via setIPv4Enabled:) 264 | * - The socket is explicitly bound to an IPv6 address 265 | * - The socket is connected to an IPv6 address 266 | **/ 267 | - (BOOL)isIPv4; 268 | 269 | /** 270 | * Returns whether or not this socket is IPv6. 271 | * 272 | * By default this will be true, unless: 273 | * - IPv6 is disabled (via setIPv6Enabled:) 274 | * - The socket is explicitly bound to an IPv4 address 275 | * _ The socket is connected to an IPv4 address 276 | * 277 | * This method will also return false on platforms that do not support IPv6. 278 | * Note: The iPhone does not currently support IPv6. 279 | **/ 280 | - (BOOL)isIPv6; 281 | 282 | #pragma mark Binding 283 | 284 | /** 285 | * Binds the UDP socket to the given port. 286 | * Binding should be done for server sockets that receive data prior to sending it. 287 | * Client sockets can skip binding, 288 | * as the OS will automatically assign the socket an available port when it starts sending data. 289 | * 290 | * You may optionally pass a port number of zero to immediately bind the socket, 291 | * yet still allow the OS to automatically assign an available port. 292 | * 293 | * You cannot bind a socket after its been connected. 294 | * You can only bind a socket once. 295 | * You can still connect a socket (if desired) after binding. 296 | * 297 | * On success, returns YES. 298 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr. 299 | **/ 300 | - (BOOL)bindToPort:(uint16_t)port error:(NSError **)errPtr; 301 | 302 | /** 303 | * Binds the UDP socket to the given port and optional interface. 304 | * Binding should be done for server sockets that receive data prior to sending it. 305 | * Client sockets can skip binding, 306 | * as the OS will automatically assign the socket an available port when it starts sending data. 307 | * 308 | * You may optionally pass a port number of zero to immediately bind the socket, 309 | * yet still allow the OS to automatically assign an available port. 310 | * 311 | * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). 312 | * You may also use the special strings "localhost" or "loopback" to specify that 313 | * the socket only accept packets from the local machine. 314 | * 315 | * You cannot bind a socket after its been connected. 316 | * You can only bind a socket once. 317 | * You can still connect a socket (if desired) after binding. 318 | * 319 | * On success, returns YES. 320 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr. 321 | **/ 322 | - (BOOL)bindToPort:(uint16_t)port interface:(NSString *)interface error:(NSError **)errPtr; 323 | 324 | /** 325 | * Binds the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object. 326 | * 327 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 328 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 329 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 330 | * 331 | * Binding should be done for server sockets that receive data prior to sending it. 332 | * Client sockets can skip binding, 333 | * as the OS will automatically assign the socket an available port when it starts sending data. 334 | * 335 | * You cannot bind a socket after its been connected. 336 | * You can only bind a socket once. 337 | * You can still connect a socket (if desired) after binding. 338 | * 339 | * On success, returns YES. 340 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr. 341 | **/ 342 | - (BOOL)bindToAddress:(NSData *)localAddr error:(NSError **)errPtr; 343 | 344 | #pragma mark Connecting 345 | 346 | /** 347 | * Connects the UDP socket to the given host and port. 348 | * By design, UDP is a connectionless protocol, and connecting is not needed. 349 | * 350 | * Choosing to connect to a specific host/port has the following effect: 351 | * - You will only be able to send data to the connected host/port. 352 | * - You will only be able to receive data from the connected host/port. 353 | * - You will receive ICMP messages that come from the connected host/port, such as "connection refused". 354 | * 355 | * The actual process of connecting a UDP socket does not result in any communication on the socket. 356 | * It simply changes the internal state of the socket. 357 | * 358 | * You cannot bind a socket after it has been connected. 359 | * You can only connect a socket once. 360 | * 361 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2"). 362 | * 363 | * This method is asynchronous as it requires a DNS lookup to resolve the given host name. 364 | * If an obvious error is detected, this method immediately returns NO and sets errPtr. 365 | * If you don't care about the error, you can pass nil for errPtr. 366 | * Otherwise, this method returns YES and begins the asynchronous connection process. 367 | * The result of the asynchronous connection process will be reported via the delegate methods. 368 | **/ 369 | - (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr; 370 | 371 | /** 372 | * Connects the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object. 373 | * 374 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 375 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 376 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 377 | * 378 | * By design, UDP is a connectionless protocol, and connecting is not needed. 379 | * 380 | * Choosing to connect to a specific address has the following effect: 381 | * - You will only be able to send data to the connected address. 382 | * - You will only be able to receive data from the connected address. 383 | * - You will receive ICMP messages that come from the connected address, such as "connection refused". 384 | * 385 | * Connecting a UDP socket does not result in any communication on the socket. 386 | * It simply changes the internal state of the socket. 387 | * 388 | * You cannot bind a socket after its been connected. 389 | * You can only connect a socket once. 390 | * 391 | * On success, returns YES. 392 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 393 | * 394 | * Note: Unlike the connectToHost:onPort:error: method, this method does not require a DNS lookup. 395 | * Thus when this method returns, the connection has either failed or fully completed. 396 | * In other words, this method is synchronous, unlike the asynchronous connectToHost::: method. 397 | * However, for compatibility and simplification of delegate code, if this method returns YES 398 | * then the corresponding delegate method (udpSocket:didConnectToHost:port:) is still invoked. 399 | **/ 400 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 401 | 402 | #pragma mark Multicast 403 | 404 | /** 405 | * Join multicast group. 406 | * Group should be an IP address (eg @"225.228.0.1"). 407 | * 408 | * On success, returns YES. 409 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 410 | **/ 411 | - (BOOL)joinMulticastGroup:(NSString *)group error:(NSError **)errPtr; 412 | 413 | /** 414 | * Join multicast group. 415 | * Group should be an IP address (eg @"225.228.0.1"). 416 | * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). 417 | * 418 | * On success, returns YES. 419 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 420 | **/ 421 | - (BOOL)joinMulticastGroup:(NSString *)group onInterface:(NSString *)interface error:(NSError **)errPtr; 422 | 423 | - (BOOL)leaveMulticastGroup:(NSString *)group error:(NSError **)errPtr; 424 | - (BOOL)leaveMulticastGroup:(NSString *)group onInterface:(NSString *)interface error:(NSError **)errPtr; 425 | 426 | #pragma mark Broadcast 427 | 428 | /** 429 | * By default, the underlying socket in the OS will not allow you to send broadcast messages. 430 | * In order to send broadcast messages, you need to enable this functionality in the socket. 431 | * 432 | * A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is 433 | * delivered to every host on the network. 434 | * The reason this is generally disabled by default (by the OS) is to prevent 435 | * accidental broadcast messages from flooding the network. 436 | **/ 437 | - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr; 438 | 439 | #pragma mark Sending 440 | 441 | /** 442 | * Asynchronously sends the given data, with the given timeout and tag. 443 | * 444 | * This method may only be used with a connected socket. 445 | * Recall that connecting is optional for a UDP socket. 446 | * For connected sockets, data can only be sent to the connected address. 447 | * For non-connected sockets, the remote destination is specified for each packet. 448 | * For more information about optionally connecting udp sockets, see the documentation for the connect methods above. 449 | * 450 | * @param data 451 | * The data to send. 452 | * If data is nil or zero-length, this method does nothing. 453 | * If passing NSMutableData, please read the thread-safety notice below. 454 | * 455 | * @param timeout 456 | * The timeout for the send opeartion. 457 | * If the timeout value is negative, the send operation will not use a timeout. 458 | * 459 | * @param tag 460 | * The tag is for your convenience. 461 | * It is not sent or received over the socket in any manner what-so-ever. 462 | * It is reported back as a parameter in the udpSocket:didSendDataWithTag: 463 | * or udpSocket:didNotSendDataWithTag:dueToError: methods. 464 | * You can use it as an array index, state id, type constant, etc. 465 | * 466 | * 467 | * Thread-Safety Note: 468 | * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while 469 | * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method 470 | * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying 471 | * that this particular send operation has completed. 472 | * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data. 473 | * It simply retains it for performance reasons. 474 | * Often times, if NSMutableData is passed, it is because a request/response was built up in memory. 475 | * Copying this data adds an unwanted/unneeded overhead. 476 | * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket 477 | * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time 478 | * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method. 479 | **/ 480 | - (void)sendData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 481 | 482 | /** 483 | * Asynchronously sends the given data, with the given timeout and tag, to the given host and port. 484 | * 485 | * This method cannot be used with a connected socket. 486 | * Recall that connecting is optional for a UDP socket. 487 | * For connected sockets, data can only be sent to the connected address. 488 | * For non-connected sockets, the remote destination is specified for each packet. 489 | * For more information about optionally connecting udp sockets, see the documentation for the connect methods above. 490 | * 491 | * @param data 492 | * The data to send. 493 | * If data is nil or zero-length, this method does nothing. 494 | * If passing NSMutableData, please read the thread-safety notice below. 495 | * 496 | * @param host 497 | * The destination to send the udp packet to. 498 | * May be specified as a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2"). 499 | * You may also use the convenience strings of "loopback" or "localhost". 500 | * 501 | * @param port 502 | * The port of the host to send to. 503 | * 504 | * @param timeout 505 | * The timeout for the send opeartion. 506 | * If the timeout value is negative, the send operation will not use a timeout. 507 | * 508 | * @param tag 509 | * The tag is for your convenience. 510 | * It is not sent or received over the socket in any manner what-so-ever. 511 | * It is reported back as a parameter in the udpSocket:didSendDataWithTag: 512 | * or udpSocket:didNotSendDataWithTag:dueToError: methods. 513 | * You can use it as an array index, state id, type constant, etc. 514 | * 515 | * 516 | * Thread-Safety Note: 517 | * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while 518 | * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method 519 | * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying 520 | * that this particular send operation has completed. 521 | * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data. 522 | * It simply retains it for performance reasons. 523 | * Often times, if NSMutableData is passed, it is because a request/response was built up in memory. 524 | * Copying this data adds an unwanted/unneeded overhead. 525 | * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket 526 | * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time 527 | * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method. 528 | **/ 529 | - (void)sendData:(NSData *)data 530 | toHost:(NSString *)host 531 | port:(uint16_t)port 532 | withTimeout:(NSTimeInterval)timeout 533 | tag:(long)tag; 534 | 535 | /** 536 | * Asynchronously sends the given data, with the given timeout and tag, to the given address. 537 | * 538 | * This method cannot be used with a connected socket. 539 | * Recall that connecting is optional for a UDP socket. 540 | * For connected sockets, data can only be sent to the connected address. 541 | * For non-connected sockets, the remote destination is specified for each packet. 542 | * For more information about optionally connecting udp sockets, see the documentation for the connect methods above. 543 | * 544 | * @param data 545 | * The data to send. 546 | * If data is nil or zero-length, this method does nothing. 547 | * If passing NSMutableData, please read the thread-safety notice below. 548 | * 549 | * @param remoteAddr 550 | * The address to send the data to (specified as a sockaddr structure wrapped in a NSData object). 551 | * 552 | * @param timeout 553 | * The timeout for the send opeartion. 554 | * If the timeout value is negative, the send operation will not use a timeout. 555 | * 556 | * @param tag 557 | * The tag is for your convenience. 558 | * It is not sent or received over the socket in any manner what-so-ever. 559 | * It is reported back as a parameter in the udpSocket:didSendDataWithTag: 560 | * or udpSocket:didNotSendDataWithTag:dueToError: methods. 561 | * You can use it as an array index, state id, type constant, etc. 562 | * 563 | * 564 | * Thread-Safety Note: 565 | * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while 566 | * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method 567 | * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying 568 | * that this particular send operation has completed. 569 | * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data. 570 | * It simply retains it for performance reasons. 571 | * Often times, if NSMutableData is passed, it is because a request/response was built up in memory. 572 | * Copying this data adds an unwanted/unneeded overhead. 573 | * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket 574 | * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time 575 | * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method. 576 | **/ 577 | - (void)sendData:(NSData *)data toAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout tag:(long)tag; 578 | 579 | /** 580 | * You may optionally set a send filter for the socket. 581 | * A filter can provide several interesting possibilities: 582 | * 583 | * 1. Optional caching of resolved addresses for domain names. 584 | * The cache could later be consulted, resulting in fewer system calls to getaddrinfo. 585 | * 586 | * 2. Reusable modules of code for bandwidth monitoring. 587 | * 588 | * 3. Sometimes traffic shapers are needed to simulate real world environments. 589 | * A filter allows you to write custom code to simulate such environments. 590 | * The ability to code this yourself is especially helpful when your simulated environment 591 | * is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router), 592 | * or the system tools to handle this aren't available (e.g. on a mobile device). 593 | * 594 | * For more information about GCDAsyncUdpSocketSendFilterBlock, see the documentation for its typedef. 595 | * To remove a previously set filter, invoke this method and pass a nil filterBlock and NULL filterQueue. 596 | * 597 | * Note: This method invokes setSendFilter:withQueue:isAsynchronous: (documented below), 598 | * passing YES for the isAsynchronous parameter. 599 | **/ 600 | - (void)setSendFilter:(GCDAsyncUdpSocketSendFilterBlock)filterBlock withQueue:(dispatch_queue_t)filterQueue; 601 | 602 | /** 603 | * The receive filter can be run via dispatch_async or dispatch_sync. 604 | * Most typical situations call for asynchronous operation. 605 | * 606 | * However, there are a few situations in which synchronous operation is preferred. 607 | * Such is the case when the filter is extremely minimal and fast. 608 | * This is because dispatch_sync is faster than dispatch_async. 609 | * 610 | * If you choose synchronous operation, be aware of possible deadlock conditions. 611 | * Since the socket queue is executing your block via dispatch_sync, 612 | * then you cannot perform any tasks which may invoke dispatch_sync on the socket queue. 613 | * For example, you can't query properties on the socket. 614 | **/ 615 | - (void)setSendFilter:(GCDAsyncUdpSocketSendFilterBlock)filterBlock 616 | withQueue:(dispatch_queue_t)filterQueue 617 | isAsynchronous:(BOOL)isAsynchronous; 618 | 619 | #pragma mark Receiving 620 | 621 | /** 622 | * There are two modes of operation for receiving packets: one-at-a-time & continuous. 623 | * 624 | * In one-at-a-time mode, you call receiveOnce everytime your delegate is ready to process an incoming udp packet. 625 | * Receiving packets one-at-a-time may be better suited for implementing certain state machine code, 626 | * where your state machine may not always be ready to process incoming packets. 627 | * 628 | * In continuous mode, the delegate is invoked immediately everytime incoming udp packets are received. 629 | * Receiving packets continuously is better suited to real-time streaming applications. 630 | * 631 | * You may switch back and forth between one-at-a-time mode and continuous mode. 632 | * If the socket is currently in continuous mode, calling this method will switch it to one-at-a-time mode. 633 | * 634 | * When a packet is received (and not filtered by the optional receive filter), 635 | * the delegate method (udpSocket:didReceiveData:fromAddress:withFilterContext:) is invoked. 636 | * 637 | * If the socket is able to begin receiving packets, this method returns YES. 638 | * Otherwise it returns NO, and sets the errPtr with appropriate error information. 639 | * 640 | * An example error: 641 | * You created a udp socket to act as a server, and immediately called receive. 642 | * You forgot to first bind the socket to a port number, and received a error with a message like: 643 | * "Must bind socket before you can receive data." 644 | **/ 645 | - (BOOL)receiveOnce:(NSError **)errPtr; 646 | 647 | /** 648 | * There are two modes of operation for receiving packets: one-at-a-time & continuous. 649 | * 650 | * In one-at-a-time mode, you call receiveOnce everytime your delegate is ready to process an incoming udp packet. 651 | * Receiving packets one-at-a-time may be better suited for implementing certain state machine code, 652 | * where your state machine may not always be ready to process incoming packets. 653 | * 654 | * In continuous mode, the delegate is invoked immediately everytime incoming udp packets are received. 655 | * Receiving packets continuously is better suited to real-time streaming applications. 656 | * 657 | * You may switch back and forth between one-at-a-time mode and continuous mode. 658 | * If the socket is currently in one-at-a-time mode, calling this method will switch it to continuous mode. 659 | * 660 | * For every received packet (not filtered by the optional receive filter), 661 | * the delegate method (udpSocket:didReceiveData:fromAddress:withFilterContext:) is invoked. 662 | * 663 | * If the socket is able to begin receiving packets, this method returns YES. 664 | * Otherwise it returns NO, and sets the errPtr with appropriate error information. 665 | * 666 | * An example error: 667 | * You created a udp socket to act as a server, and immediately called receive. 668 | * You forgot to first bind the socket to a port number, and received a error with a message like: 669 | * "Must bind socket before you can receive data." 670 | **/ 671 | - (BOOL)beginReceiving:(NSError **)errPtr; 672 | 673 | /** 674 | * If the socket is currently receiving (beginReceiving has been called), this method pauses the receiving. 675 | * That is, it won't read any more packets from the underlying OS socket until beginReceiving is called again. 676 | * 677 | * Important Note: 678 | * GCDAsyncUdpSocket may be running in parallel with your code. 679 | * That is, your delegate is likely running on a separate thread/dispatch_queue. 680 | * When you invoke this method, GCDAsyncUdpSocket may have already dispatched delegate methods to be invoked. 681 | * Thus, if those delegate methods have already been dispatch_async'd, 682 | * your didReceive delegate method may still be invoked after this method has been called. 683 | * You should be aware of this, and program defensively. 684 | **/ 685 | - (void)pauseReceiving; 686 | 687 | /** 688 | * You may optionally set a receive filter for the socket. 689 | * This receive filter may be set to run in its own queue (independent of delegate queue). 690 | * 691 | * A filter can provide several useful features. 692 | * 693 | * 1. Many times udp packets need to be parsed. 694 | * Since the filter can run in its own independent queue, you can parallelize this parsing quite easily. 695 | * The end result is a parallel socket io, datagram parsing, and packet processing. 696 | * 697 | * 2. Many times udp packets are discarded because they are duplicate/unneeded/unsolicited. 698 | * The filter can prevent such packets from arriving at the delegate. 699 | * And because the filter can run in its own independent queue, this doesn't slow down the delegate. 700 | * 701 | * - Since the udp protocol does not guarantee delivery, udp packets may be lost. 702 | * Many protocols built atop udp thus provide various resend/re-request algorithms. 703 | * This sometimes results in duplicate packets arriving. 704 | * A filter may allow you to architect the duplicate detection code to run in parallel to normal processing. 705 | * 706 | * - Since the udp socket may be connectionless, its possible for unsolicited packets to arrive. 707 | * Such packets need to be ignored. 708 | * 709 | * 3. Sometimes traffic shapers are needed to simulate real world environments. 710 | * A filter allows you to write custom code to simulate such environments. 711 | * The ability to code this yourself is especially helpful when your simulated environment 712 | * is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router), 713 | * or the system tools to handle this aren't available (e.g. on a mobile device). 714 | * 715 | * Example: 716 | * 717 | * GCDAsyncUdpSocketReceiveFilterBlock filter = ^BOOL (NSData *data, NSData *address, id *context) { 718 | * 719 | * MyProtocolMessage *msg = [MyProtocol parseMessage:data]; 720 | * 721 | * *context = response; 722 | * return (response != nil); 723 | * }; 724 | * [udpSocket setReceiveFilter:filter withQueue:myParsingQueue]; 725 | * 726 | * For more information about GCDAsyncUdpSocketReceiveFilterBlock, see the documentation for its typedef. 727 | * To remove a previously set filter, invoke this method and pass a nil filterBlock and NULL filterQueue. 728 | * 729 | * Note: This method invokes setReceiveFilter:withQueue:isAsynchronous: (documented below), 730 | * passing YES for the isAsynchronous parameter. 731 | **/ 732 | - (void)setReceiveFilter:(GCDAsyncUdpSocketReceiveFilterBlock)filterBlock withQueue:(dispatch_queue_t)filterQueue; 733 | 734 | /** 735 | * The receive filter can be run via dispatch_async or dispatch_sync. 736 | * Most typical situations call for asynchronous operation. 737 | * 738 | * However, there are a few situations in which synchronous operation is preferred. 739 | * Such is the case when the filter is extremely minimal and fast. 740 | * This is because dispatch_sync is faster than dispatch_async. 741 | * 742 | * If you choose synchronous operation, be aware of possible deadlock conditions. 743 | * Since the socket queue is executing your block via dispatch_sync, 744 | * then you cannot perform any tasks which may invoke dispatch_sync on the socket queue. 745 | * For example, you can't query properties on the socket. 746 | **/ 747 | - (void)setReceiveFilter:(GCDAsyncUdpSocketReceiveFilterBlock)filterBlock 748 | withQueue:(dispatch_queue_t)filterQueue 749 | isAsynchronous:(BOOL)isAsynchronous; 750 | 751 | #pragma mark Closing 752 | 753 | /** 754 | * Immediately closes the underlying socket. 755 | * Any pending send operations are discarded. 756 | * 757 | * The GCDAsyncUdpSocket instance may optionally be used again. 758 | * (it will setup/configure/use another unnderlying BSD socket). 759 | **/ 760 | - (void)close; 761 | 762 | /** 763 | * Closes the underlying socket after all pending send operations have been sent. 764 | * 765 | * The GCDAsyncUdpSocket instance may optionally be used again. 766 | * (it will setup/configure/use another unnderlying BSD socket). 767 | **/ 768 | - (void)closeAfterSending; 769 | 770 | #pragma mark Advanced 771 | /** 772 | * GCDAsyncSocket maintains thread safety by using an internal serial dispatch_queue. 773 | * In most cases, the instance creates this queue itself. 774 | * However, to allow for maximum flexibility, the internal queue may be passed in the init method. 775 | * This allows for some advanced options such as controlling socket priority via target queues. 776 | * However, when one begins to use target queues like this, they open the door to some specific deadlock issues. 777 | * 778 | * For example, imagine there are 2 queues: 779 | * dispatch_queue_t socketQueue; 780 | * dispatch_queue_t socketTargetQueue; 781 | * 782 | * If you do this (pseudo-code): 783 | * socketQueue.targetQueue = socketTargetQueue; 784 | * 785 | * Then all socketQueue operations will actually get run on the given socketTargetQueue. 786 | * This is fine and works great in most situations. 787 | * But if you run code directly from within the socketTargetQueue that accesses the socket, 788 | * you could potentially get deadlock. Imagine the following code: 789 | * 790 | * - (BOOL)socketHasSomething 791 | * { 792 | * __block BOOL result = NO; 793 | * dispatch_block_t block = ^{ 794 | * result = [self someInternalMethodToBeRunOnlyOnSocketQueue]; 795 | * } 796 | * if (is_executing_on_queue(socketQueue)) 797 | * block(); 798 | * else 799 | * dispatch_sync(socketQueue, block); 800 | * 801 | * return result; 802 | * } 803 | * 804 | * What happens if you call this method from the socketTargetQueue? The result is deadlock. 805 | * This is because the GCD API offers no mechanism to discover a queue's targetQueue. 806 | * Thus we have no idea if our socketQueue is configured with a targetQueue. 807 | * If we had this information, we could easily avoid deadlock. 808 | * But, since these API's are missing or unfeasible, you'll have to explicitly set it. 809 | * 810 | * IF you pass a socketQueue via the init method, 811 | * AND you've configured the passed socketQueue with a targetQueue, 812 | * THEN you should pass the end queue in the target hierarchy. 813 | * 814 | * For example, consider the following queue hierarchy: 815 | * socketQueue -> ipQueue -> moduleQueue 816 | * 817 | * This example demonstrates priority shaping within some server. 818 | * All incoming client connections from the same IP address are executed on the same target queue. 819 | * And all connections for a particular module are executed on the same target queue. 820 | * Thus, the priority of all networking for the entire module can be changed on the fly. 821 | * Additionally, networking traffic from a single IP cannot monopolize the module. 822 | * 823 | * Here's how you would accomplish something like that: 824 | * - (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock 825 | * { 826 | * dispatch_queue_t socketQueue = dispatch_queue_create("", NULL); 827 | * dispatch_queue_t ipQueue = [self ipQueueForAddress:address]; 828 | * 829 | * dispatch_set_target_queue(socketQueue, ipQueue); 830 | * dispatch_set_target_queue(iqQueue, moduleQueue); 831 | * 832 | * return socketQueue; 833 | * } 834 | * - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 835 | * { 836 | * [clientConnections addObject:newSocket]; 837 | * [newSocket markSocketQueueTargetQueue:moduleQueue]; 838 | * } 839 | * 840 | * Note: This workaround is ONLY needed if you intend to execute code directly on the ipQueue or moduleQueue. 841 | * This is often NOT the case, as such queues are used solely for execution shaping. 842 | **/ 843 | - (void)markSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreConfiguredTargetQueue; 844 | - (void)unmarkSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreviouslyConfiguredTargetQueue; 845 | 846 | /** 847 | * It's not thread-safe to access certain variables from outside the socket's internal queue. 848 | * 849 | * For example, the socket file descriptor. 850 | * File descriptors are simply integers which reference an index in the per-process file table. 851 | * However, when one requests a new file descriptor (by opening a file or socket), 852 | * the file descriptor returned is guaranteed to be the lowest numbered unused descriptor. 853 | * So if we're not careful, the following could be possible: 854 | * 855 | * - Thread A invokes a method which returns the socket's file descriptor. 856 | * - The socket is closed via the socket's internal queue on thread B. 857 | * - Thread C opens a file, and subsequently receives the file descriptor that was previously the socket's FD. 858 | * - Thread A is now accessing/altering the file instead of the socket. 859 | * 860 | * In addition to this, other variables are not actually objects, 861 | * and thus cannot be retained/released or even autoreleased. 862 | * An example is the sslContext, of type SSLContextRef, which is actually a malloc'd struct. 863 | * 864 | * Although there are internal variables that make it difficult to maintain thread-safety, 865 | * it is important to provide access to these variables 866 | * to ensure this class can be used in a wide array of environments. 867 | * This method helps to accomplish this by invoking the current block on the socket's internal queue. 868 | * The methods below can be invoked from within the block to access 869 | * those generally thread-unsafe internal variables in a thread-safe manner. 870 | * The given block will be invoked synchronously on the socket's internal queue. 871 | * 872 | * If you save references to any protected variables and use them outside the block, you do so at your own peril. 873 | **/ 874 | - (void)performBlock:(dispatch_block_t)block; 875 | 876 | /** 877 | * These methods are only available from within the context of a performBlock: invocation. 878 | * See the documentation for the performBlock: method above. 879 | * 880 | * Provides access to the socket's file descriptor(s). 881 | * If the socket isn't connected, or explicity bound to a particular interface, 882 | * it might actually have multiple internal socket file descriptors - one for IPv4 and one for IPv6. 883 | **/ 884 | - (int)socketFD; 885 | - (int)socket4FD; 886 | - (int)socket6FD; 887 | 888 | #if TARGET_OS_IPHONE 889 | 890 | /** 891 | * These methods are only available from within the context of a performBlock: invocation. 892 | * See the documentation for the performBlock: method above. 893 | * 894 | * Returns (creating if necessary) a CFReadStream/CFWriteStream for the internal socket. 895 | * 896 | * Generally GCDAsyncUdpSocket doesn't use CFStream. (It uses the faster GCD API's.) 897 | * However, if you need one for any reason, 898 | * these methods are a convenient way to get access to a safe instance of one. 899 | **/ 900 | - (CFReadStreamRef)readStream; 901 | - (CFWriteStreamRef)writeStream; 902 | 903 | /** 904 | * This method is only available from within the context of a performBlock: invocation. 905 | * See the documentation for the performBlock: method above. 906 | * 907 | * Configures the socket to allow it to operate when the iOS application has been backgrounded. 908 | * In other words, this method creates a read & write stream, and invokes: 909 | * 910 | * CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); 911 | * CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); 912 | * 913 | * Returns YES if successful, NO otherwise. 914 | * 915 | * Example usage: 916 | * 917 | * [asyncUdpSocket performBlock:^{ 918 | * [asyncUdpSocket enableBackgroundingOnSocket]; 919 | * }]; 920 | * 921 | * 922 | * NOTE : Apple doesn't currently support backgrounding UDP sockets. (Only TCP for now). 923 | **/ 924 | //- (BOOL)enableBackgroundingOnSockets; 925 | 926 | #endif 927 | 928 | #pragma mark Utilities 929 | 930 | /** 931 | * Extracting host/port/family information from raw address data. 932 | **/ 933 | 934 | + (NSString *)hostFromAddress:(NSData *)address; 935 | + (uint16_t)portFromAddress:(NSData *)address; 936 | + (int)familyFromAddress:(NSData *)address; 937 | 938 | + (BOOL)isIPv4Address:(NSData *)address; 939 | + (BOOL)isIPv6Address:(NSData *)address; 940 | 941 | + (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address; 942 | + (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(int *)afPtr fromAddress:(NSData *)address; 943 | 944 | @end 945 | 946 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 947 | #pragma mark - 948 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 949 | 950 | @protocol GCDAsyncUdpSocketDelegate 951 | @optional 952 | 953 | /** 954 | * By design, UDP is a connectionless protocol, and connecting is not needed. 955 | * However, you may optionally choose to connect to a particular host for reasons 956 | * outlined in the documentation for the various connect methods listed above. 957 | * 958 | * This method is called if one of the connect methods are invoked, and the connection is successful. 959 | **/ 960 | - (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address; 961 | 962 | /** 963 | * By design, UDP is a connectionless protocol, and connecting is not needed. 964 | * However, you may optionally choose to connect to a particular host for reasons 965 | * outlined in the documentation for the various connect methods listed above. 966 | * 967 | * This method is called if one of the connect methods are invoked, and the connection fails. 968 | * This may happen, for example, if a domain name is given for the host and the domain name is unable to be resolved. 969 | **/ 970 | - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError *)error; 971 | 972 | /** 973 | * Called when the datagram with the given tag has been sent. 974 | **/ 975 | - (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag; 976 | 977 | /** 978 | * Called if an error occurs while trying to send a datagram. 979 | * This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet. 980 | **/ 981 | - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error; 982 | 983 | /** 984 | * Called when the socket has received the requested datagram. 985 | **/ 986 | - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data 987 | fromAddress:(NSData *)address 988 | withFilterContext:(id)filterContext; 989 | 990 | /** 991 | * Called when the socket is closed. 992 | **/ 993 | - (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error; 994 | 995 | @end 996 | 997 | -------------------------------------------------------------------------------- /Packet Sender/HRToast+UIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HRToast + UIView.swift 3 | // ToastDemo 4 | // 5 | // Created by Rannie on 14/7/6. 6 | // Copyright (c) 2014年 Rannie. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /* 12 | * Infix overload method 13 | */ 14 | func /(lhs: CGFloat, rhs: Int) -> CGFloat { 15 | return lhs / CGFloat(rhs) 16 | } 17 | 18 | /* 19 | * Toast Config 20 | */ 21 | let HRToastDefaultDuration = 2.0 22 | let HRToastFadeDuration = 0.2 23 | let HRToastHorizontalMargin : CGFloat = 10.0 24 | let HRToastVerticalMargin : CGFloat = 10.0 25 | 26 | let HRToastPositionDefault = "bottom" 27 | let HRToastPositionTop = "top" 28 | let HRToastPositionCenter = "center" 29 | 30 | // activity 31 | let HRToastActivityWidth : CGFloat = 100.0 32 | let HRToastActivityHeight : CGFloat = 100.0 33 | let HRToastActivityPositionDefault = "center" 34 | 35 | // image size 36 | let HRToastImageViewWidth : CGFloat = 80.0 37 | let HRToastImageViewHeight: CGFloat = 80.0 38 | 39 | // label setting 40 | let HRToastMaxWidth : CGFloat = 0.8; // 80% of parent view width 41 | let HRToastMaxHeight : CGFloat = 0.8; 42 | let HRToastFontSize : CGFloat = 16.0 43 | let HRToastMaxTitleLines = 0 44 | let HRToastMaxMessageLines = 0 45 | 46 | // shadow appearance 47 | let HRToastShadowOpacity : CGFloat = 0.8 48 | let HRToastShadowRadius : CGFloat = 6.0 49 | let HRToastShadowOffset : CGSize = CGSizeMake(CGFloat(4.0), CGFloat(4.0)) 50 | 51 | let HRToastOpacity : CGFloat = 0.8 52 | let HRToastCornerRadius : CGFloat = 10.0 53 | 54 | var HRToastActivityView: UnsafePointer = nil 55 | var HRToastTimer: UnsafePointer = nil 56 | var HRToastView: UnsafePointer = nil 57 | 58 | /* 59 | * Custom Config 60 | */ 61 | let HRToastHidesOnTap = true 62 | let HRToastDisplayShadow = true 63 | 64 | //HRToast (UIView + Toast using Swift) 65 | 66 | extension UIView { 67 | 68 | /* 69 | * public methods 70 | */ 71 | func makeToast(message msg: String) { 72 | self.makeToast(message: msg, duration: HRToastDefaultDuration, position: HRToastPositionDefault) 73 | } 74 | 75 | func makeToast(message msg: String, duration: Double, position: AnyObject) { 76 | var toast = self.viewForMessage(msg, title: nil, image: nil) 77 | self.showToast(toast: toast!, duration: duration, position: position) 78 | } 79 | 80 | func makeToast(message msg: String, duration: Double, position: AnyObject, title: String) { 81 | var toast = self.viewForMessage(msg, title: title, image: nil) 82 | self.showToast(toast: toast!, duration: duration, position: position) 83 | } 84 | 85 | func makeToast(message msg: String, duration: Double, position: AnyObject, image: UIImage) { 86 | var toast = self.viewForMessage(msg, title: nil, image: image) 87 | self.showToast(toast: toast!, duration: duration, position: position) 88 | } 89 | 90 | func makeToast(message msg: String, duration: Double, position: AnyObject, title: String, image: UIImage) { 91 | var toast = self.viewForMessage(msg, title: title, image: image) 92 | self.showToast(toast: toast!, duration: duration, position: position) 93 | } 94 | 95 | func showToast(#toast: UIView) { 96 | self.showToast(toast: toast, duration: HRToastDefaultDuration, position: HRToastPositionDefault) 97 | } 98 | 99 | func showToast(#toast: UIView, duration: Double, position: AnyObject) { 100 | var existToast = objc_getAssociatedObject(self, &HRToastView) as! UIView? 101 | if existToast != nil { 102 | var timer = objc_getAssociatedObject(existToast, &HRToastTimer) as! NSTimer 103 | timer.invalidate(); 104 | self.hideToast(toast: existToast!, force: false); 105 | } 106 | 107 | toast.center = self.centerPointForPosition(position, toast: toast) 108 | toast.alpha = 0.0 109 | 110 | if HRToastHidesOnTap { 111 | var tapRecognizer = UITapGestureRecognizer(target: toast, action: Selector("handleToastTapped:")) 112 | toast.addGestureRecognizer(tapRecognizer) 113 | toast.userInteractionEnabled = true; 114 | toast.exclusiveTouch = true; 115 | } 116 | 117 | self.addSubview(toast) 118 | objc_setAssociatedObject(self, &HRToastView, toast, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN)) 119 | 120 | UIView.animateWithDuration(HRToastFadeDuration, 121 | delay: 0.0, options: (.CurveEaseOut | .AllowUserInteraction), 122 | animations: { 123 | toast.alpha = 1.0 124 | }, 125 | completion: { (finished: Bool) in 126 | var timer = NSTimer.scheduledTimerWithTimeInterval(duration, target: self, selector: Selector("toastTimerDidFinish:"), userInfo: toast, repeats: false) 127 | objc_setAssociatedObject(toast, &HRToastTimer, timer, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) 128 | }) 129 | } 130 | 131 | func makeToastActivity() { 132 | self.makeToastActivity(position: HRToastActivityPositionDefault) 133 | } 134 | 135 | func makeToastActivityWithMessage(message msg: String){ 136 | self.makeToastActivity(position: HRToastActivityPositionDefault, message: msg) 137 | } 138 | 139 | func makeToastActivity(position pos: AnyObject, message msg: String = "") { 140 | var existingActivityView: UIView? = objc_getAssociatedObject(self, &HRToastActivityView) as? UIView 141 | if existingActivityView != nil { return } 142 | 143 | var activityView = UIView(frame: CGRectMake(0, 0, HRToastActivityWidth, HRToastActivityHeight)) 144 | activityView.center = self.centerPointForPosition(pos, toast: activityView) 145 | activityView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(HRToastOpacity) 146 | activityView.alpha = 0.0 147 | activityView.autoresizingMask = (.FlexibleLeftMargin | .FlexibleTopMargin | .FlexibleRightMargin | .FlexibleBottomMargin) 148 | activityView.layer.cornerRadius = HRToastCornerRadius 149 | 150 | if HRToastDisplayShadow { 151 | activityView.layer.shadowColor = UIColor.blackColor().CGColor 152 | activityView.layer.shadowOpacity = Float(HRToastShadowOpacity) 153 | activityView.layer.shadowRadius = HRToastShadowRadius 154 | activityView.layer.shadowOffset = HRToastShadowOffset 155 | } 156 | 157 | var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge) 158 | activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2) 159 | activityView.addSubview(activityIndicatorView) 160 | activityIndicatorView.startAnimating() 161 | 162 | if (!msg.isEmpty){ 163 | activityIndicatorView.frame.origin.y -= 10 164 | var activityMessageLabel = UILabel(frame: CGRectMake(activityView.bounds.origin.x, (activityIndicatorView.frame.origin.y + activityIndicatorView.frame.size.height + 10), activityView.bounds.size.width, 20)) 165 | activityMessageLabel.textColor = UIColor.whiteColor() 166 | activityMessageLabel.font = (count(msg)<=10) ? UIFont(name:activityMessageLabel.font.fontName, size: 16) : UIFont(name:activityMessageLabel.font.fontName, size: 13) 167 | activityMessageLabel.textAlignment = .Center 168 | activityMessageLabel.text = msg 169 | activityView.addSubview(activityMessageLabel) 170 | } 171 | 172 | self.addSubview(activityView) 173 | 174 | // associate activity view with self 175 | objc_setAssociatedObject(self, &HRToastActivityView, activityView, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) 176 | 177 | UIView.animateWithDuration(HRToastFadeDuration, 178 | delay: 0.0, 179 | options: UIViewAnimationOptions.CurveEaseOut, 180 | animations: { 181 | activityView.alpha = 1.0 182 | }, 183 | completion: nil) 184 | } 185 | 186 | func hideToastActivity() { 187 | var existingActivityView = objc_getAssociatedObject(self, &HRToastActivityView) as! UIView? 188 | if existingActivityView == nil { return } 189 | UIView.animateWithDuration(HRToastFadeDuration, 190 | delay: 0.0, 191 | options: UIViewAnimationOptions.CurveEaseOut, 192 | animations: { 193 | existingActivityView!.alpha = 0.0 194 | }, 195 | completion: { (finished: Bool) in 196 | existingActivityView!.removeFromSuperview() 197 | objc_setAssociatedObject(self, &HRToastActivityView, nil, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) 198 | }) 199 | } 200 | 201 | /* 202 | * private methods (helper) 203 | */ 204 | func hideToast(#toast: UIView) { 205 | self.hideToast(toast: toast, force: false); 206 | } 207 | 208 | func hideToast(#toast: UIView, force: Bool) { 209 | var completeClosure = { (finish: Bool) -> () in 210 | toast.removeFromSuperview() 211 | objc_setAssociatedObject(self, &HRToastTimer, nil, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) 212 | } 213 | 214 | if force { 215 | completeClosure(true) 216 | } else { 217 | UIView.animateWithDuration(HRToastFadeDuration, 218 | delay: 0.0, 219 | options: (.CurveEaseIn | .BeginFromCurrentState), 220 | animations: { 221 | toast.alpha = 0.0 222 | }, 223 | completion:completeClosure) 224 | } 225 | } 226 | 227 | func toastTimerDidFinish(timer: NSTimer) { 228 | self.hideToast(toast: timer.userInfo as! UIView) 229 | } 230 | 231 | func handleToastTapped(recognizer: UITapGestureRecognizer) { 232 | var timer = objc_getAssociatedObject(self, &HRToastTimer) as! NSTimer 233 | timer.invalidate() 234 | 235 | self.hideToast(toast: recognizer.view!) 236 | } 237 | 238 | func centerPointForPosition(position: AnyObject, toast: UIView) -> CGPoint { 239 | if position is String { 240 | var toastSize = toast.bounds.size 241 | var viewSize = self.bounds.size 242 | if position.lowercaseString == HRToastPositionTop { 243 | return CGPointMake(viewSize.width/2, toastSize.height/2 + HRToastVerticalMargin) 244 | } else if position.lowercaseString == HRToastPositionDefault { 245 | return CGPointMake(viewSize.width/2, viewSize.height - toastSize.height/2 - HRToastVerticalMargin) 246 | } else if position.lowercaseString == HRToastPositionCenter { 247 | return CGPointMake(viewSize.width/2, viewSize.height/2) 248 | } 249 | } else if position is NSValue { 250 | return position.CGPointValue() 251 | } 252 | 253 | println("Warning: Invalid position for toast.") 254 | return self.centerPointForPosition(HRToastPositionDefault, toast: toast) 255 | } 256 | 257 | func viewForMessage(msg: String?, title: String?, image: UIImage?) -> UIView? { 258 | if msg == nil && title == nil && image == nil { return nil } 259 | 260 | var msgLabel: UILabel? 261 | var titleLabel: UILabel? 262 | var imageView: UIImageView? 263 | 264 | var wrapperView = UIView() 265 | wrapperView.autoresizingMask = (.FlexibleLeftMargin | .FlexibleRightMargin | .FlexibleTopMargin | .FlexibleBottomMargin) 266 | wrapperView.layer.cornerRadius = HRToastCornerRadius 267 | wrapperView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(HRToastOpacity) 268 | 269 | if HRToastDisplayShadow { 270 | wrapperView.layer.shadowColor = UIColor.blackColor().CGColor 271 | wrapperView.layer.shadowOpacity = Float(HRToastShadowOpacity) 272 | wrapperView.layer.shadowRadius = HRToastShadowRadius 273 | wrapperView.layer.shadowOffset = HRToastShadowOffset 274 | } 275 | 276 | if image != nil { 277 | imageView = UIImageView(image: image) 278 | imageView!.contentMode = .ScaleAspectFit 279 | imageView!.frame = CGRectMake(HRToastHorizontalMargin, HRToastVerticalMargin, CGFloat(HRToastImageViewWidth), CGFloat(HRToastImageViewHeight)) 280 | } 281 | 282 | var imageWidth: CGFloat, imageHeight: CGFloat, imageLeft: CGFloat 283 | if imageView != nil { 284 | imageWidth = imageView!.bounds.size.width 285 | imageHeight = imageView!.bounds.size.height 286 | imageLeft = HRToastHorizontalMargin 287 | } else { 288 | imageWidth = 0.0; imageHeight = 0.0; imageLeft = 0.0 289 | } 290 | 291 | if title != nil { 292 | titleLabel = UILabel() 293 | titleLabel!.numberOfLines = HRToastMaxTitleLines 294 | titleLabel!.font = UIFont.boldSystemFontOfSize(HRToastFontSize) 295 | titleLabel!.textAlignment = .Center 296 | titleLabel!.lineBreakMode = .ByWordWrapping 297 | titleLabel!.textColor = UIColor.whiteColor() 298 | titleLabel!.backgroundColor = UIColor.clearColor() 299 | titleLabel!.alpha = 1.0 300 | titleLabel!.text = title 301 | 302 | // size the title label according to the length of the text 303 | var maxSizeTitle = CGSizeMake((self.bounds.size.width * HRToastMaxWidth) - imageWidth, self.bounds.size.height * HRToastMaxHeight); 304 | var expectedHeight = title!.stringHeightWithFontSize(HRToastFontSize, width: maxSizeTitle.width) 305 | titleLabel!.frame = CGRectMake(0.0, 0.0, maxSizeTitle.width, expectedHeight) 306 | } 307 | 308 | if msg != nil { 309 | msgLabel = UILabel(); 310 | msgLabel!.numberOfLines = HRToastMaxMessageLines 311 | msgLabel!.font = UIFont.systemFontOfSize(HRToastFontSize) 312 | msgLabel!.lineBreakMode = .ByWordWrapping 313 | msgLabel!.textAlignment = .Center 314 | msgLabel!.textColor = UIColor.whiteColor() 315 | msgLabel!.backgroundColor = UIColor.clearColor() 316 | msgLabel!.alpha = 1.0 317 | msgLabel!.text = msg 318 | 319 | var maxSizeMessage = CGSizeMake((self.bounds.size.width * HRToastMaxWidth) - imageWidth, self.bounds.size.height * HRToastMaxHeight) 320 | var expectedHeight = msg!.stringHeightWithFontSize(HRToastFontSize, width: maxSizeMessage.width) 321 | msgLabel!.frame = CGRectMake(0.0, 0.0, maxSizeMessage.width, expectedHeight) 322 | } 323 | 324 | var titleWidth: CGFloat, titleHeight: CGFloat, titleTop: CGFloat, titleLeft: CGFloat 325 | if titleLabel != nil { 326 | titleWidth = titleLabel!.bounds.size.width 327 | titleHeight = titleLabel!.bounds.size.height 328 | titleTop = HRToastVerticalMargin 329 | titleLeft = imageLeft + imageWidth + HRToastHorizontalMargin 330 | } else { 331 | titleWidth = 0.0; titleHeight = 0.0; titleTop = 0.0; titleLeft = 0.0 332 | } 333 | 334 | var msgWidth: CGFloat, msgHeight: CGFloat, msgTop: CGFloat, msgLeft: CGFloat 335 | if msgLabel != nil { 336 | msgWidth = msgLabel!.bounds.size.width 337 | msgHeight = msgLabel!.bounds.size.height 338 | msgTop = titleTop + titleHeight + HRToastVerticalMargin 339 | msgLeft = imageLeft + imageWidth + HRToastHorizontalMargin 340 | } else { 341 | msgWidth = 0.0; msgHeight = 0.0; msgTop = 0.0; msgLeft = 0.0 342 | } 343 | 344 | var largerWidth = max(titleWidth, msgWidth) 345 | var largerLeft = max(titleLeft, msgLeft) 346 | 347 | // set wrapper view's frame 348 | var wrapperWidth = max(imageWidth + HRToastHorizontalMargin * 2, largerLeft + largerWidth + HRToastHorizontalMargin) 349 | var wrapperHeight = max(msgTop + msgHeight + HRToastVerticalMargin, imageHeight + HRToastVerticalMargin * 2) 350 | wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight) 351 | 352 | // add subviews 353 | if titleLabel != nil { 354 | titleLabel!.frame = CGRectMake(titleLeft, titleTop, titleWidth, titleHeight) 355 | wrapperView.addSubview(titleLabel!) 356 | } 357 | if msgLabel != nil { 358 | msgLabel!.frame = CGRectMake(msgLeft, msgTop, msgWidth, msgHeight) 359 | wrapperView.addSubview(msgLabel!) 360 | } 361 | if imageView != nil { 362 | wrapperView.addSubview(imageView!) 363 | } 364 | 365 | return wrapperView 366 | } 367 | 368 | } 369 | 370 | extension String { 371 | 372 | func stringHeightWithFontSize(fontSize: CGFloat,width: CGFloat) -> CGFloat { 373 | var font = UIFont.systemFontOfSize(fontSize) 374 | var size = CGSizeMake(width, CGFloat.max) 375 | var paragraphStyle = NSMutableParagraphStyle() 376 | paragraphStyle.lineBreakMode = .ByWordWrapping; 377 | var attributes = [NSFontAttributeName:font, 378 | NSParagraphStyleAttributeName:paragraphStyle.copy()] 379 | 380 | var text = self as NSString 381 | var rect = text.boundingRectWithSize(size, options:.UsesLineFragmentOrigin, attributes: attributes, context:nil) 382 | return rect.size.height 383 | } 384 | 385 | } 386 | 387 | 388 | -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "pslogo29@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "pslogo29@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "pslogo40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "pslogo40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "pslogo60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "pslogo60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "pslogo29.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "pslogo29@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "pslogo40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "pslogo40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "pslogo76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "pslogo76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@2x-1.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@2x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo29@3x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@2x-1.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@2x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo40@3x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo60@2x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo60@3x.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo76.png -------------------------------------------------------------------------------- /Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/Images.xcassets/AppIcon.appiconset/pslogo76@2x.png -------------------------------------------------------------------------------- /Packet Sender/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationExitsOnSuspend 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | com.packetsender.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | UIInterfaceOrientationPortraitUpsideDown 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Packet Sender/Packet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Packet.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | import UIKit 11 | import Foundation 12 | import CoreData 13 | 14 | extension Character { 15 | func intValue() -> Int { 16 | for s in String(self).utf8 { 17 | return Int(s) 18 | } 19 | return 0 as Int 20 | } 21 | func utf8Value() -> UInt8 { 22 | for s in String(self).utf8 { 23 | return s 24 | } 25 | return 0 26 | } 27 | 28 | func utf16Value() -> UInt16 { 29 | for s in String(self).utf16 { 30 | return s 31 | } 32 | return 0 33 | } 34 | 35 | func unicodeValue() -> UInt32 { 36 | for s in String(self).unicodeScalars { 37 | return s.value 38 | } 39 | return 0 40 | } 41 | } 42 | 43 | 44 | func DLog(message: String, file: String = __FILE__, function: String = __FUNCTION__, line: Int = __LINE__, column: Int = __COLUMN__) { 45 | 46 | let fileArr = split(file) {$0 == "/"} 47 | let lastPart = fileArr.last 48 | println("\(lastPart!) : \(function) (\(line)): \(message)") 49 | } 50 | 51 | 52 | struct Globals { 53 | static var initialLoadFlag = false 54 | static var dataChanged = false 55 | static var trafficDataChanged = false 56 | static var timestamp = CACurrentMediaTime(); 57 | static var psnetwork = PacketNetwork() 58 | 59 | static var tcpServerError = "TCP Success" 60 | static var udpServerError = "UDP Success" 61 | } 62 | 63 | struct Packet: Printable { 64 | 65 | var name:String = "" 66 | var tcpOrUdp = "tcp" 67 | var fromIP = "" 68 | var toIP = "" 69 | var port = 5000 70 | var fromPort = 5000 71 | var hexString:String = "" 72 | var inTrafficLog:Bool = false; 73 | var timestamp:NSDate = NSDate() 74 | var error = "" 75 | 76 | 77 | static func parserUnitTest(ascii:String, hex:String) -> Bool { 78 | 79 | var hextest = Packet.asciiToHex(ascii) 80 | var asciitest = Packet.hexToASCII(hex) 81 | 82 | var pass1 = false 83 | var pass2 = false 84 | if(asciitest == ascii) { 85 | pass1 = true 86 | } else { 87 | DLog("fail ascii:\n" + asciitest + "\n" + ascii) 88 | } 89 | 90 | if(hextest == hex) { 91 | pass2 = true 92 | } else { 93 | DLog("fail hex:\n" + hextest + "\n" + hex) 94 | } 95 | 96 | return (pass1 && pass2) 97 | } 98 | 99 | static func asciiIsHex(val:Int) -> Bool { 100 | 101 | let zeroInt = Character("0").intValue() 102 | let nineInt = Character("9").intValue() 103 | let aInt = Character("a").intValue() 104 | let fInt = Character("f").intValue() 105 | let AInt = Character("A").intValue() 106 | let FInt = Character("F").intValue() 107 | 108 | if(val >= zeroInt && val <= nineInt) { 109 | return true 110 | } 111 | 112 | if(val >= aInt && val <= fInt) { 113 | return true 114 | } 115 | 116 | if(val >= AInt && val <= FInt) { 117 | return true 118 | } 119 | 120 | return false 121 | 122 | 123 | } 124 | 125 | 126 | static func asciiToHex(ascii:String) -> String { 127 | 128 | let length = ascii.lengthOfBytesUsingEncoding(NSASCIIStringEncoding) 129 | let characters = Array(ascii) 130 | var hexArray:[Int] = [] 131 | var i = 0 132 | 133 | let slashInt = Character("\\").intValue() 134 | let rInt = Character("r").intValue() 135 | let nInt = Character("n").intValue() 136 | 137 | for (i = 0; i < length; i++) { 138 | var char1 = characters[i].intValue() 139 | // hexArray.append(char1) 140 | // continue 141 | if char1 == slashInt && i + 1 < length{ 142 | var char2 = characters[i+1].intValue() 143 | 144 | if(char2 == slashInt) { 145 | hexArray.append(0x5C) 146 | i++ 147 | continue 148 | } 149 | if(char2 == rInt) { 150 | hexArray.append(0x0d) 151 | i++ 152 | continue 153 | } 154 | if(char2 == nInt) { 155 | hexArray.append(0x0a) 156 | i++ 157 | continue 158 | } 159 | 160 | if(asciiIsHex(char2)) { 161 | i++ 162 | var testString = "" 163 | let charC2 = Character(UnicodeScalar(char2)) 164 | testString.append(charC2) 165 | var result : UInt32 = 0 166 | if(i + 1 < length) { 167 | var char3 = characters[i+1].intValue() 168 | if(asciiIsHex(char3)) { 169 | i++ 170 | 171 | let charC3 = Character(UnicodeScalar(char3)) 172 | testString.append(charC3) 173 | let scanner = NSScanner(string: testString) 174 | if scanner.scanHexInt(&result) { 175 | hexArray.append(Int(result)) 176 | } 177 | } else { 178 | let scanner = NSScanner(string: testString) 179 | if scanner.scanHexInt(&result) { 180 | hexArray.append(Int(result)) 181 | } 182 | } 183 | } else { 184 | let scanner = NSScanner(string: testString) 185 | if scanner.scanHexInt(&result) { 186 | hexArray.append(Int(result)) 187 | } 188 | } 189 | continue 190 | } 191 | 192 | } else { 193 | hexArray.append(char1) 194 | } 195 | } 196 | 197 | var returnString:String = "" 198 | for hex in hexArray { 199 | var st = NSString(format:"%02X", hex) as String 200 | returnString += " " + st 201 | 202 | 203 | } 204 | //hexArray.join(" ") 205 | returnString = returnString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) 206 | 207 | return returnString.lowercaseString 208 | } 209 | 210 | 211 | static func hexToASCII(hex:String) -> String { 212 | 213 | var result : UInt32 = 0 214 | var byteArray:[UInt32] = [] 215 | let hexArray:[String] = split(hex) {$0 == " "} 216 | for val in hexArray { 217 | let scanner = NSScanner(string: val) 218 | if scanner.scanHexInt(&result) { 219 | byteArray.append(result) 220 | } 221 | } 222 | 223 | var resultString = "" 224 | for byte in byteArray { 225 | 226 | if(byte == 0x0A) 227 | { 228 | resultString = resultString + ("\\n"); 229 | 230 | } else if (byte == 0x5C) { 231 | resultString = resultString + ("\\\\"); 232 | 233 | } else if (byte == 0x0D) { 234 | resultString = resultString + ("\\r"); 235 | 236 | } else if (byte >= 0x20 && byte <= 0x7E) { 237 | let char = Character(UnicodeScalar(byte)) 238 | resultString.append(char) 239 | } else { 240 | var st = NSString(format:"%02X", byte) as String 241 | resultString = resultString + "\\" + st.lowercaseString 242 | 243 | } 244 | } 245 | 246 | return resultString 247 | } 248 | 249 | 250 | static func delete(thename:String) { 251 | DLog("deleting..." + thename) 252 | 253 | var appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 254 | var context:NSManagedObjectContext = appDel.managedObjectContext! 255 | var newPacket:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("PacketEntity", inManagedObjectContext: context) as! NSManagedObject; 256 | var request:NSFetchRequest = NSFetchRequest(entityName: "PacketEntity") 257 | request.returnsObjectsAsFaults = false 258 | 259 | var results:NSArray = context.executeFetchRequest(request, error:nil)! 260 | var didDel = false 261 | if(results.count > 0) { 262 | for result in results { 263 | var resCheck = result as! NSManagedObject 264 | var nameTest = result.valueForKey("name") as! String? 265 | if (nameTest != nil) { 266 | if (nameTest == thename) { 267 | context.deleteObject(resCheck) 268 | didDel = true 269 | } 270 | } 271 | } 272 | 273 | } 274 | if(didDel) { 275 | context.save(nil) 276 | Globals.dataChanged = true 277 | Globals.trafficDataChanged = true 278 | } 279 | 280 | 281 | } 282 | 283 | static func plainASCIItoHex(ascii:String) -> String { 284 | 285 | let data = ascii.dataUsingEncoding(NSUTF8StringEncoding) 286 | if( data != nil) { 287 | return Packet.NSDataToHex(data!) 288 | } else { 289 | return "" 290 | } 291 | 292 | } 293 | 294 | 295 | static func NSDataToHex(data:NSData) -> String { 296 | 297 | let count = data.length / sizeof(UInt8) 298 | var array = [UInt8](count: count, repeatedValue: 0) 299 | // copy bytes into array 300 | data.getBytes(&array, length:count * sizeof(UInt8)) 301 | 302 | var returnString:String = "" 303 | for hex in array { 304 | var st = NSString(format:"%02X", hex) as String 305 | returnString += " " + st 306 | 307 | } 308 | //hexArray.join(" ") 309 | returnString = returnString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString 310 | 311 | return returnString 312 | } 313 | 314 | static func fetchAllFromDBFiltered(traffic:Bool) -> [Packet] { 315 | 316 | var pktArray = fetchAllFromDB() 317 | 318 | 319 | var returnArray:[Packet] = [] 320 | 321 | for pkt in pktArray { 322 | 323 | if(traffic && pkt.inTrafficLog) { 324 | returnArray.append(pkt) 325 | } 326 | if(!traffic && !pkt.inTrafficLog) { 327 | returnArray.append(pkt) 328 | } 329 | 330 | } 331 | 332 | if(traffic) { 333 | returnArray.sort({ ($0.timestamp.compare($1.timestamp) == NSComparisonResult.OrderedDescending) }) 334 | 335 | } else { 336 | 337 | returnArray.sort({ $0.name < $1.name }) 338 | } 339 | 340 | 341 | 342 | return returnArray 343 | 344 | } 345 | 346 | func getUIImage() -> UIImage { 347 | 348 | var returnImage:UIImage 349 | if(isTCP()) { 350 | if(fromIP.lowercaseString != "you") { 351 | returnImage = UIImage(named: "rx_tcp30.png")! 352 | } else { 353 | returnImage = UIImage(named: "tx_tcp30.png")! 354 | } 355 | } else { 356 | if(fromIP.lowercaseString != "you") { 357 | returnImage = UIImage(named: "rx_udp30.png")! 358 | } else { 359 | returnImage = UIImage(named: "tx_udp30.png")! 360 | } 361 | 362 | } 363 | 364 | 365 | return returnImage 366 | 367 | } 368 | 369 | static func fetchAllFromDB() -> [Packet] { 370 | 371 | DLog("fetching...") 372 | 373 | var appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 374 | var context:NSManagedObjectContext = appDel.managedObjectContext! 375 | var newPacket:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("PacketEntity", inManagedObjectContext: context) as! NSManagedObject 376 | var request:NSFetchRequest = NSFetchRequest(entityName: "PacketEntity") 377 | request.returnsObjectsAsFaults = false 378 | 379 | var results:NSArray = context.executeFetchRequest(request, error:nil)! 380 | var resultArray:[Packet] = [] 381 | if(results.count > 0) { 382 | for result in results { 383 | var nameTest = result.valueForKey("name") as! String? 384 | if (nameTest != nil) { 385 | if(count(nameTest!) > 1) { 386 | var pkt = Packet() 387 | pkt.name = result.valueForKey("name") as! String 388 | pkt.hexString = result.valueForKey("hexString") as! String 389 | pkt.port = result.valueForKey("port") as! Int 390 | pkt.fromPort = result.valueForKey("fromPort") as! Int 391 | pkt.fromIP = result.valueForKey("fromIP") as! String 392 | pkt.tcpOrUdp = result.valueForKey("tcpOrUdp") as! String 393 | pkt.toIP = result.valueForKey("toIP") as! String 394 | pkt.inTrafficLog = result.valueForKey("inTrafficLog") as! Bool 395 | pkt.timestamp = result.valueForKey("timestamp") as! NSDate 396 | pkt.error = result.valueForKey("error") as! String 397 | resultArray.append(pkt) 398 | } 399 | } 400 | } 401 | } 402 | 403 | 404 | resultArray.sort({ $0.name > $1.name }) 405 | 406 | return resultArray 407 | 408 | } 409 | 410 | func save() { 411 | 412 | let namesize = count(self.name) 413 | if (namesize < 1) { 414 | DLog("Not saving") 415 | return 416 | } 417 | 418 | //delete if exists 419 | Packet.delete(name) 420 | 421 | var appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 422 | var context:NSManagedObjectContext = appDel.managedObjectContext! 423 | var newPacket:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("PacketEntity", inManagedObjectContext: context) as! NSManagedObject 424 | newPacket.setValue(self.name, forKey: "name") 425 | newPacket.setValue(self.hexString, forKey: "hexString") 426 | newPacket.setValue(self.port, forKey: "port") 427 | newPacket.setValue(self.fromIP, forKey: "fromIP") 428 | newPacket.setValue(self.fromPort, forKey: "fromPort") 429 | newPacket.setValue(self.tcpOrUdp, forKey: "tcpOrUdp") 430 | newPacket.setValue(self.toIP, forKey: "toIP") 431 | newPacket.setValue(self.inTrafficLog, forKey: "inTrafficLog") 432 | newPacket.setValue(self.timestamp, forKey: "timestamp") 433 | newPacket.setValue(self.error, forKey: "error") 434 | if(self.inTrafficLog) { 435 | Globals.trafficDataChanged = true 436 | } else { 437 | Globals.dataChanged = true 438 | } 439 | context.save(nil) 440 | println(newPacket) 441 | 442 | 443 | } 444 | 445 | func isTCP() -> Bool { 446 | if(tcpOrUdp.uppercaseString == "TCP") { 447 | return true; 448 | } else { 449 | return false; 450 | } 451 | } 452 | 453 | func isUDP() -> Bool { 454 | return !isTCP() 455 | } 456 | 457 | 458 | var description: String { 459 | return "name = \(name), toIP=\(toIP):\(port) data = \(hexString)" 460 | } 461 | 462 | var nsData: NSData { 463 | get { 464 | 465 | var mystring = "" 466 | var result : UInt32 = 0 467 | var byteArray:[UInt8] = [] 468 | let hexArray:[String] = split(hexString) {$0 == " "} 469 | for val in hexArray { 470 | let scanner = NSScanner(string: val) 471 | if scanner.scanHexInt(&result) { 472 | byteArray.append(UInt8(result & 0xFF)) 473 | } 474 | } 475 | 476 | let data: NSData = NSData(bytes: byteArray, length: byteArray.count) 477 | return data 478 | } 479 | } 480 | 481 | 482 | var asciiString: String { 483 | get { 484 | return Packet.hexToASCII(hexString) 485 | } 486 | 487 | set { 488 | hexString = Packet.asciiToHex(newValue) 489 | } 490 | 491 | } 492 | 493 | } 494 | -------------------------------------------------------------------------------- /Packet Sender/PacketCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PacketCell.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 1/29/15. 6 | // Copyright (c) 2015 Dan Nagle. All rights reserved. 7 | // 8 | 9 | 10 | import Foundation 11 | import UIKit 12 | 13 | class PacketCell: UITableViewCell { 14 | 15 | @IBOutlet weak var pktLabel: UILabel! 16 | @IBOutlet weak var pktImage: UIImageView! 17 | 18 | @IBOutlet weak var detailsLabel: UILabel! 19 | func forceCompile() -> Bool { 20 | return true; 21 | } 22 | 23 | 24 | override func awakeFromNib() { 25 | super.awakeFromNib() 26 | // Initialization code 27 | } 28 | 29 | override func setSelected(selected: Bool, animated: Bool) { 30 | super.setSelected(selected, animated: animated) 31 | 32 | // Configure the view for the selected state 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Packet Sender/PacketDetailsController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PacketDetailsController.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 1/29/15. 6 | // Copyright (c) 2015 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | 11 | import Foundation 12 | 13 | import UIKit 14 | import QuartzCore 15 | 16 | class PacketDetailsController: UITableViewController, UITextViewDelegate, UITextFieldDelegate { 17 | 18 | @IBOutlet weak var nameEdit: UITextField! 19 | @IBOutlet weak var ipEdit: UITextField! 20 | @IBOutlet weak var portEdit: UITextField! 21 | @IBOutlet weak var tcpOrUdpSwitch: UISegmentedControl! 22 | @IBOutlet weak var asciiTextView: UITextView! 23 | @IBOutlet weak var hexTextView: UITextView! 24 | 25 | var packetDetail:Packet = Packet(); 26 | 27 | 28 | //TODO: put back in the edit hooks to auto-translate the hex/ascii changes! 29 | 30 | 31 | @IBAction func saveBtnClick() { 32 | DLog("Save clicked") 33 | 34 | var pkt = buildPacket() 35 | pkt.save() 36 | 37 | //[self.navigationController popViewControllerAnimated:TRUE]; 38 | 39 | self.navigationController?.popViewControllerAnimated(true) 40 | 41 | 42 | } 43 | 44 | @IBAction func sendBtnClick() { 45 | DLog("Send clicked") 46 | 47 | var pkt = buildPacket() 48 | DLog("Need to send " + pkt.description) 49 | Globals.psnetwork.sendPacket(&pkt) 50 | 51 | var msgBuild = pkt.tcpOrUdp.uppercaseString + " " 52 | msgBuild = msgBuild + pkt.toIP + ":" + String(pkt.port) 53 | 54 | if(pkt.error.isEmpty) { 55 | self.view.makeToast(message: msgBuild, duration: 2, position: HRToastPositionCenter, title: "Sent") 56 | } else { 57 | self.view.makeToast(message: pkt.error, duration: 4, position: HRToastPositionCenter, title: "Error") 58 | } 59 | 60 | 61 | 62 | } 63 | 64 | 65 | 66 | 67 | func buildPacket() -> Packet { 68 | 69 | var pkt = Packet() 70 | pkt.name = nameEdit!.text 71 | pkt.toIP = ipEdit!.text 72 | let intTest = portEdit!.text.toInt() 73 | if(intTest == nil) { 74 | pkt.port = 1 75 | } else { 76 | pkt.port = intTest! 77 | } 78 | 79 | pkt.hexString = hexTextView!.text 80 | 81 | if(tcpOrUdpSwitch?.selectedSegmentIndex == 0) { 82 | pkt.tcpOrUdp = "tcp" 83 | } else { 84 | pkt.tcpOrUdp = "udp" 85 | } 86 | 87 | 88 | return pkt 89 | } 90 | 91 | 92 | override func viewDidLoad() { 93 | super.viewDidLoad() 94 | 95 | // Do any additional setup after loading the view. 96 | DLog("loaded packet...") 97 | 98 | // Do any additional setup after loading the view. 99 | DLog("Loaded Packet Details") 100 | nameEdit.text = packetDetail.name 101 | ipEdit.text = packetDetail.toIP 102 | portEdit.text = String(packetDetail.port) 103 | hexTextView.text = packetDetail.hexString 104 | asciiTextView.text = packetDetail.asciiString 105 | 106 | if(packetDetail.isTCP()) { 107 | tcpOrUdpSwitch.selectedSegmentIndex = 0; 108 | } else { 109 | tcpOrUdpSwitch.selectedSegmentIndex = 1; 110 | } 111 | 112 | 113 | } 114 | 115 | 116 | 117 | 118 | func textViewDidChange(textView: UITextView) { //Handle the text changes 119 | 120 | if(textView.restorationIdentifier! != "hexEditID") { 121 | textViewDidEndEditing(textView) 122 | } 123 | 124 | } 125 | 126 | func textFieldDidEndEditing(textField: UITextField) { 127 | 128 | if(textField.restorationIdentifier! == "nameID") { 129 | DLog("Verification of name field") 130 | } 131 | if(textField.restorationIdentifier! == "ipID") { 132 | DLog("Verification of ip field") 133 | } 134 | if(textField.restorationIdentifier! == "portID") { 135 | DLog("Verification of port field") 136 | 137 | let intTest = portEdit!.text.toInt() 138 | if(intTest == nil) { 139 | DLog("Verification of port field FAILED") 140 | portEdit?.textColor = UIColor.redColor() 141 | } else { 142 | portEdit?.textColor = UIColor.blackColor() 143 | } 144 | } 145 | } 146 | 147 | func textViewDidEndEditing(textView: UITextView) { 148 | 149 | if(textView.restorationIdentifier! == "hexEditID") { 150 | DLog("Text Changed Finished Hex") 151 | asciiTextView.text = Packet.hexToASCII(textView.text) 152 | hexTextView.text = Packet.asciiToHex(asciiTextView.text) 153 | 154 | } else { 155 | DLog("Text Changed Finished Ascii") 156 | 157 | hexTextView.text = Packet.asciiToHex(textView.text) 158 | 159 | } 160 | } 161 | 162 | 163 | 164 | 165 | 166 | override func didReceiveMemoryWarning() { 167 | super.didReceiveMemoryWarning() 168 | // Dispose of any resources that can be recreated. 169 | } 170 | 171 | 172 | override func viewWillAppear(animated: Bool) { 173 | super.viewWillAppear(false); 174 | DLog("Reloaded table") 175 | 176 | } 177 | 178 | 179 | 180 | } 181 | -------------------------------------------------------------------------------- /Packet Sender/PacketNetwork.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PacketNetwork.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/20/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | 11 | import Foundation 12 | import CFNetwork 13 | import CoreFoundation 14 | import QuartzCore 15 | 16 | 17 | class PacketNetwork: NSObject, Printable { 18 | 19 | var udpSocket:GCDAsyncUdpSocket! 20 | var tcpSocket:GCDAsyncSocket! 21 | var connectedSockets:NSMutableArray 22 | 23 | //var uSocket = GCDAsyncUdpSocket(self, delegateQueue: dispatch_get_main_queue()) 24 | 25 | override init() { 26 | DLog("Packe Network Init") 27 | connectedSockets = NSMutableArray(capacity: 1) 28 | super.init() 29 | 30 | //udpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 31 | 32 | //enableServerSwitch?.addTarget(self, action: Selector("stateChanged:"), forControlEvents: UIControlEvents.ValueChanged) 33 | 34 | udpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 35 | tcpSocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 36 | 37 | let serversOn = getSavedServersOn() 38 | 39 | if(serversOn) { 40 | 41 | 42 | startServers() 43 | 44 | 45 | 46 | } else { 47 | 48 | stopServers() 49 | 50 | } 51 | 52 | 53 | 54 | 55 | } 56 | func getIFAddresses() -> [String] { 57 | var addresses = [String]() 58 | 59 | // Get list of all interfaces on the local machine: 60 | var ifaddr : UnsafeMutablePointer = nil 61 | if getifaddrs(&ifaddr) == 0 { 62 | 63 | // For each interface ... 64 | for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) { 65 | let flags = Int32(ptr.memory.ifa_flags) 66 | var addr = ptr.memory.ifa_addr.memory 67 | 68 | // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. 69 | if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { 70 | if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) { 71 | 72 | // Convert interface address to a human readable string: 73 | var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0) 74 | if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count), 75 | nil, socklen_t(0), NI_NUMERICHOST) == 0) { 76 | if let address = String.fromCString(hostname) { 77 | addresses.append(address) 78 | } 79 | } 80 | } 81 | } 82 | } 83 | freeifaddrs(ifaddr) 84 | } 85 | 86 | return addresses 87 | } 88 | 89 | func restartServers() { 90 | 91 | stopServers() 92 | startServers() 93 | } 94 | 95 | 96 | func stopServers() { 97 | 98 | udpSocket.setDelegate(nil, delegateQueue: dispatch_get_main_queue()) 99 | udpSocket.close() 100 | udpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 101 | 102 | 103 | tcpSocket.setDelegate(nil, delegateQueue: dispatch_get_main_queue()) 104 | tcpSocket.disconnect() 105 | tcpSocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 106 | 107 | } 108 | 109 | func startServers() { 110 | 111 | var error: NSError? 112 | 113 | let tcpPort = UInt16(getSavedTCPport()) 114 | let udpPort = UInt16(getSavedUDPport()) 115 | 116 | 117 | if (udpSocket.bindToPort(udpPort, error: &error)) { 118 | DLog("UDP Port success. It is " + String(udpSocket.localPort())) 119 | if(udpSocket.beginReceiving(&error)) { 120 | DLog("Server started!") 121 | Globals.udpServerError = "Binded to \(udpSocket.localPort())" 122 | } else { 123 | DLog("NOT RECEIVING!") 124 | Globals.udpServerError = "Not receiving" 125 | } 126 | } else { 127 | DLog("Port failed. Attempted \(udpPort). Got " + String(udpSocket.localPort())) 128 | DLog(error!.localizedDescription) 129 | Globals.udpServerError = error!.localizedDescription 130 | 131 | } 132 | 133 | if(tcpSocket.acceptOnPort(tcpPort, error: &error)) { 134 | DLog("TCP Port success. It is " + String(tcpSocket.localPort)) 135 | Globals.tcpServerError = "Binded to \(tcpSocket.localPort)" 136 | 137 | } else { 138 | DLog("Port failed. Attempted \(tcpPort). It is " + String(tcpSocket.localPort)) 139 | DLog(error!.localizedDescription) 140 | Globals.tcpServerError = error!.localizedDescription 141 | 142 | 143 | } 144 | 145 | 146 | 147 | } 148 | 149 | func storeServersOn(serversOn:Bool) { 150 | 151 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 152 | defaults.setObject(serversOn, forKey: "serversOn") 153 | defaults.synchronize() 154 | 155 | } 156 | 157 | 158 | func getSavedServersOn() -> Bool { 159 | 160 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 161 | if let serversOn = defaults.objectForKey("serversOn") as? Bool { 162 | if serversOn { 163 | return true 164 | } else { 165 | return false 166 | } 167 | } else { 168 | return true 169 | } 170 | 171 | } 172 | 173 | 174 | func storeUDPPort(udpPort:Int) { 175 | 176 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 177 | defaults.setObject(udpPort, forKey: "udpPort") 178 | defaults.synchronize() 179 | 180 | } 181 | 182 | func storeTCPPort(tcpPort:Int) { 183 | 184 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 185 | defaults.setObject(tcpPort, forKey: "tcpPort") 186 | defaults.synchronize() 187 | } 188 | 189 | 190 | 191 | func getSavedUDPport() -> Int { 192 | 193 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 194 | if let tcpInt = defaults.objectForKey("udpPort") as? Int { 195 | 196 | if (tcpInt >= 0 && tcpInt < 65000) { 197 | return tcpInt 198 | } 199 | } 200 | return 55056; 201 | } 202 | 203 | 204 | func getSavedTCPport() -> Int { 205 | 206 | var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() 207 | if let udpPort = defaults.objectForKey("tcpPort") as? Int { 208 | 209 | if (udpPort >= 0 && udpPort < 65000) { 210 | return udpPort 211 | } 212 | } 213 | return 55056; 214 | } 215 | 216 | func start() { 217 | DLog("Starting...") 218 | } 219 | 220 | 221 | func saveTrafficPacket(pkt:Packet) { 222 | 223 | saveTrafficData(pkt.nsData, fromIP:pkt.fromIP, fromPort:pkt.fromPort, toIP:pkt.toIP, toPort:pkt.port, tcpOrUdp:pkt.tcpOrUdp); 224 | 225 | } 226 | 227 | func saveTrafficData(data:NSData, fromIP:String, fromPort:Int, toIP:String, toPort:Int, tcpOrUdp:String) { 228 | 229 | var pkt = Packet() 230 | pkt.tcpOrUdp = tcpOrUdp 231 | pkt.hexString = Packet.NSDataToHex(data) 232 | DLog("Data from \(fromIP), port \(fromPort) : \(pkt.asciiString)") 233 | 234 | let date = NSDate() 235 | let timestamp = date.timeIntervalSince1970 236 | var t:CFTimeInterval = CACurrentMediaTime() - Globals.timestamp; 237 | pkt.inTrafficLog = true 238 | pkt.name = String(t.description) + timestamp.description 239 | pkt.timestamp = NSDate() 240 | 241 | pkt.fromIP = fromIP; 242 | pkt.port = toPort; 243 | pkt.fromPort = fromPort; 244 | pkt.toIP = toIP; 245 | 246 | pkt.save() 247 | Globals.trafficDataChanged = true 248 | 249 | } 250 | 251 | 252 | func send(message:String){ 253 | let data = message.dataUsingEncoding(NSUTF8StringEncoding) 254 | udpSocket.sendData(data, toHost: "localhost", port: 55056, withTimeout: 2, tag: 0) 255 | saveTrafficData(data!, fromIP: "You", fromPort: Int(udpSocket.localPort()), 256 | toIP: "localhost", toPort: 55056, tcpOrUdp:"udp") 257 | } 258 | 259 | 260 | 261 | 262 | func sendPacket(inout pkt:Packet) { 263 | DLog("Sending " + pkt.name) 264 | 265 | 266 | if(pkt.isUDP()) { 267 | udpSocket.sendData(pkt.nsData, toHost: pkt.toIP, port: UInt16(pkt.port), withTimeout: 200, tag: 0) 268 | pkt.fromIP = "You" 269 | pkt.fromPort = Int(udpSocket.localPort()) 270 | saveTrafficPacket(pkt) 271 | 272 | } else { 273 | 274 | var inputStream: NSInputStream? 275 | var outputStream: NSOutputStream? 276 | 277 | let data = pkt.nsData 278 | NSStream.getStreamsToHostWithName(pkt.toIP, port: pkt.port, inputStream: &inputStream, outputStream: &outputStream) 279 | 280 | outputStream!.open() 281 | inputStream!.open() 282 | 283 | 284 | let startTime = NSDate() 285 | 286 | while (outputStream?.streamStatus == NSStreamStatus.Opening) { 287 | var timeCompare = startTime.dateByAddingTimeInterval(5) 288 | 289 | if (timeCompare.compare(NSDate()) == NSComparisonResult.OrderedAscending) { 290 | DLog("Failed to open socket...") 291 | break; 292 | 293 | } 294 | 295 | //DLog("Wait while opening...") 296 | } 297 | 298 | switch(outputStream!.streamStatus) { 299 | case NSStreamStatus.NotOpen : 300 | DLog("NotOpen") 301 | case NSStreamStatus.Opening : 302 | DLog("Opening") 303 | pkt.error = "Connection timeout." 304 | case NSStreamStatus.Open : 305 | DLog("Open") 306 | case NSStreamStatus.Reading : 307 | DLog("Reading") 308 | case NSStreamStatus.Writing : 309 | DLog("Writing") 310 | case NSStreamStatus.AtEnd : 311 | DLog("AtEnd") 312 | case NSStreamStatus.Closed : 313 | DLog("Closed") 314 | case NSStreamStatus.Error : 315 | DLog("Error") 316 | pkt.error = "Connection error, likely refused." 317 | 318 | } 319 | 320 | pkt.fromIP = "You" 321 | pkt.fromPort = Int(tcpSocket.localPort) 322 | 323 | 324 | if(outputStream?.streamStatus == NSStreamStatus.Open) { 325 | DLog("Successfully opened. Send data") 326 | outputStream!.write(UnsafePointer(data.bytes), maxLength: data.length) 327 | 328 | outputStream!.close() 329 | } else { 330 | DLog("Did not open. Probably an error...") 331 | 332 | //TODO: need to report meaningful errors. 333 | 334 | 335 | if(pkt.error.isEmpty) { 336 | pkt.error = "Send Error" 337 | } 338 | 339 | } 340 | if(inputStream?.streamStatus == NSStreamStatus.Open) { 341 | inputStream!.close() 342 | } 343 | 344 | saveTrafficPacket(pkt) 345 | 346 | 347 | } 348 | 349 | } 350 | 351 | func connectTestUDP() { 352 | 353 | let mystring = "Write this UDP!" 354 | let data: NSData = mystring.dataUsingEncoding(NSUTF8StringEncoding)! 355 | var mySocket:GCDAsyncUdpSocket = GCDAsyncUdpSocket() 356 | mySocket.sendData(data, toHost: "192.168.1.92", port: 55056, withTimeout: 200, tag: 0) 357 | 358 | } 359 | 360 | 361 | func socket (socketDidDisconnect: GCDAsyncSocket!, error withError: NSError!) { 362 | DLog("Disconnected socket") 363 | connectedSockets.removeObject(socketDidDisconnect) 364 | } 365 | 366 | 367 | //- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket; 368 | func socket (socket : GCDAsyncSocket!, didAcceptNewSocket newSocket:GCDAsyncSocket!) { 369 | 370 | DLog("Connected Sock count is \(connectedSockets.count)") 371 | DLog("Got sock from \(newSocket.connectedHost), port \(newSocket.connectedPort)") 372 | newSocket.setDelegate(self, delegateQueue: dispatch_get_main_queue()) 373 | newSocket.readDataWithTimeout(-1, tag: 0) 374 | 375 | connectedSockets.addObject(newSocket) 376 | DLog("Connected Sock count is \(connectedSockets.count)") 377 | 378 | 379 | 380 | } 381 | 382 | // receiver device 383 | // - (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 384 | func socket(socket: GCDAsyncSocket!, didReadPartialDataOfLength partialLength: Int, withTag tag: Int) { 385 | DLog("Got partial") 386 | 387 | } 388 | 389 | func socket(socket : GCDAsyncSocket, didReadData data:NSData, withTag tag:UInt16) 390 | { 391 | var pkt = Packet() 392 | pkt.hexString = Packet.NSDataToHex(data) 393 | DLog("Data from \(socket.connectedHost), port \(socket.connectedPort) : \(pkt.asciiString)") 394 | 395 | pkt.fromIP = socket.connectedHost 396 | pkt.port = Int(socket.localPort) 397 | pkt.fromPort = Int(socket.connectedPort) 398 | pkt.toIP = "You" 399 | saveTrafficPacket(pkt) 400 | 401 | } 402 | 403 | 404 | 405 | func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) { 406 | 407 | var host: NSString? 408 | var port1: UInt16 = 0 409 | GCDAsyncUdpSocket.getHost(&host, port: &port1, fromAddress: address) 410 | DLog("Packet From \(host!)") 411 | 412 | saveTrafficData(data!, fromIP: host! as String, fromPort: Int(port1), toIP: "You", toPort: Int(sock.localPort()), tcpOrUdp: "udp") 413 | 414 | 415 | } 416 | 417 | 418 | 419 | func udpSocket(sock: GCDAsyncUdpSocket!, didNotConnect error: NSError!) { 420 | DLog("yes") 421 | DLog(error!.localizedDescription) 422 | } 423 | 424 | func udpSocket(sock: GCDAsyncUdpSocket!, didNotSendDataWithTag tag: Int, dueToError error: NSError!) { 425 | DLog("yes") 426 | DLog(error!.localizedDescription) 427 | 428 | } 429 | 430 | func udpSocket(sock: GCDAsyncUdpSocket!, didSendDataWithTag tag: Int) { 431 | DLog("sent packet") 432 | } 433 | 434 | func udpSocketDidClose(sock: GCDAsyncUdpSocket!, withError error: NSError!) { 435 | DLog("yes") 436 | } 437 | 438 | 439 | 440 | func connectTestTCP() { 441 | var inputStream: NSInputStream? 442 | var outputStream: NSOutputStream? 443 | 444 | DLog("attempting connect") 445 | NSStream.getStreamsToHostWithName("192.168.1.92", port: 55056, inputStream: &inputStream, outputStream: &outputStream) 446 | DLog("Did I connect?") 447 | 448 | let mystring = "Write this TCP!" 449 | outputStream!.open() 450 | inputStream!.open() 451 | let data: NSData = mystring.dataUsingEncoding(NSUTF8StringEncoding)! 452 | DLog("Did I write?") 453 | outputStream!.write(UnsafePointer(data.bytes), maxLength: data.length) 454 | outputStream!.close() 455 | inputStream!.close() 456 | DLog("Did I close?") 457 | } 458 | 459 | 460 | override var description: String { 461 | return "packetnetwork boom" 462 | } 463 | 464 | } 465 | -------------------------------------------------------------------------------- /Packet Sender/Packet_Sender-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // obj_includes.h 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/26/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | 9 | #ifndef Packet_Sender_obj_includes_h 10 | 11 | 12 | #import "GCDAsyncSocket.h" 13 | #import "GCDAsyncUdpSocket.h" 14 | 15 | #define Packet_Sender_obj_includes_h 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Packet Sender/Packet_Sender.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Packet_Sender.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Packet Sender/Packet_Sender.xcdatamodeld/Packet_Sender.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Packet Sender/PacketsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PacketsViewController.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | 11 | import UIKit 12 | import CoreData 13 | 14 | class PacketsViewController: UITableViewController, GCDAsyncUdpSocketDelegate { 15 | 16 | var pktArray = Packet.fetchAllFromDBFiltered(false) 17 | 18 | 19 | @IBAction func addBtnClick() { 20 | DLog("Add clicked") 21 | 22 | performSegueWithIdentifier("PacketDetailNewSegue",sender: self) 23 | 24 | 25 | } 26 | 27 | 28 | override func viewDidLoad() { 29 | super.viewDidLoad() 30 | 31 | let hex1 = "73 0d 20 69 0a 73 20 66 72 6f 6d 20 70 04 61 63 5c 6b 65 74" 32 | let ascii1 = "s\\r i\\ns from p\\04ac\\\\ket" 33 | 34 | Packet.parserUnitTest(ascii1, hex: hex1) 35 | 36 | let hex2 = "6e 61 6d 20 3d 20 2c 20 64 61 74 61 20 3d 20 99 88 aa cc" 37 | let ascii2 = "nam = , data = \\99\\88\\aa\\cc" 38 | 39 | Packet.parserUnitTest(ascii2, hex: hex2) 40 | 41 | let ascii3 = "test f\\rro\\nm s\\88imulator" 42 | let hex3 = "74 65 73 74 20 66 0d 72 6f 0a 6d 20 73 88 69 6d 75 6c 61 74 6f 72" 43 | 44 | Packet.parserUnitTest(ascii3, hex: hex3) 45 | 46 | //force load of PacketNetwork 47 | Globals.psnetwork.start() 48 | 49 | 50 | // Uncomment the following line to preserve selection between presentations 51 | // self.clearsSelectionOnViewWillAppear = false 52 | 53 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 54 | 55 | self.navigationItem.leftBarButtonItem = self.editButtonItem() 56 | let myIPAddress = Globals.psnetwork.getIFAddresses() 57 | 58 | var myIP = "Unknown" 59 | if (myIPAddress.count > 0) { 60 | myIP = myIPAddress.first! 61 | } 62 | 63 | self.view.makeToast(message: "IP Address", duration: 3, position: HRToastPositionCenter, title: myIP) 64 | 65 | 66 | 67 | } 68 | 69 | override func viewWillAppear(animated: Bool) { 70 | super.viewWillAppear(false); 71 | if(Globals.dataChanged) { 72 | pktArray = Packet.fetchAllFromDBFiltered(false) 73 | self.tableView.reloadData() 74 | Globals.dataChanged = false 75 | DLog("Reloaded table") 76 | } else { 77 | DLog("Did not reload") 78 | } 79 | 80 | } 81 | 82 | 83 | 84 | 85 | override func didReceiveMemoryWarning() { 86 | super.didReceiveMemoryWarning() 87 | // Dispose of any resources that can be recreated. 88 | } 89 | 90 | // MARK: - Table Headers and Footers 91 | 92 | override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 93 | return "Packets" 94 | } 95 | 96 | 97 | // MARK: - Table view data source 98 | 99 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 100 | // #warning Potentially incomplete method implementation. 101 | // Return the number of sections. 102 | return 1 103 | } 104 | 105 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 106 | // #warning Incomplete method implementation. 107 | // Return the number of rows in the section. 108 | return pktArray.count 109 | } 110 | 111 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> PacketCell { 112 | let cell = tableView.dequeueReusableCellWithIdentifier("pktReuseID", forIndexPath: indexPath) as! PacketCell 113 | 114 | pktArray[indexPath.row].fromIP = "You" 115 | 116 | cell.pktLabel.text = pktArray[indexPath.row].name 117 | cell.detailsLabel.text = " to " + (pktArray[indexPath.row].toIP) + ":" + String(pktArray[indexPath.row].port) 118 | cell.pktImage.image = pktArray[indexPath.row].getUIImage() 119 | 120 | return cell 121 | } 122 | 123 | // Override to support conditional editing of the table view. 124 | override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 125 | // Return NO if you do not want the specified item to be editable. 126 | return true 127 | } 128 | 129 | // Override to support editing the table view. 130 | override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 131 | 132 | if editingStyle == .Delete { 133 | // Delete the row from the data source 134 | DLog("Attempting delete") 135 | Packet.delete(pktArray[indexPath.row].name) 136 | pktArray = Packet.fetchAllFromDBFiltered(false) 137 | DLog("Did delete work?") 138 | 139 | tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 140 | 141 | } else if editingStyle == .Insert { 142 | 143 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 144 | 145 | } 146 | 147 | } 148 | 149 | /* 150 | // Override to support rearranging the table view. 151 | override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { 152 | 153 | } 154 | */ 155 | 156 | /* 157 | // Override to support conditional rearranging of the table view. 158 | override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { 159 | // Return NO if you do not want the item to be re-orderable. 160 | return true 161 | } 162 | */ 163 | 164 | // MARK: - Navigation 165 | 166 | 167 | 168 | 169 | // In a storyboard-based application, you will often want to do a little preparation before navigation 170 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 171 | // Get the new view controller using [segue destinationViewController]. 172 | // Pass the selected object to the new view controller. 173 | if (segue.identifier == "packetNewSegue") { 174 | 175 | DLog("Load the New Packet Details"); 176 | 177 | // var vc:PacketDetailViewController = segue.destinationViewController as PacketDetailViewController 178 | 179 | var vc:PacketDetailsController = segue.destinationViewController as! PacketDetailsController 180 | 181 | vc.packetDetail = Packet() 182 | /* 183 | vc.packetDetail.toIP = "192.168.1.92" 184 | vc.packetDetail.port = 55056 185 | vc.packetDetail.hexString = "74 65 73 74 20 66 0d 72 6f 0a 6d 20 73 88 69 6d 75 6c 61 74 6f 72" 186 | */ 187 | 188 | } else if (segue.identifier == "packetShowSegue") { 189 | // pass data to next view 190 | DLog("Load the Packet Details"); 191 | 192 | var indexPath = self.tableView.indexPathForSelectedRow() //get index of data for selected row 193 | var vc:PacketDetailsController = segue.destinationViewController as! PacketDetailsController 194 | vc.packetDetail = pktArray[indexPath!.item] 195 | 196 | 197 | } else { 198 | DLog("ID unknown or nil"); 199 | } 200 | 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /Packet Sender/SettingsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewController.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | 11 | import UIKit 12 | 13 | class SettingsViewController: UITableViewController, UITextViewDelegate, UITextFieldDelegate { 14 | 15 | 16 | @IBOutlet var tcpPortEdit: UITextField? 17 | 18 | 19 | @IBOutlet var udpPortEdit: UITextField? 20 | 21 | @IBOutlet var enableServerSwitch: UISwitch? 22 | 23 | 24 | @IBOutlet var udpResultsLabel: UILabel! 25 | @IBOutlet var tcpResultsLabel: UILabel! 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | 30 | // Do any additional setup after loading the view. 31 | DLog("loading settings...") 32 | 33 | 34 | 35 | //[yourSwitchObject addTarget:self action:@selector(setState:) forControlEvents:UIControlEventValueChanged]; 36 | 37 | enableServerSwitch?.addTarget(self, action: Selector("stateChanged:"), forControlEvents: UIControlEvents.ValueChanged) 38 | 39 | tcpPortEdit?.addTarget(self, action: Selector("textFieldDidChange:"), forControlEvents: UIControlEvents.EditingChanged) 40 | udpPortEdit?.addTarget(self, action: Selector("textFieldDidChange:"), forControlEvents: UIControlEvents.EditingChanged) 41 | 42 | 43 | doReload() 44 | } 45 | 46 | func restart() { 47 | 48 | Globals.psnetwork.restartServers() 49 | doReload() 50 | 51 | } 52 | 53 | func doReload() { 54 | 55 | DLog("Do reload") 56 | 57 | udpPortEdit?.text = String(Globals.psnetwork.getSavedUDPport()) 58 | 59 | var l = udpPortEdit?.text.lengthOfBytesUsingEncoding(NSASCIIStringEncoding); 60 | 61 | if (l != nil ) { 62 | var i = l! 63 | while i < 5 { 64 | udpPortEdit!.text = " " + udpPortEdit!.text 65 | i = i + 1 66 | } 67 | } 68 | 69 | tcpPortEdit?.text = String(Globals.psnetwork.getSavedTCPport()) 70 | 71 | l = tcpPortEdit?.text.lengthOfBytesUsingEncoding(NSASCIIStringEncoding); 72 | 73 | if (l != nil ) { 74 | var i = l! 75 | while i < 5 { 76 | tcpPortEdit!.text = " " + tcpPortEdit!.text 77 | i = i + 1 78 | } 79 | } 80 | 81 | 82 | enableServerSwitch?.setOn(Globals.psnetwork.getSavedServersOn(), animated: false) 83 | udpResultsLabel.text = "UDP Status: " + Globals.udpServerError 84 | tcpResultsLabel.text = "TCP Status: " + Globals.tcpServerError 85 | 86 | 87 | } 88 | 89 | func stateChanged(switchState: UISwitch) { 90 | var toggle = false 91 | if switchState.on { 92 | DLog("Is ON") 93 | toggle = true 94 | } else { 95 | DLog("Is Off") 96 | toggle = false 97 | } 98 | 99 | Globals.psnetwork.storeServersOn(toggle) 100 | restart() 101 | 102 | 103 | } 104 | 105 | func textFieldDidChange(textField: UITextField!) { 106 | 107 | //DLog("Resize tests...") 108 | 109 | 110 | } 111 | 112 | func textFieldDidEndEditing(textField: UITextField) { 113 | 114 | let intTest = textField.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).toInt() 115 | DLog("Verification of port field: \(intTest)") 116 | if(intTest == nil) { 117 | DLog("Verification of port field FAILED") 118 | textField.textColor = UIColor.redColor() 119 | } else { 120 | textField.textColor = UIColor.blackColor() 121 | } 122 | 123 | let tcpInt = tcpPortEdit!.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).toInt() 124 | let udpInt = udpPortEdit!.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).toInt() 125 | 126 | if (tcpInt != nil && udpInt != nil) { 127 | 128 | DLog("TCP port is " + String(tcpInt!)) 129 | DLog("UDP port is " + String(udpInt!)) 130 | 131 | Globals.psnetwork.storeTCPPort(tcpInt!) 132 | Globals.psnetwork.storeUDPPort(udpInt!) 133 | restart() 134 | doReload() 135 | 136 | 137 | } 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | } 146 | 147 | 148 | override func didReceiveMemoryWarning() { 149 | super.didReceiveMemoryWarning() 150 | // Dispose of any resources that can be recreated. 151 | } 152 | 153 | 154 | override func viewWillAppear(animated: Bool) { 155 | super.viewWillAppear(false); 156 | DLog("Reloaded table") 157 | 158 | } 159 | 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /Packet Sender/TrafficViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrafficViewCell.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/30/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | import Foundation 11 | import UIKit 12 | 13 | class TrafficViewCell: UITableViewCell { 14 | 15 | @IBOutlet weak var customSubLabel: UILabel! 16 | @IBOutlet weak var customLabel: UILabel! 17 | @IBOutlet weak var customRightLabel: UILabel! 18 | 19 | @IBOutlet weak var customImage: UIImageView! 20 | 21 | 22 | func forceCompile() -> Bool { 23 | return true; 24 | } 25 | 26 | @IBOutlet var cellLabel:UILabel! 27 | 28 | override func awakeFromNib() { 29 | super.awakeFromNib() 30 | // Initialization code 31 | } 32 | 33 | override func setSelected(selected: Bool, animated: Bool) { 34 | super.setSelected(selected, animated: animated) 35 | 36 | // Configure the view for the selected state 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Packet Sender/TrafficViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrafficViewController.swift 3 | // Packet Sender 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | // Licensed MIT: https://github.com/dannagle/PacketSender-iOS 9 | 10 | import UIKit 11 | 12 | 13 | 14 | 15 | //TODO: need to report errors. 16 | 17 | class TrafficViewController: UITableViewController { 18 | 19 | var pktArray = Packet.fetchAllFromDBFiltered(true) 20 | 21 | 22 | @IBAction func clearBtnClick() { 23 | DLog("Clear clicked") 24 | for pkt in pktArray { 25 | Packet.delete(pkt.name) 26 | } 27 | pktArray.removeAll(keepCapacity: false) 28 | self.tableView.reloadData() 29 | 30 | } 31 | 32 | 33 | @IBAction func saveBtnClick() { 34 | DLog("Save clicked") 35 | 36 | var indexPath = self.tableView.indexPathForSelectedRow() //get index of data for selected row 37 | 38 | if(indexPath == nil) { 39 | return; 40 | } 41 | let packetDetail = pktArray[indexPath!.item] 42 | 43 | var inputTextField: UITextField? 44 | let savePrompt = UIAlertController(title: "Save packet", message: "Name for the new packet.", preferredStyle: UIAlertControllerStyle.Alert) 45 | 46 | savePrompt.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: nil)) 47 | savePrompt.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (action) -> Void in 48 | // Now do whatever you want with inputTextField (remember to unwrap the optional) 49 | 50 | let newname = inputTextField?.text 51 | 52 | 53 | if(newname != nil) { 54 | DLog("Need to save \(packetDetail) as \(newname!)") 55 | var savePacket = Packet() 56 | savePacket.hexString = packetDetail.hexString 57 | 58 | if (packetDetail.fromIP.lowercaseString == "you" || packetDetail.fromIP == "127.0.0.1" 59 | || packetDetail.fromIP == "::1" || packetDetail.fromIP == "localhost" ) 60 | { 61 | DLog("No swap") 62 | savePacket.toIP = packetDetail.toIP 63 | savePacket.port = packetDetail.port 64 | 65 | } else { 66 | 67 | DLog("Do swap") 68 | savePacket.toIP = packetDetail.fromIP 69 | savePacket.port = packetDetail.fromPort 70 | 71 | } 72 | 73 | savePacket.name = newname! 74 | savePacket.tcpOrUdp = packetDetail.tcpOrUdp 75 | savePacket.inTrafficLog = false 76 | savePacket.save() 77 | 78 | } else { 79 | DLog("Cancel save") 80 | } 81 | 82 | })) 83 | savePrompt.addTextFieldWithConfigurationHandler({(textField: UITextField!) in 84 | textField.placeholder = "Packet Name" 85 | inputTextField = textField 86 | }) 87 | 88 | presentViewController(savePrompt, animated: true, completion: nil); 89 | 90 | 91 | 92 | 93 | } 94 | 95 | 96 | override func viewDidLoad() { 97 | super.viewDidLoad() 98 | DLog("Traffic size is " + String(pktArray.count)) 99 | 100 | // Do any additional setup after loading the view. 101 | var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: Selector("timerTimeout"), userInfo: nil, repeats: true) 102 | 103 | } 104 | 105 | 106 | func timerTimeout() { 107 | 108 | if(Globals.trafficDataChanged) { 109 | DLog("Reloaded table") 110 | pktArray = Packet.fetchAllFromDBFiltered(true) 111 | Globals.trafficDataChanged = false 112 | self.tableView.reloadData() 113 | } 114 | } 115 | 116 | override func didReceiveMemoryWarning() { 117 | super.didReceiveMemoryWarning() 118 | // Dispose of any resources that can be recreated. 119 | } 120 | 121 | // MARK: - Table Headers and Footers 122 | 123 | override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 124 | return "Log" 125 | } 126 | 127 | 128 | // MARK: - Table view data source 129 | 130 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 131 | // #warning Potentially incomplete method implementation. 132 | // Return the number of sections. 133 | return 1 134 | } 135 | 136 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 137 | // #warning Incomplete method implementation. 138 | // Return the number of rows in the section. 139 | return pktArray.count 140 | } 141 | 142 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> TrafficViewCell { 143 | let cell = tableView.dequeueReusableCellWithIdentifier("tablepktReuseID", forIndexPath: indexPath) as! TrafficViewCell 144 | 145 | // Configure the cell... 146 | //[ImageViewName setImage:[UIImage imageNamed: @"ImageName.png"]]; 147 | 148 | cell.customImage.image = pktArray[indexPath.row].getUIImage() 149 | cell.customSubLabel?.text = pktArray[indexPath.row].hexString 150 | cell.customLabel?.text = pktArray[indexPath.row].asciiString 151 | var dateFormatter = NSDateFormatter() 152 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS" 153 | dateFormatter.dateFormat = "HH:mm:ss.SSS" 154 | if(cell.customRightLabel != nil) { 155 | 156 | var str = "" 157 | 158 | if (pktArray[indexPath.row].isTCP()) { 159 | //str = "TCP: " 160 | } else { 161 | //str = "UDP: " 162 | } 163 | 164 | str = str + "\(pktArray[indexPath.row].fromIP):\(pktArray[indexPath.row].fromPort) -> " 165 | str = str + "\(pktArray[indexPath.row].toIP):\(pktArray[indexPath.row].port) " 166 | str = str + dateFormatter.stringFromDate(pktArray[indexPath.row].timestamp) 167 | 168 | cell.customRightLabel!.text! = str //"yyyy-MM-dd'T'HH:mm:ss.SSS" 169 | } 170 | 171 | 172 | return cell 173 | } 174 | 175 | // Override to support conditional editing of the table view. 176 | override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 177 | // Return NO if you do not want the specified item to be editable. 178 | return true 179 | } 180 | 181 | // Override to support editing the table view. 182 | override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 183 | 184 | if editingStyle == .Delete { 185 | // Delete the row from the data source 186 | DLog("Attempting delete") 187 | Packet.delete(pktArray[indexPath.row].name) 188 | pktArray = Packet.fetchAllFromDBFiltered(true) 189 | DLog("Did delete work?") 190 | 191 | tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 192 | 193 | } else if editingStyle == .Insert { 194 | 195 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 196 | 197 | } 198 | 199 | } 200 | 201 | /* 202 | // MARK: - Navigation 203 | 204 | // In a storyboard-based application, you will often want to do a little preparation before navigation 205 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 206 | // Get the new view controller using segue.destinationViewController. 207 | // Pass the selected object to the new view controller. 208 | } 209 | */ 210 | 211 | } 212 | -------------------------------------------------------------------------------- /Packet Sender/assetsraw/applogo_bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/applogo_bw.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/applogo_notagline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/applogo_notagline.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/applogo_tagline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/applogo_tagline.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_import_export30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_import_export30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_import_export30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_import_export30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_settings30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_settings30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_settings30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_settings30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_settings48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_settings48.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/ic_action_settings96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/ic_action_settings96.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/moveupdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/moveupdown.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo29.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo29@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo29@3x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo30@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo30@3x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo40.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo40@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo40@3x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo60.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo60@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo60@3x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo76.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo76@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/pslogo76@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/pslogo76@3x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_tcp30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_tcp30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_tcp30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_tcp30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_tcp75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_tcp75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_udp30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_udp30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_udp30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_udp30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_udp75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_udp75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_white30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_white30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_white30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_white30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_white75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_white75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_yellow30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_yellow30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_yellow30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_yellow30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/rx_yellow75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/rx_yellow75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_tcp30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_tcp30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_tcp30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_tcp30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_tcp75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_tcp75.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_udp30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_udp30.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_udp30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_udp30@2x.png -------------------------------------------------------------------------------- /Packet Sender/assetsraw/tx_udp75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/Packet Sender/assetsraw/tx_udp75.png -------------------------------------------------------------------------------- /Packet SenderTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.packetsender.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Packet SenderTests/Packet_SenderTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Packet_SenderTests.swift 3 | // Packet SenderTests 4 | // 5 | // Created by Dan Nagle on 12/6/14. 6 | // Copyright (c) 2014 Dan Nagle. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class Packet_SenderTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *This repo has been abandoned.* The mobile edition is now a Xamarin project that exists here: 2 | https://github.com/dannagle/Packet_Sender_Mobile 3 | 4 | 5 | # Packet Sender for iOS 6 | This was the iOS version of Packet Sender for Desktop. The project is not being actively developed. 7 | 8 | Packet Sender Android 9 | 10 | ## Parent project 11 | This was originally an attempt to rewrite the GPL-based desktop version: 12 | https://github.com/dannagle/PacketSender 13 | 14 | 15 | ## License 16 | 17 | MIT. Feel free to fork and make it your own. 18 | 19 | 20 | ## Copyright 21 | 22 | Packet Sender is wholly owned and copyright © - [@NagleCode](http://twitter.com/NagleCode) - [DanNagle.com](http://DanNagle.com) - [PacketSender.com](http://PacketSender.com) 23 | -------------------------------------------------------------------------------- /screenshots/iphone-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dannagle/PacketSender-iOS/1c3185d232bf1f6d5fb53acc10caf0db94286ec6/screenshots/iphone-screenshot.png --------------------------------------------------------------------------------