madmag77 / STUNClient

Stun client written in Swift for exploration of NAT traversal details (iOS/macOs/Linux)
MIT License
22 stars 7 forks source link

Swift

StunClient

Simple Stun client that connects to Stun server using UDP and asks for your external IP and Port. Can be used both from iOS and macOS.

Requirements

Installation

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler.

Just add Stun Client to the dependencies of your Package.swift

dependencies: [
    .package(url: "https://github.com/madmag77/STUNClient.git", .upToNextMajor(from: "1.0.3"))
]

or using Xcode Menu: File->Swift Packages->Add Package Dependency where just insert https://github.com/madmag77/STUNClient.git in the search line.

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. Add StunClient in the Podfile:

pod 'StunClient'

iOS Example project with StunClient as a CocoaPod you can find here: https://github.com/madmag77/STUNClient/tree/master/iOSExampleWithPods

Manually

In terminal:

git clone https://github.com/madmag77/STUNClient
cd STUNClient 
swift run

You should see the following output:

LOG: Start Who Am I procedure with Stun server 64.233.163.127:19302 from local port 14135
LOG: XOR_MAPPED_ADDRESS 
 Family: 1 
 Port: 54668  
 Address: xxx.xxx.xxx.xxx
COMPLETED, my address: xxx.xxx.xxx.xxx my port: 54668

Then you can try iOS example:

cd iOSExample 
open STUNClient.xcodeproj

Choose simulator and run the project.

Usage

This is how Stun Client can be used (Google Stun IP address and port are being used here):

client = StunClient(stunIpAddress: "64.233.163.127", stunPort: 19302, localPort: UInt16(14135))
let successCallback: (String, Int) -> () = { [weak self] (myAddress: String, myPort: Int) in
        guard let self = self else { return }

        print("COMPLETED, my address: \(myAddress) my port: \(myPort)")
}
let errorCallback: (StunError) -> () = { [weak self] error in
            guard let self = self else { return }

            print("ERROR: \(error.localizedDescription)")
    }
let verboseCallback: (String) -> () = { [weak self] logText in
            guard let _ = self else { return }

            print("LOG: \(logText)")
    }

client
    .whoAmI()
    .ifWhoAmISuccessful(successCallback)
    .ifError(errorCallback)
    .verbose(verboseCallback)
    .start()