How to connect to Socket.IO swift? - swift

I am having trouble connecting to Socket.IO chat..
import UIKit
import SocketIO
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let manager = SocketManager(socketURL: URL(string: "wss://socket-io-chat.now.sh/socket.io/")!, config: [.log(true), .compress])
let socket = manager.defaultSocket
socket.on(clientEvent: .connect) {data, ack in
print("socket connected")
}
socket.on("new message") {data, ack in
print("new Messages")
}
socket.connect()
}
}
I am using the latest socket.io library and already added app transport in info.plist.
here's what the logs says..
2018-01-22 16:56:46.316676+0800 ExampleSocket[6963:2231315] LOG SocketEngine: Got message: 40
2018-01-22 16:56:46.317249+0800 ExampleSocket[6963:2231315] LOG SocketEngine: Writing poll: has data: false
2018-01-22 16:56:46.317771+0800 ExampleSocket[6963:2231315] LOG SocketEnginePolling: Sending poll: as type: 2
2018-01-22 16:56:46.323959+0800 ExampleSocket[6963:2231318] TIC Read Status [2:0x0]: 1:57
2018-01-22 16:56:46.324082+0800 ExampleSocket[6963:2231318] TIC Read Status [2:0x0]: 1:57
2018-01-22 16:56:46.330099+0800 ExampleSocket[6963:2231315] LOG SocketEnginePolling: Created POST string: 1:2
2018-01-22 16:56:46.330615+0800 ExampleSocket[6963:2231315] LOG SocketEnginePolling: POSTing
2018-01-22 16:56:46.330744+0800 ExampleSocket[6963:2231315] LOG SocketEngine: Engine is being released

try the below code:
var socketClient: SocketIOClient!
if let url = URL(string: "wss://socket-io-chat.now.sh/socket.io/") {
let socketClient = SocketIOClient(socketURL: url, config: [.log(true),.forcePolling(true)])
socketClient.connect()
}
socketClient.onAny { (socEvent) in
if let status = socEvent.items as? [SocketIO.SocketIOClientStatus] {
if let first = status.first {
switch first {
case .connected:
print("Socket: connected")
break
case .disconnected:
print("Socket: disconnected")
break
case .notConnected:
print("Socket: notConnected")
break
case .connecting:
print("Socket: connecting")
break
}
}
}
}

Related

Reading eID with NFC crushing in production build but it works in debug mode

I have a React-Native application and I implemented a 3rd party eID NFC Reader SDK. This 3rd SDK is using NFCPassportReader library and CoreNFC package also. I'm trying to read Turkish Citizenship eID with this module. My problem this module is working properly in debug mode but It's crushing in release version. I've added a crush log related to this issue and I've added tagReaderSession implementation code. I've added my "com.apple.developer.nfc.readersession.iso7816.select-identifiers" configuration code also.
Does anybody have an idea about that problem?
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Codes: 0x0000000000000001, 0x0000000000000000
VM Region Info: 0 is not in any region. Bytes before following region: 4340301824
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 102b3c000-10603c000 [ 53.0M] r-x/r-x SM=COW ...ePieMobileDev
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [9236]
Triggered by Thread: 8
Thread 8 name: Dispatch queue: com.apple.corenfc.readersession.delegate
Thread 8 Crashed:
public func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
Log.debug( "tagReaderSession:didDetect - \(tags[0])" )
if tags.count > 1 {
Log.debug( "tagReaderSession:more than 1 tag detected! - \(tags)" )
let errorMessage = NFCViewDisplayMessage.error(.MoreThanOneTagFound)
self.invalidateSession(errorMessage: errorMessage, error: NFCPassportReaderError.MoreThanOneTagFound)
return
}
let tag = tags.first!
var passportTag: NFCISO7816Tag
switch tags.first! {
case let .iso7816(tag):
passportTag = tag
default:
Log.debug( "tagReaderSession:invalid tag detected!!!" )
let errorMessage = NFCViewDisplayMessage.error(NFCPassportReaderError.TagNotValid)
self.invalidateSession(errorMessage:errorMessage, error: NFCPassportReaderError.TagNotValid)
return
}
// Connect to tag
Log.debug( "tagReaderSession:connecting to tag - \(tag)" )
session.connect(to: tag) { [unowned self] (error: Error?) in
if error != nil {
Log.debug( "tagReaderSession:failed to connect to tag - \(error?.localizedDescription ?? "Unknown error")" )
let errorMessage = NFCViewDisplayMessage.error(NFCPassportReaderError.ConnectionError)
self.invalidateSession(errorMessage: errorMessage, error: NFCPassportReaderError.ConnectionError)
return
}
Log.debug( "tagReaderSession:connected to tag - starting authentication" )
self.updateReaderSessionMessage( alertMessage: NFCViewDisplayMessage.authenticatingWithPassport(0) )
self.tagReader = TagReader(tag:passportTag)
if let newAmount = self.dataAmountToReadOverride {
self.tagReader?.overrideDataAmountToRead(newAmount: newAmount)
}
self.tagReader!.progress = { [unowned self] (progress) in
if let dgId = self.currentlyReadingDataGroup {
self.updateReaderSessionMessage( alertMessage: NFCViewDisplayMessage.readingDataGroupProgress(dgId, progress) )
} else {
self.updateReaderSessionMessage( alertMessage: NFCViewDisplayMessage.authenticatingWithPassport(progress) )
}
}
DispatchQueue.global().async {
self.startReading( )
}
}
}
<key>NFCReaderUsageDescription</key>
<string>Read the NFC chip of ePassports</string>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
</array>
Video recording of this issue:
https://vimeo.com/784270897
I can run the application in debug mode without any problems, but when I start reading nfc in release mode, the application crashes.

