├── .github
└── ISSUE_TEMPLATE.md
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── Readme Files
├── AppIcon.png
├── EASessionConnected.png
├── ServerStarted.png
├── Start.png
├── TCPConnected.png
└── USBConnected.png
├── Relay.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
└── Relay
├── AppDelegate.h
├── AppDelegate.m
├── Assets.xcassets
├── AppIcon.appiconset
│ ├── 120-1.png
│ ├── 120.png
│ ├── 180.png
│ ├── 58.png
│ ├── 80.png
│ ├── 87.png
│ └── Contents.json
├── Contents.json
├── Logging_Icon.imageset
│ ├── Contents.json
│ └── text_20x20@2x.png
└── Settings_Icon.imageset
│ ├── Contents.json
│ └── profile_20x20@2x.png
├── Base.lproj
└── LaunchScreen.storyboard
├── EASession+Streams.h
├── EASession+Streams.m
├── Info.plist
├── Main.storyboard
├── NSObject+Notifications.h
├── NSObject+Notifications.m
├── NSStream+Connection.h
├── NSStream+Connection.m
├── SDLLabel.h
├── SDLLabel.m
├── SDLRelayManager.h
├── SDLRelayManager.m
├── SDLStatusViewController.h
├── SDLStatusViewController.m
├── SDLTCPConnection.h
├── SDLTCPConnection.m
├── SDLTCPServer.h
├── SDLTCPServer.m
├── SDLiAPManager.h
├── SDLiAPManager.m
└── main.m
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | [Delete any non-applicable sections, but we may ask for more information.]
2 |
3 | ### Bug Report
4 | [Summary]
5 |
6 | ##### Reproduction Steps
7 | 1. [Step 1]
8 | 2. [Step 2]
9 | 3. [Step 3]
10 |
11 | ##### Expected Behavior
12 | [Some expected behavior]
13 |
14 | ##### Observed Behavior
15 | [Some observed behavior]
16 |
17 | ##### OS & Version Information
18 | * iOS Version: [What version of iOS are you using when the bug occurred]
19 | * SDL iOS Version: [What version of the library has this bug been seen on]
20 | * Testing Against: [What you tested with to observe this behavior]
21 |
22 | ##### Test Case, Sample Code, and / or Example App
23 | [Paste a link to a PR, gist, or other code that exemplifies this behavior]
24 |
--------------------------------------------------------------------------------
/.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 | # OS generated files #
21 | ######################
22 | .DS_Store
23 | .DS_Store?
24 | ._*
25 | .Spotlight-V100
26 | .Trashes
27 | Icon?
28 | ehthumbs.db
29 | Thumbs.db
30 |
31 | # OS X temporary files #
32 | ########################
33 | *.swp
34 | *.lock
35 | profile
36 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 1.0 Release Notes
2 | * Initial Commit
3 |
4 | # 1.0.1 Release Notes
5 | * Fixed issue that caused an application to not be able to reconnect after disconnect.
6 | * Fixed issue where in certain circumstances the relay would crash.
7 |
8 | # 1.0.2 Release Notes
9 | * Fixed issue that caused the relay to go into a "Connecting…" EASession state after SDL disconnected.
10 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to SDL Projects
2 |
3 | Third party contributions are essential for making SDL great. However, we do have a few guidelines we need contributors to follow.
4 |
5 | ### Issues
6 | If writing a bug report, please make sure it has enough info. Include all relevant information.
7 |
8 | If requesting a feature, understand that we appreciate the input! However, it may not immediately fit our roadmap, and it may take a while for us to get to your request.
9 |
10 | ### Gitflow
11 | We use Gitflow as our branch management system. Please follow gitflow's guidelines while contributing to any SDL project.
12 |
13 | ### Pull Requests
14 | * Please follow the repository's for all code and documentation.
15 | * All feature branches should be based on `develop` and have the format `feature/branch_name`.
16 | * Minor bug fixes, that is bug fixes that do not change, add, or remove any public API, should be based on `master` and have the format `hotfix/branch_name`.
17 | * All pull requests should implement a single feature or fix a single bug. Pull Requests that involve multiple changes (it is our discretion what precisely this means) will be rejected with a reason.
18 | * All commits should separated into logical units, i.e. unrelated changes should be in different commits within a pull request.
19 | * Work in progress pull requests should have "[WIP]" in front of the Pull Request title. When you believe the pull request is ready to merge, remove this tag and @mention the appropriate SDL team to schedule a review.
20 | * All new code *must* include unit tests. Bug fixes should have a test that fails previously and now passes. All new features should be covered. If your code does not have tests, or regresses old tests, it will be rejected.
21 | * A great example of a pull request can be found here.
22 |
23 | ### Contributor's License Agreement (CLA)
24 | In order to accept Pull Requests from contributors, you must first sign [the Contributor's License Agreement](https://docs.google.com/forms/d/1VNR8EUd5b46cQ7uNbCq1fJmnu0askNpUp5dudLKRGpU/viewform). If you need to make a change to information that you entered, [please contact us](mailto:justin@livio.io).
25 |
26 | ### Repository Specific Guidelines
27 | * iOS Style Guide
28 | * Please document all code written using [Objective-C style documentation](http://nshipster.com/documentation/) for methods (we use [VVDocumenter](https://github.com/onevcat/VVDocumenter-Xcode) for methods and use inline code comments where it makes sense, i.e. for non-obvious code chunks.
29 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | [Delete any non-applicable sections, but we may ask for more information.]
2 |
3 | ### Bug Report
4 | [Summary]
5 |
6 | ##### Reproduction Steps
7 | 1. [Step 1]
8 | 1. [Step 2]
9 | 1. [Step 3]
10 |
11 | ##### Expected Behavior
12 | [Some expected behavior]
13 |
14 | ##### Observed Behavior
15 | [Some observed behavior]
16 |
17 | ##### OS & Version Information
18 | * Relay Device's iOS Version: [What version of iOS is the Relay app running on when the bug occurred]
19 | * Relay Version: [What version of Relay App]
20 | * App's SDL Version: [What version of the library has this bug been seen on]
21 | * Testing Against: [What you tested with to observe this behavior]
22 |
23 | ##### Test Case, Sample Code, and / or Example App
24 | [Paste a link to a PR, gist, or other code that exemplifies this behavior]
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2017 SmartDeviceLink Consortium, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Fixes #[issue number]
2 |
3 | This PR is **[ready / not ready]** for review.
4 |
5 | ### Risk
6 | This PR makes **[no / minor / major]** API changes.
7 |
8 | ### Testing Plan
9 | [Describe how you plan to unit test the changes in this PR]
10 |
11 | ### Summary
12 | [Summary of PR changes]
13 |
14 | ### Changelog
15 | ##### Breaking Changes
16 | * [Breaking change info]
17 |
18 | ##### Enchancements
19 | * [Enchancement info]
20 |
21 | ##### Bug Fixes
22 | * [Bug Fix Info]
23 |
24 | ### Tasks Remaining:
25 | - [ ] [Task 1]
26 | - [ ] [Task 2]
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | # SmartDeviceLink (SDL) iOS Relay
3 |
4 | SDL iOS Relay is a tool built for developers building applications
5 | that utilizes SmartDeviceLink for connecting their apps to technologies using
6 | our [SmartDeviceLink Core](https://github.com/smartdevicelink/sdl_core) connected
7 | via USB. This tool allows those developers to test their applications over a TCP/IP connection, allowing developers to easily see debug logs to make development faster
8 | and easier.
9 |
10 | ### Things To Note
11 | - Make sure that both SDL iOS Relay and your app are connected to the
12 | **same** wifi network.
13 |
14 |
15 | ## Relay Status
16 |
17 | #### Start
18 |
19 | > Initial app startup. This state is visible when the app is not connected to
20 | hardware running SDL Core via USB.
21 |
22 | #### USB Connected
23 |
24 | > When Relay is initially connected via USB, but the connection isn't complete.
25 |
26 | #### EASession Connected
27 |
28 | > When the Relay is fully connected via USB, and ready for server start.
29 |
30 | #### Relay started
31 |
32 | > Server is now started, and awating connection.
33 |
34 |
35 | #### Connected to Relay
36 |
37 | > Application is correctly connected to Relay, and messages can
38 | now be sent and received.
39 |
40 | ## How To Start Testing Using Relay
41 |
42 | > ###### For all documentation purposes, we will be using our [SDL iOS Library](https://github.com/smartdevicelink/sdl_ios) for code snippets.
43 |
44 | To get started, please be sure to use the proxy builder's [TCP/IP initializer](https://github.com/smartdevicelink/sdl_ios/blob/master/SmartDeviceLink-iOS/SmartDeviceLink/SDLProxyFactory.h#L16).
45 | ```objective-c
46 | SDLProxy* proxy = [SDLProxyFactory buildSDLProxyWithListener:sdlProxyListenerDelegate
47 | tcpIPAddress:@"1.2.3.4"
48 | port:@"2776"];
49 | ```
50 | > NOTE: Be sure to start the Relay app **before** connecting your application to it.
51 |
52 | ## Need Help?
53 | If you need general assistance, or have other questions, you can [sign up](http://slack.smartdevicelink.org/) for the [SDL Slack](https://smartdevicelink.slack.com/) and chat with other developers and the maintainers of the project.
54 |
55 | ## Found a Bug?
56 | If you see a bug, feel free to [post an issue](https://github.com/smartdevicelink/relay_app_ios/issues/new). Please see the [contribution guidelines](https://github.com/smartdevicelink/relay_app_ios/blob/master/CONTRIBUTING.md) before proceeding.
57 |
58 | ## Want to Help?
59 | If you want to help add more features, please [file a pull request](https://github.com/smartdevicelink/relay_app_ios/compare). Please see the [contribution guidelines](https://github.com/smartdevicelink/relay_app_ios/blob/master/CONTRIBUTING.md) before proceeding.
60 |
--------------------------------------------------------------------------------
/Readme Files/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/AppIcon.png
--------------------------------------------------------------------------------
/Readme Files/EASessionConnected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/EASessionConnected.png
--------------------------------------------------------------------------------
/Readme Files/ServerStarted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/ServerStarted.png
--------------------------------------------------------------------------------
/Readme Files/Start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/Start.png
--------------------------------------------------------------------------------
/Readme Files/TCPConnected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/TCPConnected.png
--------------------------------------------------------------------------------
/Readme Files/USBConnected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Readme Files/USBConnected.png
--------------------------------------------------------------------------------
/Relay.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1A8553C61BE833AC00312347 /* SDLStatusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8553C41BE833AC00312347 /* SDLStatusViewController.m */; };
11 | 1A8553CF1BE833C900312347 /* SDLTCPServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8553CE1BE833C900312347 /* SDLTCPServer.m */; };
12 | 1A8553D21BE833D000312347 /* SDLiAPManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8553D11BE833D000312347 /* SDLiAPManager.m */; };
13 | 1A8553D51BE833E400312347 /* SDLRelayManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8553D41BE833E400312347 /* SDLRelayManager.m */; };
14 | 1AEDDD631BE2824800ACCCA6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AEDDD621BE2824800ACCCA6 /* main.m */; };
15 | 1AEDDD661BE2824800ACCCA6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AEDDD651BE2824800ACCCA6 /* AppDelegate.m */; };
16 | 1AEDDD6E1BE2824800ACCCA6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1AEDDD6D1BE2824800ACCCA6 /* Assets.xcassets */; };
17 | 1AEDDD711BE2824800ACCCA6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1AEDDD6F1BE2824800ACCCA6 /* LaunchScreen.storyboard */; };
18 | DA9EAE2C1C193C8000697E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA9EAE2B1C193C8000697E06 /* Main.storyboard */; };
19 | DA9EAE331C1959EA00697E06 /* SDLLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9EAE321C1959EA00697E06 /* SDLLabel.m */; };
20 | DAD0ACF51C8790F90060A411 /* SDLTCPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD0ACF41C8790F90060A411 /* SDLTCPConnection.m */; };
21 | DAD0ACFD1C87DE3F0060A411 /* NSStream+Connection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD0ACFC1C87DE3F0060A411 /* NSStream+Connection.m */; };
22 | DAD0AD001C87DE470060A411 /* EASession+Streams.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD0ACFF1C87DE470060A411 /* EASession+Streams.m */; };
23 | DAD0AD041C89060C0060A411 /* NSObject+Notifications.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD0AD031C89060C0060A411 /* NSObject+Notifications.m */; };
24 | /* End PBXBuildFile section */
25 |
26 | /* Begin PBXFileReference section */
27 | 1A8553C31BE833AC00312347 /* SDLStatusViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStatusViewController.h; sourceTree = ""; };
28 | 1A8553C41BE833AC00312347 /* SDLStatusViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStatusViewController.m; sourceTree = ""; };
29 | 1A8553CD1BE833C900312347 /* SDLTCPServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLTCPServer.h; sourceTree = ""; };
30 | 1A8553CE1BE833C900312347 /* SDLTCPServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTCPServer.m; sourceTree = ""; };
31 | 1A8553D01BE833D000312347 /* SDLiAPManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLiAPManager.h; sourceTree = ""; };
32 | 1A8553D11BE833D000312347 /* SDLiAPManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLiAPManager.m; sourceTree = ""; };
33 | 1A8553D31BE833E400312347 /* SDLRelayManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLRelayManager.h; sourceTree = ""; };
34 | 1A8553D41BE833E400312347 /* SDLRelayManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLRelayManager.m; sourceTree = ""; };
35 | 1AEDDD5E1BE2824800ACCCA6 /* Relay.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Relay.app; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 1AEDDD621BE2824800ACCCA6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
37 | 1AEDDD641BE2824800ACCCA6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
38 | 1AEDDD651BE2824800ACCCA6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
39 | 1AEDDD6D1BE2824800ACCCA6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
40 | 1AEDDD701BE2824800ACCCA6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
41 | 1AEDDD721BE2824800ACCCA6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
42 | DA9EAE2B1C193C8000697E06 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
43 | DA9EAE311C1959EA00697E06 /* SDLLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLabel.h; sourceTree = ""; };
44 | DA9EAE321C1959EA00697E06 /* SDLLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLLabel.m; sourceTree = ""; };
45 | DAD0ACF31C8790F90060A411 /* SDLTCPConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLTCPConnection.h; sourceTree = ""; };
46 | DAD0ACF41C8790F90060A411 /* SDLTCPConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTCPConnection.m; sourceTree = ""; };
47 | DAD0ACFB1C87DE3F0060A411 /* NSStream+Connection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSStream+Connection.h"; sourceTree = ""; };
48 | DAD0ACFC1C87DE3F0060A411 /* NSStream+Connection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSStream+Connection.m"; sourceTree = ""; };
49 | DAD0ACFE1C87DE470060A411 /* EASession+Streams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "EASession+Streams.h"; sourceTree = ""; };
50 | DAD0ACFF1C87DE470060A411 /* EASession+Streams.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "EASession+Streams.m"; sourceTree = ""; };
51 | DAD0AD021C89060C0060A411 /* NSObject+Notifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Notifications.h"; sourceTree = ""; };
52 | DAD0AD031C89060C0060A411 /* NSObject+Notifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Notifications.m"; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | 1AEDDD5B1BE2824800ACCCA6 /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | );
61 | runOnlyForDeploymentPostprocessing = 0;
62 | };
63 | /* End PBXFrameworksBuildPhase section */
64 |
65 | /* Begin PBXGroup section */
66 | 1ABE50361BE95805006394EF /* ViewControllers */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 1A8553C31BE833AC00312347 /* SDLStatusViewController.h */,
70 | 1A8553C41BE833AC00312347 /* SDLStatusViewController.m */,
71 | );
72 | name = ViewControllers;
73 | sourceTree = "";
74 | };
75 | 1AEDDD551BE2824800ACCCA6 = {
76 | isa = PBXGroup;
77 | children = (
78 | 1AEDDD601BE2824800ACCCA6 /* Relay */,
79 | 1AEDDD5F1BE2824800ACCCA6 /* Products */,
80 | );
81 | sourceTree = "";
82 | };
83 | 1AEDDD5F1BE2824800ACCCA6 /* Products */ = {
84 | isa = PBXGroup;
85 | children = (
86 | 1AEDDD5E1BE2824800ACCCA6 /* Relay.app */,
87 | );
88 | name = Products;
89 | sourceTree = "";
90 | };
91 | 1AEDDD601BE2824800ACCCA6 /* Relay */ = {
92 | isa = PBXGroup;
93 | children = (
94 | DAD0ACFA1C87DE370060A411 /* Categories */,
95 | 1AEDDD641BE2824800ACCCA6 /* AppDelegate.h */,
96 | 1AEDDD651BE2824800ACCCA6 /* AppDelegate.m */,
97 | DAD0ACF31C8790F90060A411 /* SDLTCPConnection.h */,
98 | DAD0ACF41C8790F90060A411 /* SDLTCPConnection.m */,
99 | 1A8553CD1BE833C900312347 /* SDLTCPServer.h */,
100 | 1A8553CE1BE833C900312347 /* SDLTCPServer.m */,
101 | 1A8553D01BE833D000312347 /* SDLiAPManager.h */,
102 | 1A8553D11BE833D000312347 /* SDLiAPManager.m */,
103 | 1A8553D31BE833E400312347 /* SDLRelayManager.h */,
104 | 1A8553D41BE833E400312347 /* SDLRelayManager.m */,
105 | DA9EAE301C1959DD00697E06 /* Views */,
106 | 1ABE50361BE95805006394EF /* ViewControllers */,
107 | 1AEDDD611BE2824800ACCCA6 /* Supporting Files */,
108 | );
109 | path = Relay;
110 | sourceTree = "";
111 | };
112 | 1AEDDD611BE2824800ACCCA6 /* Supporting Files */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 1AEDDD6D1BE2824800ACCCA6 /* Assets.xcassets */,
116 | 1AEDDD6F1BE2824800ACCCA6 /* LaunchScreen.storyboard */,
117 | DA9EAE2B1C193C8000697E06 /* Main.storyboard */,
118 | 1AEDDD721BE2824800ACCCA6 /* Info.plist */,
119 | 1AEDDD621BE2824800ACCCA6 /* main.m */,
120 | );
121 | name = "Supporting Files";
122 | sourceTree = "";
123 | };
124 | DA9EAE301C1959DD00697E06 /* Views */ = {
125 | isa = PBXGroup;
126 | children = (
127 | DA9EAE311C1959EA00697E06 /* SDLLabel.h */,
128 | DA9EAE321C1959EA00697E06 /* SDLLabel.m */,
129 | );
130 | name = Views;
131 | sourceTree = "";
132 | };
133 | DAD0ACFA1C87DE370060A411 /* Categories */ = {
134 | isa = PBXGroup;
135 | children = (
136 | DAD0ACFE1C87DE470060A411 /* EASession+Streams.h */,
137 | DAD0ACFF1C87DE470060A411 /* EASession+Streams.m */,
138 | DAD0ACFB1C87DE3F0060A411 /* NSStream+Connection.h */,
139 | DAD0ACFC1C87DE3F0060A411 /* NSStream+Connection.m */,
140 | DAD0AD021C89060C0060A411 /* NSObject+Notifications.h */,
141 | DAD0AD031C89060C0060A411 /* NSObject+Notifications.m */,
142 | );
143 | name = Categories;
144 | sourceTree = "";
145 | };
146 | /* End PBXGroup section */
147 |
148 | /* Begin PBXNativeTarget section */
149 | 1AEDDD5D1BE2824800ACCCA6 /* Relay */ = {
150 | isa = PBXNativeTarget;
151 | buildConfigurationList = 1AEDDD751BE2824800ACCCA6 /* Build configuration list for PBXNativeTarget "Relay" */;
152 | buildPhases = (
153 | 1AEDDD5A1BE2824800ACCCA6 /* Sources */,
154 | 1AEDDD5B1BE2824800ACCCA6 /* Frameworks */,
155 | 1AEDDD5C1BE2824800ACCCA6 /* Resources */,
156 | );
157 | buildRules = (
158 | );
159 | dependencies = (
160 | );
161 | name = Relay;
162 | productName = Relay;
163 | productReference = 1AEDDD5E1BE2824800ACCCA6 /* Relay.app */;
164 | productType = "com.apple.product-type.application";
165 | };
166 | /* End PBXNativeTarget section */
167 |
168 | /* Begin PBXProject section */
169 | 1AEDDD561BE2824800ACCCA6 /* Project object */ = {
170 | isa = PBXProject;
171 | attributes = {
172 | LastUpgradeCheck = 0710;
173 | ORGANIZATIONNAME = "Ford Motor Company";
174 | TargetAttributes = {
175 | 1AEDDD5D1BE2824800ACCCA6 = {
176 | CreatedOnToolsVersion = 7.1;
177 | };
178 | };
179 | };
180 | buildConfigurationList = 1AEDDD591BE2824800ACCCA6 /* Build configuration list for PBXProject "Relay" */;
181 | compatibilityVersion = "Xcode 3.2";
182 | developmentRegion = English;
183 | hasScannedForEncodings = 0;
184 | knownRegions = (
185 | en,
186 | Base,
187 | );
188 | mainGroup = 1AEDDD551BE2824800ACCCA6;
189 | productRefGroup = 1AEDDD5F1BE2824800ACCCA6 /* Products */;
190 | projectDirPath = "";
191 | projectRoot = "";
192 | targets = (
193 | 1AEDDD5D1BE2824800ACCCA6 /* Relay */,
194 | );
195 | };
196 | /* End PBXProject section */
197 |
198 | /* Begin PBXResourcesBuildPhase section */
199 | 1AEDDD5C1BE2824800ACCCA6 /* Resources */ = {
200 | isa = PBXResourcesBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | DA9EAE2C1C193C8000697E06 /* Main.storyboard in Resources */,
204 | 1AEDDD711BE2824800ACCCA6 /* LaunchScreen.storyboard in Resources */,
205 | 1AEDDD6E1BE2824800ACCCA6 /* Assets.xcassets in Resources */,
206 | );
207 | runOnlyForDeploymentPostprocessing = 0;
208 | };
209 | /* End PBXResourcesBuildPhase section */
210 |
211 | /* Begin PBXSourcesBuildPhase section */
212 | 1AEDDD5A1BE2824800ACCCA6 /* Sources */ = {
213 | isa = PBXSourcesBuildPhase;
214 | buildActionMask = 2147483647;
215 | files = (
216 | DA9EAE331C1959EA00697E06 /* SDLLabel.m in Sources */,
217 | DAD0ACFD1C87DE3F0060A411 /* NSStream+Connection.m in Sources */,
218 | 1A8553C61BE833AC00312347 /* SDLStatusViewController.m in Sources */,
219 | 1A8553D21BE833D000312347 /* SDLiAPManager.m in Sources */,
220 | 1A8553CF1BE833C900312347 /* SDLTCPServer.m in Sources */,
221 | DAD0AD041C89060C0060A411 /* NSObject+Notifications.m in Sources */,
222 | 1AEDDD661BE2824800ACCCA6 /* AppDelegate.m in Sources */,
223 | 1A8553D51BE833E400312347 /* SDLRelayManager.m in Sources */,
224 | 1AEDDD631BE2824800ACCCA6 /* main.m in Sources */,
225 | DAD0AD001C87DE470060A411 /* EASession+Streams.m in Sources */,
226 | DAD0ACF51C8790F90060A411 /* SDLTCPConnection.m in Sources */,
227 | );
228 | runOnlyForDeploymentPostprocessing = 0;
229 | };
230 | /* End PBXSourcesBuildPhase section */
231 |
232 | /* Begin PBXVariantGroup section */
233 | 1AEDDD6F1BE2824800ACCCA6 /* LaunchScreen.storyboard */ = {
234 | isa = PBXVariantGroup;
235 | children = (
236 | 1AEDDD701BE2824800ACCCA6 /* Base */,
237 | );
238 | name = LaunchScreen.storyboard;
239 | sourceTree = "";
240 | };
241 | /* End PBXVariantGroup section */
242 |
243 | /* Begin XCBuildConfiguration section */
244 | 1AEDDD731BE2824800ACCCA6 /* Debug */ = {
245 | isa = XCBuildConfiguration;
246 | buildSettings = {
247 | ALWAYS_SEARCH_USER_PATHS = NO;
248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
249 | CLANG_CXX_LIBRARY = "libc++";
250 | CLANG_ENABLE_MODULES = YES;
251 | CLANG_ENABLE_OBJC_ARC = YES;
252 | CLANG_WARN_BOOL_CONVERSION = YES;
253 | CLANG_WARN_CONSTANT_CONVERSION = YES;
254 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
255 | CLANG_WARN_EMPTY_BODY = YES;
256 | CLANG_WARN_ENUM_CONVERSION = YES;
257 | CLANG_WARN_INT_CONVERSION = YES;
258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
259 | CLANG_WARN_UNREACHABLE_CODE = YES;
260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
261 | CODE_SIGN_IDENTITY = "iPhone Developer: James Sokoll (VQ4272R23R)";
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: James Sokoll (VQ4272R23R)";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
265 | ENABLE_STRICT_OBJC_MSGSEND = YES;
266 | ENABLE_TESTABILITY = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_DYNAMIC_NO_PIC = NO;
269 | GCC_NO_COMMON_BLOCKS = YES;
270 | GCC_OPTIMIZATION_LEVEL = 0;
271 | GCC_PREPROCESSOR_DEFINITIONS = (
272 | "DEBUG=1",
273 | "$(inherited)",
274 | );
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
277 | GCC_WARN_UNDECLARED_SELECTOR = YES;
278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
279 | GCC_WARN_UNUSED_FUNCTION = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
282 | MTL_ENABLE_DEBUG_INFO = YES;
283 | ONLY_ACTIVE_ARCH = YES;
284 | SDKROOT = iphoneos;
285 | STRIP_INSTALLED_PRODUCT = NO;
286 | STRIP_STYLE = debugging;
287 | };
288 | name = Debug;
289 | };
290 | 1AEDDD741BE2824800ACCCA6 /* Release */ = {
291 | isa = XCBuildConfiguration;
292 | buildSettings = {
293 | ALWAYS_SEARCH_USER_PATHS = NO;
294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
295 | CLANG_CXX_LIBRARY = "libc++";
296 | CLANG_ENABLE_MODULES = YES;
297 | CLANG_ENABLE_OBJC_ARC = YES;
298 | CLANG_WARN_BOOL_CONVERSION = YES;
299 | CLANG_WARN_CONSTANT_CONVERSION = YES;
300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
301 | CLANG_WARN_EMPTY_BODY = YES;
302 | CLANG_WARN_ENUM_CONVERSION = YES;
303 | CLANG_WARN_INT_CONVERSION = YES;
304 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
305 | CLANG_WARN_UNREACHABLE_CODE = YES;
306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
307 | CODE_SIGN_IDENTITY = "iPhone Developer: James Sokoll (VQ4272R23R)";
308 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: James Sokoll (VQ4272R23R)";
309 | COPY_PHASE_STRIP = NO;
310 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
311 | ENABLE_NS_ASSERTIONS = NO;
312 | ENABLE_STRICT_OBJC_MSGSEND = YES;
313 | GCC_C_LANGUAGE_STANDARD = gnu99;
314 | GCC_NO_COMMON_BLOCKS = YES;
315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
317 | GCC_WARN_UNDECLARED_SELECTOR = YES;
318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
319 | GCC_WARN_UNUSED_FUNCTION = YES;
320 | GCC_WARN_UNUSED_VARIABLE = YES;
321 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
322 | MTL_ENABLE_DEBUG_INFO = NO;
323 | SDKROOT = iphoneos;
324 | STRIP_INSTALLED_PRODUCT = NO;
325 | STRIP_STYLE = debugging;
326 | VALIDATE_PRODUCT = YES;
327 | };
328 | name = Release;
329 | };
330 | 1AEDDD761BE2824800ACCCA6 /* Debug */ = {
331 | isa = XCBuildConfiguration;
332 | buildSettings = {
333 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
334 | CODE_SIGN_IDENTITY = "iPhone Developer";
335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
336 | COPY_PHASE_STRIP = NO;
337 | INFOPLIST_FILE = Relay/Info.plist;
338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
339 | PRODUCT_BUNDLE_IDENTIFIER = com.sdl.relay;
340 | PRODUCT_NAME = "$(TARGET_NAME)";
341 | PROVISIONING_PROFILE = "";
342 | STRIP_INSTALLED_PRODUCT = NO;
343 | STRIP_STYLE = debugging;
344 | };
345 | name = Debug;
346 | };
347 | 1AEDDD771BE2824800ACCCA6 /* Release */ = {
348 | isa = XCBuildConfiguration;
349 | buildSettings = {
350 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
351 | CODE_SIGN_IDENTITY = "iPhone Developer";
352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
353 | COPY_PHASE_STRIP = NO;
354 | INFOPLIST_FILE = Relay/Info.plist;
355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
356 | PRODUCT_BUNDLE_IDENTIFIER = com.sdl.relay;
357 | PRODUCT_NAME = "$(TARGET_NAME)";
358 | PROVISIONING_PROFILE = "";
359 | STRIP_INSTALLED_PRODUCT = NO;
360 | STRIP_STYLE = debugging;
361 | };
362 | name = Release;
363 | };
364 | /* End XCBuildConfiguration section */
365 |
366 | /* Begin XCConfigurationList section */
367 | 1AEDDD591BE2824800ACCCA6 /* Build configuration list for PBXProject "Relay" */ = {
368 | isa = XCConfigurationList;
369 | buildConfigurations = (
370 | 1AEDDD731BE2824800ACCCA6 /* Debug */,
371 | 1AEDDD741BE2824800ACCCA6 /* Release */,
372 | );
373 | defaultConfigurationIsVisible = 0;
374 | defaultConfigurationName = Release;
375 | };
376 | 1AEDDD751BE2824800ACCCA6 /* Build configuration list for PBXNativeTarget "Relay" */ = {
377 | isa = XCConfigurationList;
378 | buildConfigurations = (
379 | 1AEDDD761BE2824800ACCCA6 /* Debug */,
380 | 1AEDDD771BE2824800ACCCA6 /* Release */,
381 | );
382 | defaultConfigurationIsVisible = 0;
383 | defaultConfigurationName = Release;
384 | };
385 | /* End XCConfigurationList section */
386 | };
387 | rootObject = 1AEDDD561BE2824800ACCCA6 /* Project object */;
388 | }
389 |
--------------------------------------------------------------------------------
/Relay.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Relay/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | @interface AppDelegate : UIResponder
9 |
10 | @property (strong, nonatomic) UIWindow *window;
11 |
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/Relay/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // Relay
4 | //
5 |
6 | #import "AppDelegate.h"
7 |
8 | @interface AppDelegate ()
9 |
10 | @end
11 |
12 | @implementation AppDelegate
13 |
14 |
15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
16 | [UIApplication sharedApplication].idleTimerDisabled = YES;
17 |
18 | return YES;
19 | }
20 |
21 | - (void)applicationWillResignActive:(UIApplication *)application {
22 | // 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.
23 | // 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.
24 | }
25 |
26 | - (void)applicationDidEnterBackground:(UIApplication *)application {
27 | // 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.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application {
32 | // 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.
33 | }
34 |
35 | - (void)applicationDidBecomeActive:(UIApplication *)application {
36 | // 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.
37 | }
38 |
39 | - (void)applicationWillTerminate:(UIApplication *)application {
40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/120-1.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/120.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/180.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/58.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/80.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/AppIcon.appiconset/87.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "58.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "87.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "80.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "120-1.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "120.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "180.png",
37 | "scale" : "3x"
38 | }
39 | ],
40 | "info" : {
41 | "version" : 1,
42 | "author" : "xcode"
43 | }
44 | }
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/Logging_Icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "text_20x20@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/Logging_Icon.imageset/text_20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/Logging_Icon.imageset/text_20x20@2x.png
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/Settings_Icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "profile_20x20@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Relay/Assets.xcassets/Settings_Icon.imageset/profile_20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartdevicelink/relay_app_ios/263d60a56e87f99d7ffb563cb38888695a61d881/Relay/Assets.xcassets/Settings_Icon.imageset/profile_20x20@2x.png
--------------------------------------------------------------------------------
/Relay/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Relay/EASession+Streams.h:
--------------------------------------------------------------------------------
1 | //
2 | // EASession+Streams.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | @interface EASession (Streams)
9 |
10 | /**
11 | * Convenience method that opens both input and output streams, sets their delegates, and
12 | * adds them to the currentRunLoop.
13 | *
14 | * @param delegate Delegate that will respond to NSStream's delegate notifications.
15 | */
16 | - (void)openStreamsWithDelegate:(id)delegate;
17 |
18 | /**
19 | * Convenience method that closes both input and output streams, sets their delegates to
20 | * nil, and removes them from the currentRunLoop.
21 | */
22 | - (void)closeStreams;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Relay/EASession+Streams.m:
--------------------------------------------------------------------------------
1 | //
2 | // EASession+Streams.m
3 | // Relay
4 | //
5 |
6 | #import "EASession+Streams.h"
7 | #import "NSStream+Connection.h"
8 |
9 | @implementation EASession (Streams)
10 |
11 | - (void)openStreamsWithDelegate:(id)delegate {
12 | [self.inputStream openStreamWithDelegate:delegate];
13 | [self.outputStream openStreamWithDelegate:delegate];
14 | }
15 |
16 | - (void)closeStreams {
17 | [self.inputStream closeStream];
18 | [self.outputStream closeStream];
19 | }
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Relay/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIBackgroundModes
26 |
27 | external-accessory
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedExternalAccessoryProtocols
38 |
39 | com.ford.sync.prot0
40 | com.smartdevicelink.prot0
41 | com.smartdevicelink.prot1
42 | com.smartdevicelink.prot2
43 | com.smartdevicelink.prot3
44 | com.smartdevicelink.prot4
45 | com.smartdevicelink.prot5
46 | com.smartdevicelink.prot6
47 | com.smartdevicelink.prot7
48 | com.smartdevicelink.prot8
49 | com.smartdevicelink.prot9
50 | com.smartdevicelink.prot10
51 | com.smartdevicelink.prot11
52 | com.smartdevicelink.prot12
53 | com.smartdevicelink.prot13
54 | com.smartdevicelink.prot14
55 | com.smartdevicelink.prot15
56 | com.smartdevicelink.prot16
57 | com.smartdevicelink.prot17
58 | com.smartdevicelink.prot18
59 | com.smartdevicelink.prot19
60 | com.smartdevicelink.prot20
61 | com.smartdevicelink.prot21
62 | com.smartdevicelink.prot22
63 | com.smartdevicelink.prot23
64 | com.smartdevicelink.prot24
65 | com.smartdevicelink.prot25
66 | com.smartdevicelink.prot26
67 | com.smartdevicelink.prot27
68 | com.smartdevicelink.prot28
69 | com.smartdevicelink.prot29
70 |
71 | UISupportedInterfaceOrientations
72 |
73 | UIInterfaceOrientationPortrait
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/Relay/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
38 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
62 |
68 |
74 |
80 |
86 |
92 |
98 |
104 |
110 |
116 |
122 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/Relay/NSObject+Notifications.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+Notifications.h
3 | // Relay
4 | //
5 | // Created by Muller, Alexander (A.) on 3/3/16.
6 | // Copyright © 2016 Ford Motor Company. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSObject (Notifications)
12 |
13 | - (void)addSelfObserverForNotificationNamed:(NSString *)name selector:(SEL)selector;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Relay/NSObject+Notifications.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+Notifications.m
3 | // Relay
4 | //
5 | // Created by Muller, Alexander (A.) on 3/3/16.
6 | // Copyright © 2016 Ford Motor Company. All rights reserved.
7 | //
8 |
9 | #import "NSObject+Notifications.h"
10 |
11 | @implementation NSObject (Notifications)
12 |
13 | - (void)addSelfObserverForNotificationNamed:(NSString *)name selector:(SEL)selector {
14 | [[NSNotificationCenter defaultCenter] addObserver:self
15 | selector:selector
16 | name:name
17 | object:nil];
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Relay/NSStream+Connection.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSStream+Connection.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | @interface NSStream (Connection)
9 |
10 | /**
11 | * Convenience method that opens the stream, sets it's delegate, and adds it to the
12 | * currentRunLoop.
13 | *
14 | * @param delegate Delegate that will respond to NSStream's delegate notifications.
15 | */
16 | - (void)openStreamWithDelegate:(id)delegate;
17 |
18 | /**
19 | * Convenience method that closes the stream, sets it's delegate to nil, and removes it
20 | * from the currentRunLoop.
21 | */
22 | - (void)closeStream;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Relay/NSStream+Connection.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSStream+Connection.m
3 | // Relay
4 | //
5 |
6 | #import "NSStream+Connection.h"
7 |
8 | @implementation NSStream (Connection)
9 |
10 | - (void)openStreamWithDelegate:(id)delegate {
11 | [self setDelegate:delegate];
12 | [self scheduleInRunLoop:[NSRunLoop currentRunLoop]
13 | forMode:NSDefaultRunLoopMode];
14 | [self open];
15 |
16 | }
17 |
18 | - (void)closeStream {
19 | [self setDelegate:nil];
20 | [self close];
21 | [self removeFromRunLoop:[NSRunLoop currentRunLoop]
22 | forMode:NSDefaultRunLoopMode];
23 |
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Relay/SDLLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLLabel.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | typedef NS_ENUM(NSUInteger, SDLLabelState) {
9 | SDLLabelStateNone,
10 | SDLLabelStateError,
11 | SDLLabelStateSuccess,
12 | SDLLabelStateWaiting
13 | };
14 |
15 | @interface SDLLabel : UILabel
16 |
17 | @property (nonatomic, readonly) SDLLabelState currentState;
18 |
19 | - (void)updateToErrorStateWithString:(NSString *)string;
20 | - (void)updateToNoStateWithString:(NSString *)string;
21 | - (void)updateToSuccessStateWithString:(NSString *)string;
22 | - (void)updateToWaitingStateWithString:(NSString *)string;
23 | - (void)updateToState:(SDLLabelState)newState withString:(NSString *)string;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Relay/SDLLabel.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLLabel.m
3 | // Relay
4 | //
5 |
6 | #import "SDLLabel.h"
7 |
8 | #define FLAT_COLOR_BLACK [UIColor colorWithRed:(34 / 255.0) green:(49 / 255.0) blue:(63 / 255.0) alpha:1.0f]
9 | #define FLAT_COLOR_GREEN [UIColor colorWithRed:(38 / 255.0) green:(166 / 255.0) blue:(91 / 255.0) alpha:1.0f]
10 | #define FLAT_COLOR_ORANGE [UIColor colorWithRed:(249 / 255.0) green:(105 / 255.0) blue:(14 / 255.0) alpha:1.0f]
11 | #define FLAT_COLOR_RED [UIColor colorWithRed:(217 / 255.0) green:(30 / 255.0) blue:(24 / 255.0) alpha:1.0f]
12 |
13 |
14 | @implementation SDLLabel {
15 | BOOL _hasUpdatedOnce;
16 | }
17 |
18 | - (void)setText:(NSString *)text {
19 | if (_currentState == SDLLabelStateNone && !_hasUpdatedOnce) {
20 | self.textColor = FLAT_COLOR_BLACK;
21 | }
22 | if (!_hasUpdatedOnce) {
23 | _hasUpdatedOnce = YES;
24 | }
25 | [super setText:text];
26 | }
27 |
28 | - (void)updateToErrorStateWithString:(NSString *)string {
29 | [self updateToState:SDLLabelStateError
30 | withString:string];
31 | }
32 |
33 | - (void)updateToSuccessStateWithString:(NSString *)string {
34 | [self updateToState:SDLLabelStateSuccess
35 | withString:string];
36 | }
37 |
38 | - (void)updateToNoStateWithString:(NSString *)string {
39 | [self updateToState:SDLLabelStateNone
40 | withString:string];
41 | }
42 |
43 | - (void)updateToWaitingStateWithString:(NSString *)string {
44 | [self updateToState:SDLLabelStateWaiting
45 | withString:string];
46 | }
47 |
48 |
49 | - (void)updateToState:(SDLLabelState)newState withString:(NSString *)string {
50 | self.text = string;
51 | if (_currentState == newState) {
52 | return;
53 | }
54 |
55 | _currentState = newState;
56 | UIColor *newColor = nil;
57 | switch (newState) {
58 | case SDLLabelStateNone:
59 | newColor = FLAT_COLOR_BLACK;
60 | break;
61 | case SDLLabelStateError:
62 | newColor = FLAT_COLOR_RED;
63 | break;
64 | case SDLLabelStateSuccess:
65 | newColor = FLAT_COLOR_GREEN;
66 | break;
67 | case SDLLabelStateWaiting:
68 | newColor = FLAT_COLOR_ORANGE;
69 | break;
70 | default:
71 | break;
72 | }
73 | self.textColor = newColor;
74 | }
75 |
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/Relay/SDLRelayManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLRelayManager.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | // Notification User Info Key
9 | /**
10 | * User Info key for Notifications.
11 | */
12 | extern NSString* const SDLNotificationInfoKey;
13 |
14 | /**
15 | * Notification when USB is connected.
16 | */
17 | extern NSString* const SDLRelayManagerUSBConnectedNotification;
18 |
19 | /**
20 | * Notification when USB is disonnected.
21 | */
22 | extern NSString* const SDLRelayManagerUSBDisconnectedNotification;
23 |
24 | /**
25 | * Notification when Control Session is established.
26 | */
27 | extern NSString* const SDLRelayManagerControlSessionEstablishedNotification;
28 |
29 | /**
30 | * Notification when Data Session is established.
31 | */
32 | extern NSString* const SDLRelayManagerDataSessionEstablishedNotification;
33 |
34 | /**
35 | * Notification when TCP Server has been started.
36 | */
37 | extern NSString* const SDLRelayManagerTCPServerStartedNotification;
38 |
39 | /**
40 | * Notification when TCP Server is connected.
41 | */
42 | extern NSString* const SDLRelayManagerTCPServerConnectedNotification;
43 |
44 | /**
45 | * Notification when TCP Server is disconnected.
46 | */
47 | extern NSString* const SDLRelayManagerTCPServerDisconnectedNotification;
48 |
49 | /**
50 | * Relay manager routes data and updates status'
51 | */
52 | @interface SDLRelayManager : NSObject
53 |
54 | /**
55 | * Create the RelayManager object
56 | *
57 | * @return Instance of RelayManager
58 | */
59 | + (instancetype)sharedManager;
60 |
61 | /**
62 | * Start TCP Server.
63 | */
64 | - (void)startTCPServer;
65 |
66 | /**
67 | * Stop TCP Server.
68 | */
69 | - (void)stopTCPServer;
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/Relay/SDLRelayManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLRelayManager.m
3 | // Relay
4 | //
5 |
6 | #import "SDLRelayManager.h"
7 | #import "SDLiAPManager.h"
8 | #import "SDLTCPServer.h"
9 |
10 | NSString* const SDLNotificationInfoKey = @"SDLNotificationInfoKey";
11 |
12 | NSString* const SDLRelayManagerUSBConnectedNotification = @"com.smartdevicelink.sdlrelaymanager.usbconnected";
13 | NSString* const SDLRelayManagerUSBDisconnectedNotification = @"com.smartdevicelink.sdlrelaymanager.usbdisconnected";
14 | NSString* const SDLRelayManagerControlSessionEstablishedNotification = @"com.smartdevicelink.sdlrelaymanager.controlsessionestablished";
15 | NSString* const SDLRelayManagerDataSessionEstablishedNotification = @"com.smartdevicelink.sdlrelaymanager.datasessionestablished";
16 |
17 | NSString* const SDLRelayManagerTCPServerStartedNotification = @"com.smartdevicelink.sdlrelaymanager.tcpserverstarted";
18 | NSString* const SDLRelayManagerTCPServerConnectedNotification = @"com.smartdevicelink.sdlrelaymanager.tcpserverconnected";
19 | NSString* const SDLRelayManagerTCPServerDisconnectedNotification = @"com.smartdevicelink.sdlrelaymanager.tcpserverdisconnected";
20 |
21 | @interface SDLRelayManager ()
22 |
23 | @end
24 |
25 | @implementation SDLRelayManager
26 |
27 | + (instancetype)sharedManager {
28 | static SDLRelayManager *sharedManager = nil;
29 | static dispatch_once_t onceToken;
30 | dispatch_once(&onceToken, ^{
31 | sharedManager = [[SDLRelayManager alloc] init];
32 | });
33 |
34 | return sharedManager;
35 | }
36 |
37 | - (instancetype)init {
38 | if (self = [super init]) {
39 | [SDLTCPServer sharedService].delegate = self;
40 | [SDLiAPManager sharedService].delegate = self;
41 | }
42 |
43 | return self;
44 | }
45 |
46 | #pragma mark - Private
47 | - (void)sdl_postNotification:(NSString *)name info:(id)info {
48 | NSDictionary *userInfo = nil;
49 | if (info != nil) {
50 | userInfo = @{
51 | SDLNotificationInfoKey : info
52 | };
53 | }
54 | [[NSNotificationCenter defaultCenter] postNotificationName:name
55 | object:self
56 | userInfo:userInfo];
57 | }
58 |
59 | #pragma mark - Public Functions
60 | - (void)startTCPServer {
61 | [[SDLTCPServer sharedService] startServer];
62 | }
63 |
64 | - (void)stopTCPServer {
65 | [[SDLTCPServer sharedService] stopServer];
66 | [[SDLiAPManager sharedService] restartEASession];
67 | }
68 |
69 | #pragma mark - Delegates
70 | #pragma mark SDLTCPServer
71 | - (void)TCPServer:(SDLTCPServer *)server hasAvailableConnection:(SDLTCPConnection *)connection {
72 | [self sdl_postNotification:SDLRelayManagerTCPServerStartedNotification
73 | info:connection];
74 | }
75 |
76 | - (void)TCPServerDidConnect:(SDLTCPServer *)server {
77 | [self sdl_postNotification:SDLRelayManagerTCPServerConnectedNotification
78 | info:nil];
79 | }
80 |
81 | - (void)TCPServerDidDisconnect:(SDLTCPServer *)server {
82 | [[SDLiAPManager sharedService] restartEASession];
83 | [self sdl_postNotification:SDLRelayManagerTCPServerDisconnectedNotification
84 | info:nil];
85 | }
86 |
87 | - (void)TCPServer:(SDLTCPServer *)server didReceiveData:(NSData *)data {
88 | [[SDLiAPManager sharedService] sendData:data];
89 | }
90 |
91 | #pragma mark SDLiAPManager
92 | - (void)iAPManager:(SDLiAPManager *)iAPManager didReceiveData:(NSData *)data {
93 | [[SDLTCPServer sharedService] sendData:data];
94 | }
95 |
96 | - (void)iAPManagerUSBConnected:(SDLiAPManager *)iAPManager {
97 | [self sdl_postNotification:SDLRelayManagerUSBConnectedNotification
98 | info:nil];
99 | }
100 |
101 | - (void)iAPManagerUSBDisconnected:(SDLiAPManager *)iAPManager {
102 | [self sdl_postNotification:SDLRelayManagerUSBDisconnectedNotification
103 | info:nil];
104 | }
105 |
106 | - (void)iAPManagerControlSessionEstablished:(SDLiAPManager *)iAPManager {
107 | [self sdl_postNotification:SDLRelayManagerControlSessionEstablishedNotification
108 | info:nil];
109 | }
110 |
111 | - (void)iAPManagerDataSessionEstablished:(SDLiAPManager *)iAPManager {
112 | [self sdl_postNotification:SDLRelayManagerDataSessionEstablishedNotification
113 | info:nil];
114 | }
115 |
116 | @end
117 |
--------------------------------------------------------------------------------
/Relay/SDLStatusViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLStatusViewController.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | @interface SDLStatusViewController : UIViewController
9 |
10 | @end
11 |
--------------------------------------------------------------------------------
/Relay/SDLStatusViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLStatusViewController.m
3 | // Relay
4 | //
5 |
6 | #import "SDLStatusViewController.h"
7 | #import "SDLRelayManager.h"
8 | #import "SDLTCPConnection.h"
9 | #import "SDLLabel.h"
10 |
11 | #import "NSObject+Notifications.h"
12 |
13 | static NSString* const SDLStatusAvailable = @"Available";
14 | static NSString* const SDLStatusClosed = @"Closed";
15 | static NSString* const SDLStatusConnected = @"Connected";
16 | static NSString* const SDLStatusConnecting = @"Connecting…";
17 | static NSString* const SDLStatusDisconnected = @"Disconnected";
18 | static NSString* const SDLStatusError = @"Error";
19 | static NSString* const SDLStatusNotStarted = @"Not Started";
20 |
21 | @interface SDLStatusViewController ()
22 |
23 | @property (nonatomic, readonly) SDLRelayManager *sharedManager;
24 |
25 | @property (weak) IBOutlet UIScrollView* scrollView;
26 | @property (nonatomic, weak) IBOutlet SDLLabel *usbStatusLabel;
27 | @property (nonatomic, weak) IBOutlet SDLLabel *eaStatusLabel;
28 | @property (nonatomic, weak) IBOutlet SDLLabel *serverStatusLabel;
29 | @property (nonatomic, weak) IBOutlet SDLLabel *serverAddressLabel;
30 | @property (nonatomic, weak) IBOutlet SDLLabel *serverPortLabel;
31 | @property (nonatomic, weak) IBOutlet SDLLabel *sdlStatusLabel;
32 | @property (nonatomic, weak) IBOutlet UISwitch *serverSwitch;
33 |
34 | @end
35 |
36 | @implementation SDLStatusViewController
37 |
38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
39 | if (self = [super initWithCoder:aDecoder]) {
40 | self.title = @"Status";
41 |
42 | [self sdl_registerForNotifications];
43 | }
44 | return self;
45 | }
46 |
47 | - (void)viewDidLoad {
48 | [super viewDidLoad];
49 |
50 | [self usbDisconnected:nil];
51 | [self tcpServerDisconnected:nil];
52 | [self serverToggleAction:nil];
53 | }
54 |
55 | - (void)sdl_registerForNotifications {
56 | [self addSelfObserverForNotificationNamed:SDLRelayManagerUSBConnectedNotification
57 | selector:@selector(usbConnected:)];
58 | [self addSelfObserverForNotificationNamed:SDLRelayManagerUSBDisconnectedNotification
59 | selector:@selector(usbDisconnected:)];
60 | [self addSelfObserverForNotificationNamed:SDLRelayManagerDataSessionEstablishedNotification
61 | selector:@selector(dataSessionEstablished:)];
62 | [self addSelfObserverForNotificationNamed:SDLRelayManagerControlSessionEstablishedNotification
63 | selector:@selector(controlSessionEstablished:)];
64 | [self addSelfObserverForNotificationNamed:SDLRelayManagerTCPServerStartedNotification
65 | selector:@selector(tcpServerStarted:)];
66 | [self addSelfObserverForNotificationNamed:SDLRelayManagerTCPServerConnectedNotification
67 | selector:@selector(tcpServerConnected:)];
68 | [self addSelfObserverForNotificationNamed:SDLRelayManagerTCPServerDisconnectedNotification
69 | selector:@selector(tcpServerDisconnected:)];
70 | }
71 |
72 | #pragma mark - Actions
73 | - (IBAction)serverToggleAction:(id)selector {
74 | if ([_serverSwitch isOn]) {
75 | [self.relayManager startTCPServer];
76 | } else {
77 | [self.relayManager stopTCPServer];
78 | [_serverStatusLabel updateToErrorStateWithString:SDLStatusNotStarted];
79 | _serverAddressLabel.text = @"";
80 | _serverPortLabel.text = @"";
81 | }
82 | }
83 |
84 | #pragma mark - Notifications
85 | - (void)usbConnected:(NSNotification*)notification {
86 | [_usbStatusLabel updateToSuccessStateWithString:SDLStatusConnected];
87 | }
88 |
89 | - (void)usbDisconnected:(NSNotification*)notification {
90 | [_usbStatusLabel updateToErrorStateWithString:SDLStatusDisconnected];
91 | [_eaStatusLabel updateToErrorStateWithString:SDLStatusClosed];
92 | }
93 |
94 | - (void)controlSessionEstablished:(NSNotification*)notification {
95 | [_eaStatusLabel updateToWaitingStateWithString:SDLStatusConnecting];
96 | }
97 |
98 | - (void)dataSessionEstablished:(NSNotification*)notification {
99 | [_eaStatusLabel updateToSuccessStateWithString:SDLStatusConnected];
100 | }
101 |
102 | - (void)tcpServerStarted:(NSNotification *)notification {
103 | NSString* ip = SDLStatusError;
104 | NSString* port = SDLStatusError;
105 |
106 | id notificationObject = notification.userInfo[SDLNotificationInfoKey];
107 | if ([notificationObject isKindOfClass:[SDLTCPConnection class]]) {
108 | SDLTCPConnection* connection = (SDLTCPConnection*)notificationObject;
109 | ip = connection.ipAddress;
110 | port = [NSString stringWithFormat:@"%lu", (unsigned long)connection.port];
111 | }
112 |
113 | [_serverStatusLabel updateToSuccessStateWithString:SDLStatusAvailable];
114 | _serverAddressLabel.text = ip;
115 | _serverPortLabel.text = port;
116 | }
117 |
118 | - (void)tcpServerConnected:(NSNotification *)notification {
119 | [_sdlStatusLabel updateToSuccessStateWithString:SDLStatusConnected];
120 | }
121 |
122 | - (void)tcpServerDisconnected:(NSNotification *)notification {
123 | [_sdlStatusLabel updateToErrorStateWithString:SDLStatusDisconnected];
124 | }
125 |
126 | #pragma mark - Private
127 | #pragma mark Getters
128 | - (SDLRelayManager*)relayManager {
129 | return [SDLRelayManager sharedManager];
130 | }
131 |
132 | @end
133 |
--------------------------------------------------------------------------------
/Relay/SDLTCPConnection.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLTCPConnection.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | /**
9 | * Object to store current connection properties.
10 | */
11 | @interface SDLTCPConnection : NSObject
12 |
13 | /**
14 | * Convenience initializer for creating a SDLTCPConnection object. This class will retrieve
15 | * the IP Address from the current connected network.
16 | * *
17 | * @return instance of SDLTCPConnection
18 | */
19 | + (instancetype)connection;
20 |
21 | /**
22 | * The IP Address the connection is using.
23 | */
24 | @property (nonatomic, readonly) NSString* ipAddress;
25 |
26 | /**
27 | * The port the connection is using.
28 | */
29 | @property (nonatomic, readonly) NSUInteger port;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Relay/SDLTCPConnection.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLTCPConnection.m
3 | // Relay
4 | //
5 |
6 | #import "SDLTCPConnection.h"
7 |
8 | #import
9 | #import
10 | #import
11 |
12 | @implementation SDLTCPConnection
13 |
14 | + (instancetype)connection {
15 | return [[SDLTCPConnection alloc] init];
16 | }
17 |
18 | #pragma mark - Getters
19 | - (NSString*)ipAddress {
20 | NSString *address = @"error";
21 | struct ifaddrs *interfaces = NULL;
22 | struct ifaddrs *temp_addr = NULL;
23 | int success = 0;
24 | // retrieve the current interfaces - returns 0 on success
25 | success = getifaddrs(&interfaces);
26 | if (success == 0) {
27 | // Loop through linked list of interfaces
28 | temp_addr = interfaces;
29 | while (temp_addr != NULL) {
30 | if (temp_addr->ifa_addr->sa_family == AF_INET) {
31 | // Check if interface is en0 which is the wifi connection on the iPhone
32 | if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
33 | // Get NSString from C String
34 | address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
35 | }
36 | }
37 |
38 | temp_addr = temp_addr->ifa_next;
39 | }
40 | }
41 | // Free memory
42 | freeifaddrs(interfaces);
43 | return address;
44 | }
45 |
46 | - (NSUInteger)port {
47 | return 2776;
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Relay/SDLTCPServer.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLTCPServer.h
3 | // Relay
4 | //
5 |
6 | #import
7 | #import "SDLTCPConnection.h"
8 |
9 | @class SDLTCPServer;
10 |
11 | /**
12 | * Describes the protocol of a TCPServer delegate.
13 | */
14 | @protocol SDLTCPServerDelegate
15 |
16 | /**
17 | * Called when TCPServer has data from the client.
18 | *
19 | * @param server Shared SDLTCPServer
20 | * @param data The data to be sent.
21 | */
22 | - (void)TCPServer:(SDLTCPServer*)server didReceiveData:(NSData*)data;
23 |
24 | /**
25 | * Called when TCPServer has established an available server.
26 | *
27 | * @param server Shared SDLTCPServer
28 | * @param connection Object storing connection information.
29 | */
30 | - (void)TCPServer:(SDLTCPServer*)server hasAvailableConnection:(SDLTCPConnection*)connection;
31 |
32 | /**
33 | * Called when TCPServer has accepted an incoming connection.
34 | *
35 | * @param server Shared SDLTCPServer
36 | */
37 | - (void)TCPServerDidConnect:(SDLTCPServer *)server;
38 |
39 | /**
40 | * Called when TCPServer has closed the current connection.
41 | *
42 | * @param server Shared SDLTCPServer
43 | */
44 | - (void)TCPServerDidDisconnect:(SDLTCPServer *)server;
45 |
46 | @end
47 |
48 | /**
49 | * TCP Server.
50 | */
51 | @interface SDLTCPServer : NSObject
52 |
53 | /**
54 | * The delegate for TCPServer callbacks.
55 | */
56 | @property (weak) id delegate;
57 |
58 | /**
59 | * Create the TCPServer object.
60 | *
61 | * @return Singleton instance of SDLTCPServer.
62 | */
63 | + (instancetype)sharedService;
64 |
65 | /**
66 | * Establish a new server session.
67 | */
68 | - (void)startServer;
69 |
70 | /**
71 | * Close the current server session.
72 | */
73 | - (void)stopServer;
74 |
75 | /**
76 | * Sends data to client.
77 | *
78 | * @param data The data to be sent.
79 | */
80 | - (void)sendData:(NSData*)data;
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/Relay/SDLTCPServer.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLTCPServer.m
3 | // Relay
4 | //
5 |
6 | #import "SDLTCPServer.h"
7 |
8 | #import "NSStream+Connection.h"
9 |
10 | #import
11 |
12 | @interface SDLTCPServer ()
13 |
14 | @property (strong, nonatomic) NSInputStream *inputStream;
15 | @property (strong, nonatomic) NSOutputStream *outputStream;
16 | @property CFSocketRef socket;
17 | @property dispatch_queue_t tcpLinkQueue;
18 |
19 | @end
20 |
21 | @implementation SDLTCPServer
22 |
23 | + (instancetype)sharedService {
24 | static SDLTCPServer *sharedService = nil;
25 | static dispatch_once_t onceToken;
26 | dispatch_once(&onceToken, ^{
27 | sharedService = [[SDLTCPServer alloc] init];
28 | });
29 |
30 | return sharedService;
31 | }
32 |
33 | - (instancetype)init {
34 | if (self = [super init]) {
35 | self.tcpLinkQueue = dispatch_queue_create("com.queue.tcpLinkQueue", NULL);
36 | }
37 |
38 | return self;
39 | }
40 |
41 |
42 | #pragma mark Server lifecycle methods
43 | - (void)startServer {
44 | CFSocketContext context = {0, (__bridge void *)self, NULL, NULL, NULL};
45 |
46 | self.socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, &openConnection, &context);
47 |
48 | SDLTCPConnection* connection = [SDLTCPConnection connection];
49 |
50 | struct sockaddr_in sin;
51 |
52 | memset(&sin, 0, sizeof(sin));
53 | sin.sin_len = sizeof(sin);
54 | sin.sin_family = AF_INET; /* address family */
55 | sin.sin_port = htons(connection.port);
56 | sin.sin_addr.s_addr = INADDR_ANY;
57 |
58 | // allow address/port to be reused after server is closed and restarted
59 | setsockopt(CFSocketGetNative(self.socket), SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
60 | setsockopt(CFSocketGetNative(self.socket), SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int));
61 |
62 | CFDataRef sincfd = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&sin, sizeof(sin));
63 |
64 | CFSocketSetAddress(self.socket, sincfd);
65 | CFRelease(sincfd);
66 |
67 | CFRunLoopSourceRef socketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.socket, 0);
68 | CFRunLoopAddSource(CFRunLoopGetCurrent(), socketSource, kCFRunLoopDefaultMode);
69 |
70 | [self.delegate TCPServer:self hasAvailableConnection:connection];
71 |
72 | CFRelease(socketSource);
73 | }
74 |
75 | static void openConnection(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
76 | CFReadStreamRef readStream;
77 | CFWriteStreamRef writeStream;
78 |
79 | CFSocketNativeHandle *socketNumber = (int *)data;
80 |
81 | CFStreamCreatePairWithSocket(kCFAllocatorDefault, *socketNumber, &readStream, &writeStream);
82 |
83 | SDLTCPServer *weakServer = (__bridge SDLTCPServer *)info;
84 | weakServer.inputStream = (__bridge_transfer NSInputStream *)readStream;
85 | weakServer.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
86 |
87 | [weakServer.inputStream openStreamWithDelegate:weakServer];
88 | [weakServer.outputStream openStreamWithDelegate:weakServer];
89 |
90 | [weakServer.delegate TCPServerDidConnect:weakServer];
91 | }
92 |
93 | - (void)stopServer {
94 | [self.inputStream closeStream];
95 | [self.outputStream closeStream];
96 |
97 | if (self.socket) {
98 | CFSocketInvalidate(self.socket);
99 | CFRelease(self.socket);
100 | self.socket = nil;
101 | }
102 | }
103 |
104 |
105 | #pragma mark Handle stream events
106 |
107 | - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
108 | switch (eventCode) {
109 | case NSStreamEventNone:
110 | case NSStreamEventOpenCompleted:
111 | case NSStreamEventHasSpaceAvailable:
112 | case NSStreamEventErrorOccurred:
113 | // no-op
114 | break;
115 | case NSStreamEventHasBytesAvailable:
116 | [self sdl_processIncomingBytesForStream:aStream];
117 | break;
118 | case NSStreamEventEndEncountered:
119 | [aStream close];
120 | [aStream removeFromRunLoop:[NSRunLoop currentRunLoop]
121 | forMode:NSDefaultRunLoopMode];
122 | [self.delegate TCPServerDidDisconnect:self];
123 | break;
124 | default: {
125 | break;
126 | }
127 | }
128 | }
129 |
130 | - (void)sdl_processIncomingBytesForStream:(NSStream *)theStream {
131 | uint8_t buf[1024];
132 | NSInteger len = 0;
133 | len = [(NSInputStream *)theStream read:buf maxLength:1024];
134 | if (len > 0) {
135 | NSData* data = [NSData dataWithBytes:buf length:len];
136 |
137 | [self.delegate TCPServer:self didReceiveData:data];
138 | }
139 | }
140 |
141 | - (void)sendData:(NSData *)data {
142 | dispatch_async(self.tcpLinkQueue, ^{
143 | NSData *localData = [[NSData alloc] initWithData:data];
144 |
145 | while (localData != nil) {
146 | if (self.outputStream.hasSpaceAvailable) {
147 | [self.outputStream write:[localData bytes] maxLength:[localData length]];
148 | localData = nil;
149 | }
150 | }
151 | });
152 | }
153 |
154 | @end
155 |
--------------------------------------------------------------------------------
/Relay/SDLiAPManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // SDLiAPManager.h
3 | // Relay
4 | //
5 |
6 | #import
7 |
8 | @class SDLiAPManager;
9 |
10 | /**
11 | * Describes the protocol of an SDLiAPManager delegate.
12 | */
13 | @protocol SDLiAPManagerDelegate
14 |
15 | /**
16 | * Called when SDLiAPManager has connected to an external accessory via USB.
17 | *
18 | * @param iAPManager Shared SDLiAPManager
19 | */
20 | - (void)iAPManagerUSBConnected:(SDLiAPManager*)manager;
21 |
22 | /**
23 | * Called when SDLiAPManager has disconnected from an external accessory.
24 | *
25 | * @param iAPManager Shared SDLiAPManager
26 | */
27 | - (void)iAPManagerUSBDisconnected:(SDLiAPManager *)manager;
28 |
29 | /**
30 | * Called when SDLiAPManager has established a control session with a TDK.
31 | *
32 | * @param iAPManager Shared SDLiAPManager
33 | */
34 | - (void)iAPManagerControlSessionEstablished:(SDLiAPManager*)manager;
35 |
36 | /**
37 | * Called when SDLiAPManager has established a data session with a TDK.
38 | *
39 | * @param iAPManager Shared SDLiAPManager
40 | */
41 | - (void)iAPManagerDataSessionEstablished:(SDLiAPManager*)manager;
42 |
43 | /**
44 | * Called when SDLiAPManager has data to send to send to the SDL app.
45 | *
46 | * @param iAPManager Shared SDLiAPManager
47 | * @param data The data to be sent.
48 | */
49 | - (void)iAPManager:(SDLiAPManager*)manager didReceiveData:(NSData*)data;
50 |
51 | @end
52 |
53 | /**
54 | * External Accessory session.
55 | */
56 | @interface SDLiAPManager : NSObject
57 |
58 | /**
59 | * The delegate for SDLiAPManager callbacks.
60 | */
61 | @property (weak) id delegate;
62 |
63 | /**
64 | * Create the SDLiAPManager object.
65 | *
66 | * @return Instance of SDLiAPManager.
67 | */
68 | + (instancetype)sharedService;
69 |
70 | /**
71 | * Called when SDLiAPManager has data to send to a TDK.
72 | *
73 | * @param data The data to be sent.
74 | */
75 | - (void)sendData:(NSData*)data;
76 |
77 | /**
78 | * Close the current external accessory session, attempt to create a new session.
79 | */
80 | - (void)restartEASession;
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/Relay/SDLiAPManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDLiAPManager.m
3 | // Relay
4 | //
5 |
6 | #import "SDLiAPManager.h"
7 |
8 | #import "EASession+Streams.h"
9 | #import "NSObject+Notifications.h"
10 |
11 | #import
12 | #import
13 |
14 | static NSString* const ControlProtocolString = @"com.smartdevicelink.prot0";
15 | static NSString* const IndexedProtocolString = @"com.smartdevicelink.prot%i";
16 | static NSString* const LegacyProtocolString = @"com.ford.sync.prot0";
17 |
18 | @interface SDLiAPManager ()
19 |
20 | @property BOOL protocolRerouted;
21 | @property (nonatomic, strong) EASession* session;
22 |
23 | @property dispatch_queue_t iAPManagerQueue;
24 |
25 | @end
26 |
27 | @implementation SDLiAPManager
28 | + (instancetype)sharedService {
29 | static SDLiAPManager *sharedService = nil;
30 | static dispatch_once_t onceToken;
31 | dispatch_once(&onceToken, ^{
32 | sharedService = [[SDLiAPManager alloc] init];
33 | });
34 |
35 | return sharedService;
36 | }
37 |
38 | - (instancetype)init {
39 | self = [super init];
40 |
41 | if (self) {
42 | _protocolRerouted = NO;
43 |
44 | // register for EAAccessory notifications
45 | [self addSelfObserverForNotificationNamed:EAAccessoryDidConnectNotification
46 | selector:@selector(accessoryDidConnect:)];
47 | [self addSelfObserverForNotificationNamed:EAAccessoryDidDisconnectNotification
48 | selector:@selector(accessoryDidDisconnect:)];
49 | [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
50 |
51 | // monitor battery state
52 | [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
53 | [self addSelfObserverForNotificationNamed:UIDeviceBatteryStateDidChangeNotification
54 | selector:@selector(batteryStateChanged:)];
55 |
56 | // attempt to connect on app start
57 | [self performSelector:@selector(sdl_connectToEAOnAppStart) withObject:nil afterDelay:2.0];
58 |
59 | self.iAPManagerQueue = dispatch_queue_create("com.queue.iapManager", NULL);
60 | }
61 |
62 | return self;
63 | }
64 |
65 | #pragma mark - Notifications
66 | - (void)accessoryDidConnect:(NSNotification *)notification {
67 | if (!self.session) {
68 | [self.delegate iAPManagerUSBConnected:self];
69 | self.session = [self sdl_openSessionForProtocol:ControlProtocolString];
70 | }
71 | }
72 |
73 | - (void)accessoryDidDisconnect:(NSNotification *)notification {
74 | [self.delegate iAPManagerUSBDisconnected:self];
75 | [self sdl_closeSession];
76 | }
77 |
78 | - (void)batteryStateChanged:(NSNotification*)notification {
79 | if ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateUnplugged) {
80 | [self accessoryDidDisconnect:nil];
81 | self.protocolRerouted = NO;
82 | } else if ([[UIDevice currentDevice] batteryState] != UIDeviceBatteryStateUnplugged
83 | && !self.session) {
84 | [self accessoryDidConnect:nil];
85 | }
86 | }
87 |
88 | #pragma mark - Public Functions
89 | - (void)sendData:(NSData *)data {
90 | dispatch_async(self.iAPManagerQueue, ^{
91 | NSData *localData = [[NSData alloc] initWithData:data];
92 |
93 | while (localData != nil) {
94 | if (self.session.outputStream.hasSpaceAvailable) {
95 | [self.session.outputStream write:[localData bytes] maxLength:[localData length]];
96 | localData = nil;
97 | }
98 | }
99 | });
100 | }
101 |
102 | - (void)restartEASession {
103 | if (self.session) {
104 | [self sdl_closeSession];
105 | }
106 |
107 |
108 | if ([[UIDevice currentDevice] batteryState] != UIDeviceBatteryStateUnplugged && self.session == nil) {
109 | [self accessoryDidConnect:nil];
110 | }
111 | }
112 |
113 | #pragma mark - Delegates
114 | #pragma mark NSStream
115 | - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
116 | switch (eventCode) {
117 | case NSStreamEventHasBytesAvailable:
118 | [self sdl_processIncomingBytesForStream:aStream];
119 | break;
120 | case NSStreamEventEndEncountered:
121 | [aStream close];
122 | [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
123 | break;
124 | case NSStreamEventNone:
125 | case NSStreamEventOpenCompleted:
126 | case NSStreamEventHasSpaceAvailable:
127 | break;
128 | default:
129 | break;
130 | }
131 | }
132 |
133 |
134 | #pragma mark - Private
135 | #pragma mark Helpers
136 | - (void)sdl_connectToEAOnAppStart {
137 | if ([[UIDevice currentDevice] batteryState] != UIDeviceBatteryStateUnplugged) {
138 | [self accessoryDidConnect:nil];
139 | }
140 | }
141 |
142 | - (void)sdl_processIncomingBytesForStream:(NSStream *)aStream {
143 | while ([self.session.inputStream hasBytesAvailable]) {
144 | uint8_t buf[1024];
145 | NSInteger len = 0;
146 | len = [(NSInputStream *)aStream read:buf maxLength:1024];
147 |
148 | if (len > 0) {
149 | if (self.protocolRerouted) {
150 | NSData* incomingData = [NSData dataWithBytes:buf length:len];
151 | [self.delegate iAPManager:self didReceiveData:incomingData];
152 | } else {
153 | NSData *recBytes = [[NSData alloc] initWithBytes:buf length:len];
154 | int protocol = CFSwapInt32LittleToHost(*(int *)([recBytes bytes]));
155 | NSString *newProtocol = [NSString stringWithFormat:IndexedProtocolString, protocol];
156 | [self sdl_closeSession];
157 | self.session = [self sdl_openSessionForProtocol:newProtocol];
158 | self.protocolRerouted = YES;
159 | }
160 | }
161 | }
162 | }
163 |
164 | - (EASession *)sdl_openSessionForProtocol:(NSString *)protocolString {
165 | NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
166 | EAAccessory *accessory = nil;
167 | EASession *session = nil;
168 |
169 | for (EAAccessory *obj in accessories) {
170 | if ([[obj protocolStrings] containsObject:protocolString]) {
171 | accessory = obj;
172 | break;
173 | } else {
174 | if ([[obj protocolStrings] containsObject:LegacyProtocolString] && ![[obj protocolStrings] containsObject:ControlProtocolString]) {
175 | protocolString = LegacyProtocolString;
176 | self.protocolRerouted = YES;
177 | accessory = obj;
178 | break;
179 | }
180 | }
181 | }
182 |
183 | if (accessory) {
184 | session = [[EASession alloc] initWithAccessory:accessory
185 | forProtocol:protocolString];
186 |
187 | if (session) {
188 | [session openStreamsWithDelegate:self];
189 | if ([protocolString isEqualToString:ControlProtocolString]) {
190 | [self.delegate iAPManagerControlSessionEstablished:self];
191 | } else {
192 | [self.delegate iAPManagerDataSessionEstablished:self];
193 | }
194 | }
195 | }
196 |
197 | accessory = nil;
198 |
199 | return session;
200 | }
201 |
202 | - (void)sdl_closeSession {
203 | [self.session closeStreams];
204 |
205 | _protocolRerouted = NO;
206 | self.session = nil;
207 | }
208 |
209 | @end
210 |
--------------------------------------------------------------------------------
/Relay/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Relay
4 | //
5 | // Created by James Sokoll on 10/29/15.
6 | // Copyright © 2016 Ford Motor Company. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------