I started with xmppFramework with iOS and locally ejabberd server (running on "localhost:5280"). I logged in ejabberd server by using "username: admin, password: admin"
I checked my code correctly and add delegate "XMPPStreamDelegate".
I face problem that my code call the delegate function "xmppStreamWillConnect" but it didn't call "xmppStreamDidConnect".
Genrally, what may cause this issue?
My code:
func connect() {
if !self.xmppStream.isDisconnected() {
return
}
self.xmppStream.hostName = "localhost:5280"
self.xmppStream.myJID = XMPPJID(string:"admin#localhost")
try! self.xmppStream.connect(withTimeout: 10)
if self.xmppStream.isConnected(){
print(true)
}
self.xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicy.required
self.xmppStream.supportsStartTLS()
print("ok")
}
func xmppStreamWillConnect(_ sender: XMPPStream!) {
print("will connect ")
}
func xmppStreamDidConnect(_ stream: XMPPStream!) {
print("Stream: Connected")
try! stream.authenticate(withPassword: self.password)
}
The result of printing is :
ok
willConnect
If you make localhost, surly it will not work.
Simulator will run on the localhost and you cannot run both on the same localhost.
Related
I'm using HydraSDK to create VPN app. I logged in successfully, get country (servers) list and when try to connect to closest server I receive error
Restart VPN error: Error Domain=com.anchorfree.hydra.manager Code=4
"failed_to_connect"
UserInfo={NSLocalizedDescription=failed_to_connect}
I'm using this code to start VPN
private func startVPN() {
self.hydraClient.start(location: nil) { (e, _) in
if let ex = e {
print("Restart VPN error: \(ex)")
} else {
print("Restart VPN success, country: \(self.country?.code ?? "unknown")")
}
}
}
Problem was in extension info.plist
I am trying to connect programmatically to a VPN. I got the code below on this website: http://blog.moatazthenervous.com/create-a-vpn-connection-with-apple-swift/
I am trying to develop a command line application for macOS to connect programatically to a VPN.
import Foundation
import NetworkExtension
class VPN {
let vpnManager = NEVPNManager.shared();
let userName: String;
let passString: String;
let secret: String;
let server: String;
init (_ user: String, _ pass: String, _ secret: String, _ server: String){
userName = user
passString = pass
self.secret = secret
self.server = server
}
private var vpnLoadHandler: (Error?) -> Void { return
{ (error:Error?) in
if ((error) != nil) {
print("Could not load VPN Configurations")
return;
}
print ("me! me! ")
let p = NEVPNProtocolIPSec()
p.username = self.userName
p.serverAddress = self.server
p.authenticationMethod = NEVPNIKEAuthenticationMethod.sharedSecret
let kcs = KeychainService();
kcs.save(key: "SHARED", value: self.secret )
kcs.save(key: "VPN_PASSWORD", value: self.passString)
p.sharedSecretReference = kcs.load(key: "SHARED")
p.passwordReference = kcs.load(key: "VPN_PASSWORD")
p.useExtendedAuthentication = true
p.disconnectOnSleep = false
p.localIdentifier = "uio"
self.vpnManager.protocolConfiguration = p
self.vpnManager.localizedDescription = "Contensi"
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: self.vpnSaveHandler)
} }
private var vpnSaveHandler: (Error?) -> Void { return
{ (error:Error?) in
if (error != nil) {
print("Could not save VPN Configurations")
return
} else {
do {
try self.vpnManager.connection.startVPNTunnel()
} catch let error {
print("Error starting VPN Connection \(error.localizedDescription)");
}
}
}
}
public func connectVPN() {
//For no known reason the process of saving/loading the VPN configurations fails.On the 2nd time it works
do {
self.vpnManager.loadFromPreferences(completionHandler: self.vpnLoadHandler)
// self.vpnManager.saveToPreferences(completionHandler: nil)
}
}
public func disconnectVPN() ->Void {
self.vpnManager.connection.stopVPNTunnel()
}
public func status() -> NEVPNStatus {
return vpnManager.connection.status
}
}
My problem is that I my completion handlers are not working. Take the function connectVPN(), for instance. It's completion handler is vpnLoadHandler. However, I never get that handler executed. See the print statement on the handler? Nothing ever gets printed.
Reading Apple's documentation, I know that I have to configure XCode with an entitlement in order to allow VPN - I haven't got the "capabilities"-tab, so I don't know how to add that entitlement. I am not sure if that's the problem, since the app compiles file and executes. I just don't get the completion handler to execute.
So, basically:
why isn't the handler being called? And what can I do to debug?
Could this be due the lack an entitlement to allow the configuration of a personal vpn in xcode? If so, how can I configure that?
Best,
Francis
UPDATE I actually managed to create the entitlements file, and I guess it has the proper settings to allow a personal vpn. So I guess that part is solved. But why isn't the completion handler called?
I need to send the status of the network to some analytics server, so I need to send it once the app starts. I tried to use Alamofire, but I usually get Unknown status, if there is some sort of delay it shows the right status :
These code would run in my AppDelegate (didFinishLaunchingWithOptions):
AFNetworkReachabilityManager.shared().startMonitoring()
AFNetworkReachabilityManager.shared().localizedNetworkReachabilityStatusString()
What is the best way to get the right status right away?
UPDATE 1:
I updated my code and tried to use completion handler, but why when I use this method it will print multiple YES?
connectedCompletionBlock({ connected in
if connected {
print("YES")
} else {
print("NO")
}
})
class func connectedCompletionBlock(_ completion: #escaping (_ connected: Bool) -> Void) {
AFNetworkReachabilityManager.shared().startMonitoring()
AFNetworkReachabilityManager.shared().setReachabilityStatusChange({ status in
var isConnected = false
let wifi = AFNetworkReachabilityStatus.reachableViaWiFi
let wwan = AFNetworkReachabilityStatus.reachableViaWWAN
if ( status == wifi || status == wwan) {
con = true
}
AFNetworkReachabilityManager.shared().stopMonitoring()
completion(isConnected)
})
}
Ok since nobody didn't answer, I think it's good to share the solution with you. The issue was this: I was calling this method on didFinishLaunchingWithOptions, and since it takes sometime for the Alamofire to figure out the connection status it would return unknown! I called it on applicationDidBecomeActive and it works fine now.
On version 2, the sender app was able to send messages.
func deviceManager(_ deviceManager: GCKDeviceManager!,
didConnectToCastApplication
applicationMetadata: GCKApplicationMetadata!,
sessionID: String!,
launchedApplication: Bool) {
deviceManager.add(self.textChannel)
}
However, the API says that we are now using GCKSessionManager instead of GCKDeviceManager.
The API says I must have a GCKSession add the textChannel, which I did here:
Once the session starts, I add the textChannel (because sessionManager.currentCastSession was nil before the session started).
func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) {
if session.device == connectionQueue {
connectionQueue = nil
}
self.sessionManager!.currentCastSession!.add(textChannel)
print("")
}
Meanwhile, I send the text message in another function:
let result = self.textChannel.sendTextMessage("\(self.textField.text)", error: &error)
But the result is always false, and the error is always "Channel is not connected or is not registered with a session".
In addition, when I do:
print("isConnected1 \(self.textChannel.isConnected)")
the result is false.
Do you know what other steps I am missing for it to be connected?
Just learned that it was an issue of my namespace. It connects now.
Problem was the namespace wasn't matching the namespace from my receiver code.
fileprivate lazy var textChannel:TextChannel = {
return TextChannel(namespace: NAMESPACE)
}()
We are trying to get minimal example for XMPPFramework to run.
Consider this simple class:
import Foundation
import XMPPFramework
class Connection: NSObject, XMPPStreamDelegate {
let stream: XMPPStream
override init() {
self.stream = XMPPStream()!
}
func connectToServer(timeout: TimeInterval) {
stream.addDelegate(self, delegateQueue: DispatchQueue.main)
stream.myJID = XMPPJID(string: "myuser")
stream.hostName = "myserver.tld"
stream.hostPort = 5222
do {
try stream.connect(withTimeout: timeout)
}
catch {
print(error)
}
}
func xmppStreamWillConnect(_ sender: XMPPStream!) {
print("will connect")
}
func xmppStreamDidConnect(_ sender: XMPPStream!) {
print("did connect")
self.stream.disconnect()
}
}
And this simple test class:
import Foundation
import XCTest
#testable import MyModule
class ConnectionTests: XCTestCase {
func testConnect() {
let connection = Connection()
print("Try to connect")
let expectation = self.expectation(description: "connect")
connection.connectToServer(timeout: 3)
self.waitForExpectations(timeout: 5)
}
}
I expect this output:
Try to connect
will connect
did connect
<5s timeout since I don't fulfill>
If, by accident, my XMPP server did not react favorably to my request, I'd like to see:
Try to connect
will connect
<some error message>
If the XMPP server did not reply (quickly), I'd expect:
Try to connect
will connect
<3s timeout reached>
However, I'm getting none of these but instead:
Try to connect
will connect
<5s timeout since I don't fulfill>
What is going on?
Here is what I gather.
XCTest waits on DispatchQueue.main.
We can control where the delegates run; it does not seem to matter whether DispatchQueue.main or DispatchQueue(label: "test", qos: .userInitiated, attributes: .concurrent) is used.
I can trace execution up to dispatch_sync(xmppQueue, block); in XMPPStream.connectWithTimeout where xmppQueue is a new queue with label xmpp; the block seems to be executed completely, too.
So I don't understand who blocks whom here, and how to prevent it from happening.
The problem is three-fold:
The expectation times out because it's never fulfilled.
We never see "did connect" because it never got that far.
We didn't understand enough of XMPP(Framework) to understand where to plug in.
We implement some additional delegate methods:
func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
print("socket did connect")
}
func xmppStreamDidStartNegotiation(_ sender: XMPPStream!) {
print("negotiation started")
}
...
func xmppStream(_ sender: XMPPStream!, didReceiveError error: DDXMLElement!) {
print("error: \(error)")
}
func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!) {
print("disconnected")
self.afterConnection()
}
Here, self.afterConnection is a function passed to connectToServer as additional parameter.
And we change in the test:
connection.connectToServer(timeout: 3, then: { expectation.fulfill() })
Now the test terminates in an orderly fashion with this output:
Try to connect
will connect
socket did connect
negotiation started
disconnected
error: Optional(<stream:error xmlns:stream="http://etherx.jabber.org/streams"><host-unknown xmlns="urn:ietf:params:xml:ns:xmpp-streams"/></stream:error>)
So it's a problem with the server, after all. We needed to implement the correct delegates to diagnose the issue; we'd have expected stream.connect to throw an error in such a case!
make singleton of that class as follows:
static let sharedInstance = Connection();
now call it as follows:
func testConnect() {
Connection.sharedInstance.connectToServer(timeout: 3);
}