Disable checking https certificate: Swift

I trying to make a https call to my web service from a ios application.
So I used:
//...
func sendMessage() {
let defaults = UserDefaults.standard
let url = URL(string: defaults.string(forKey:"host")! + ":" + defaults.string(forKey:"port")! + "/garage")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let parameters: [String: String] = [
"identifier": defaults.string(forKey: "secret")!
]
request.httpBody = parameters.percentEncoded()
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else { // check for fundamental networking error
print("error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
let responseString = String(data: data, encoding: .utf8)
debugPrint("responseString = \(responseString)")
}
task.resume()
}
//...
extension ViewController: URLSessionDelegate {
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
//Trust the certificate even if not valid
let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, urlCredential)
}
}
I installed the ca at on the target system too. But I also try to ignore the certificate.
I always get following error instead of a response:
2020-07-03 14:41:27.742361+0200 GarageOpener[5177:223905] ATS failed system trust
2020-07-03 14:41:27.742484+0200 GarageOpener[5177:223905] Connection 1: system TLS Trust evaluation failed(-9802)
2020-07-03 14:41:27.742642+0200 GarageOpener[5177:223905] Connection 1: TLS Trust encountered error 3:-9802
2020-07-03 14:41:27.742776+0200 GarageOpener[5177:223905] Connection 1: encountered error(3:-9802)
2020-07-03 14:41:27.746709+0200 GarageOpener[5177:223905] Task <63EC553D-485C-478D-813B-AF0C1D3D3223>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
2020-07-03 14:41:27.749778+0200 GarageOpener[5177:223905] Task <63EC553D-485C-478D-813B-AF0C1D3D3223>.<1> finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600002b187e0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
), NSUnderlyingError=0x600001773cf0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600002b187e0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://subdomain.mydomain.de:443/garage, NSErrorFailingURLStringKey=https://subdomain.mydomain.de:443/garage, NSErrorClientCertificateStateKey=0}
"3"
error Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600002b187e0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
), NSUnderlyingError=0x600001773cf0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600002b187e0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://subdomain.mydomain.de:443/garage, NSErrorFailingURLStringKey=https://subdomain.mydomain.de:443/garage, NSErrorClientCertificateStateKey=0}
I know ignore isn't a good idea and it would allow man in the middle attacks. But at least the connection would be encrypted. And if somebody has the ability to make a man in the middle attack in my WLAN I have bigger problems than this.
Please help ;)
Okay, maybe it's time to answer my question.
The first I did wrong was the signing of the certificate.
I just set the domain/ip-address of the server in the Common Name (CN) entry of the certificate.
That is an outdated solution. You need to set the subjectAltName for modern applications: http://wiki.cacert.org/FAQ/subjectAltName .
But it feels very ugly to use the instructions from that wiki site to self-sign a certificate. So I used the awesome tool certstrap: https://github.com/square/certstrap
After that:
I passed the server.key and server.crt (private and signed public
key) to the server and configured everything fine.
I downloaded the CA (ca.crt) that I created (on the iphone).
You need to go to the settings->general->profiles and trust your
certificate.
Finally, you need to trust the certificate again:
https://support.apple.com/en-us/HT204477#:~:text=If%20you%20want%20to%20turn,Mobile%20Device%20Management%20(MDM).
Done. My application worked!

Curl command works on CLI but Alamofire fails to authenticate

Here is the curl command that works:
curl -d {"Key1":"value1"} -k -vvvv --request POST --header "Content-Type: application/json" --key KEY.pem --cacert CRT.pem --cert KEY.pem "URL"
How do I translate this to Alamofire request command? I get the authentication failure errors:
Connection 1: default TLS Trust evaluation failed(-9807)
2020-04-09 01:51:46.604692-0600 CertificatePinningExample[7192:1891639] Connection 1: TLS Trust encountered error 3:-9807
2020-04-09 01:51:46.604879-0600 CertificatePinningExample[7192:1891639] Connection 1: encountered error(3:-9807)
2020-04-09 01:51:46.606672-0600 CertificatePinningExample[7192:1891639] Connection 1: unable to determine interface type without an established connection
2020-04-09 01:51:46.650936-0600 CertificatePinningExample[7192:1891639] Task <9E539D4B-9694-426E-B382-6350044743B0>.<1> HTTP load failed, 0/0 bytes (error code: -1202 [3:-9807])
2020-04-09 01:51:46.662507-0600 CertificatePinningExample[7192:1891652] Task <9E539D4B-9694-426E-B382-6350044743B0>.<1> finished with error [-1202] Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “BLAH” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
// Alamofire code to fire up the request
override func viewDidLoad() {
super.viewDidLoad()
let evaluators = [
"SERVER_IP":
PinnedCertificatesTrustEvaluator(certificates:
getCertificates()
)
]
let session = Session(
serverTrustManager: ServerTrustManager(evaluators: evaluators)
)
let url = URL(string: "URL_TO_HIT")!
//enableCertificatePinning()
var dict: NSDictionary = ["SessionId":""]
var data: Data = Data.init()
do {
data = try JSONSerialization.data(withJSONObject: dict, options: [])
} catch{
data = "".data(using: .utf8)!
}
//let data = try JSONSerialization.data(withJSONObject: dict, options: [])
let request = AF.request(url, method: .post)
// 2
request.responseJSON { (data) in
print(data)
}
}
private func getCertificates() -> [SecCertificate] {
let url = Bundle.main.url(forResource: "ExampleCert", withExtension: "der")!
let localCertificate = try! Data(contentsOf: url) as CFData
guard let certificate = SecCertificateCreateWithData(nil, localCertificate)
else { return [] }
return [certificate]
}
My concern is: Alamofire is asking for only one cert vs I am using three cert flags in curl. How do I translate Alamofire request to the same as curl?

SSAccountStore: Unable to get the local account. error = Error Domain=SSErrorDomain Code=100

I am having trouble getting access to the users Apple Music.
The error I am getting is
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
2019-02-04 19:14:37.250467+0900 SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
2019-02-04 19:14:37.252008+0900 [core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
2019-02-04 19:14:37.252051+0900 SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
2019-02-04 19:14:37.253604+0900 SSAccountStore: Unable to get the local account. error = Error Domain=SSErrorDomain Code=100 "Cannot connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store}
However the weird part of this code is that I am also able to retrieve the Music User Token.
Is there sth that I am missing?
Any help is appreciated.
static func auth(){
let cloudServiceController = SKCloudServiceController()
let developerToken = "abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyz"
SKCloudServiceController.requestAuthorization { status in
guard status == .authorized else { return }
}
cloudServiceController.requestCapabilities { capabilities, error in
guard capabilities.contains(.musicCatalogPlayback) else { return }
}
cloudServiceController.requestUserToken(forDeveloperToken: developerToken, completionHandler: { token, error in
guard let token = token else { return }
UserDefaults.standard.set(token, forKey: "MUSIC_USER_TOKEN")
UserDefaults.standard.set(developerToken, forKey: "DEVELOPER_TOKEN")
print("Music User Token:", token)
})
}
I think you have to call
cloudServiceController.requestUserToken
once user has authorised after completion handler for SKCloudServiceController.requestAuthorization
I was having this same issue until I removed Bearer from the beginning of developerToken.
OP's code example has developerToken set to "abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyz", so I can only assume if OP is including Bearer at the beginning or not.
So to be more clear, this is what I was doing before:
asyncAskMyServerToGenerateMyAppleMusicDeveloperJWTDevToken { rawDevToken in
let formattedDeveloperToken = "Bearer \(rawDevToken)"
SKCloudServiceController().requestUserToken(forDeveloperToken: formattedDeveloperToken)
{ possibleToken, _ in
if let userMusicToken = possibleToken
{
YayIGotIt.forTheWin(userMusicToken)
}
}
}
And this is what I did to make it actually work:
asyncAskMyServerToGenerateMyAppleMusicDeveloperJWTDevToken { rawDevToken in
//Not prepending "Bearer " anymore
SKCloudServiceController().requestUserToken(forDeveloperToken: rawDevToken)
{ possibleToken, _ in
if let userMusicToken = possibleToken
{
YayIGotIt.forTheWin(userMusicToken) //This actually fires now
}
}
}

GCDAsyncSocket on browser connects and disconnects immediately with "Socket closed by remote peer" error

I am really new to Network programming and using GCDAsyncSocket for the first time. I am trying to implement an iOS app where 1 device acts a host and other devices(browsers) connect to it. I am using NSNetService/NSNetServiceBrowser for publishing/browsing part.
Now, my client/browser resolves the host's address properly and try to connect to it using following code:
func netServiceDidResolveAddress(sender: NSNetService) {
// Connect with Service
if (self.connectWithService(sender, hostname: sender.hostName!)) {
println("Connecting with service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port) and hostname: \(sender.hostName!)");
} else {
println("Unable to connect with service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port)");
}
}
private func connectWithService(service: NSNetService, hostname: String) ->Bool {
var isConnecting:Bool = false;
if (self.browserSocket == nil || !(self.browserSocket?.isConnected)!) {
// Initialize Socket
self.browserSocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue());
// Connect
while (!isConnecting){
var error: NSError?;
println("Connecting port : \(service.port) and hostname: \(hostname)");
if (self.browserSocket.connectToHost(hostname, onPort: UInt16(service.port), error: &error)) {
isConnecting = true;
} else if (error != nil) {
println("Unable to connect to address. Error \(error) with user info \(error?.userInfo)");
}
}
} else {
println("Connecting is: \(self.browserSocket.isConnected)");
isConnecting = self.browserSocket.isConnected;
}
return isConnecting;
}
// GCDAsyncSocketDelegate methods
func socket(sock: GCDAsyncSocket!, didConnectToHost host: String!, port: UInt16) {
println("Socket: \(sock) Did connect to host: \(host) on port:\(port)");
// Start Reading
sock.readDataToLength(UInt(sizeof(UInt64)), withTimeout: -1.0, tag: 0);
}
func socketDidDisconnect(sock: GCDAsyncSocket!, withError err: NSError!) {
println("Socket \(sock) did disconnect with error \(err?)");
}
Following is the Publisher code:
override func viewDidLoad() {
super.viewDidLoad()
let barButton = UIBarButtonItem(title: "Stop Publishing", style: .Done, target: self, action: "stopPublishing");
self.navigationItem.rightBarButtonItem = barButton;
// Publish the service
self.publishService();
}
// MARK: Button callbacks
private func publishService() {
// Initialize GCDAsyncSocket
self.socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue());
// Start listening for incoming connections
var error: NSError?;
if (self.socket.acceptOnPort(0, error: &error)) {
// Initialize Service
self.service = NSNetService(domain: "local.", type: "_mpstest._tcp", name: UIDevice.currentDevice().name, port:0);
// Configure Service
self.service.delegate = self;
self.service.includesPeerToPeer = true;
self.service.publishWithOptions(.ListenForConnections);
} else {
println("Unable to create socket. Error \(error?.description) with user info \(error?.userInfo)");
}
}
Now, the client connects with the host and hits following method:
func socket(sock: GCDAsyncSocket!, didConnectToHost host: String!, port: UInt16) {
But then it immediately disconnects hitting following method with ErrorCode =7 "Socket closed by remote peer"
func socketDidDisconnect(sock: GCDAsyncSocket!, withError err: NSError!) {
Following is the console log from Browser device:
Service found is : <NSNetService 0x15e2f710> local. _mpstest._tcp. iPad 30
Connecting port : 50797 and hostname: iPad-30.local.
Connecting with service: domainName= local., type= _mpstest._tcp., name= iPad 30, onPort= 50797 and hostname: iPad-30.local.
Socket <GCDAsyncSocket: 0x15d80020> did disconnect with error Optional(Error Domain=kCFStreamErrorDomainNetDB Code=8 "nodename nor servname provided, or not known" UserInfo=0x15e3c7a0 {NSLocalizedDescription=nodename nor servname provided, or not known})
Connecting port : 50797 and hostname: iPad-30.local.
Connecting with service: domainName= local., type= _mpstest._tcp., name= iPad 30, onPort= 50797 and hostname: iPad-30.local.
Socket: <GCDAsyncSocket: 0x15e59c20> Did connect to host: 169.254.78.98 on port:50797
Socket <GCDAsyncSocket: 0x15e59c20> did disconnect with error Optional(Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote peer" UserInfo=0x15e5b070 {NSLocalizedDescription=Socket closed by remote peer})
Host socket delegate methods are never hit.
I am really stuck here. Any help as to what am I doing wrong here would be great.
Thanks
Vik
I had the same error as well! After much searching and pulling my hair out I stumbled upon a solution that has something to do with the weak declaration for GCDAsyncSocket, ARC in Swift understands the declaration "__weak" in GCDAsyncSocket.m as an excuse to deallocate the socket as quickly as possible.
Search for the keyword "__weak" in your project and remove all the references.
found this solution at: Delegate not getting set