XMPP framework error: socket closed by remote peer - ios

I am trying to connect to the ejabbered server with no SSL:
BOOL success;
if (![AppDelegate.xmppStream isConnected])
success = [AppDelegate.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error];
but, the server returns the error
socket closed by remote peer
In the:
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
I tried the following:
xmppPing = [XMPPPing new];
xmppPing.respondsToQueries = YES;
[xmppPing activate:xmppStream];
Also:
xmppAutoPing = [XMPPAutoPing new];
xmppAutoPing.pingInterval = 0.5;
[xmppAutoPing activate:xmppStream];
Also:
xmppStream.keepAliveInterval = 0.5;
But the error still exists. Is it something that I missed?
Log shows that connection accepted but returns the error:
(<0.455.0>:ejabberd_listener:281) : (#Port<0.2757>) Accepted
connection {{111,111,111,111},55012} -> {{222,222,222,222},5222}

Related

Socket closed by remote peer Error when server disconnected in iOS

I am using GCDAsyncSocket for connecting to socket. App works fine till phone gets lock.
When phone gets unlock then socketDidDisconnect gets call with error (Socket closed by remote peer). there I am reconnecting to server but socket gets disconnected every time. Is there any way to reconnect to socket?
Here is my Code :
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(#"Socket Disconnected===== %#",err);
[self serverConnection];
}
-(void)serverConnection
{
asyncSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if (![asyncSocket connectToHost:ipAddress onPort:portNumber error:&err]){
NSLog(#"Error in acceptOnPort:error: -> %#", err);
}
else
{
NSLog(#"Socket Connecting");
}
}

Can you setup listener socket on localhost with iOS?

I'm trying to setup a listenerSocket on localhost using GCDAsyncSocket for iOS device.
In the socketDidDisconnect delegate I either get error Code=49 for trying with port 0 (which I'm hoping would find the first available free port).
Or if I use a port no then I get error Code=61 for trying to connect with localhost.
- (IBAction)start:(id)sender {
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if(![asyncSocket connectToHost:#"localhost" onPort:0 error:&err])
{
NSLog(#"Connect Error: %#", err);
}
}
#pragma mark – delegate
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(#"socketDidDisconnect");
if (err) {
NSLog(#"Socket Error: %#", err);
// Error in connect function:
// NSPOSIXErrorDomain Code=49 "Can't assign requested address" - onPort:0
// NSPOSIXErrorDomain Code=61 "Connection refused" - connectToHost:#"localhost"
}
}
connectToHost will act as the client-side of the connection. You want to read the Writing a server section of the help page:
listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![listenSocket acceptOnPort:port error:&error])
{
NSLog(#"I goofed: %#", error);
}
- (void)socket:(GCDAsyncSocket *)sender didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
// The "sender" parameter is the listenSocket we created.
// The "newSocket" is a new instance of GCDAsyncSocket.
// It represents the accepted incoming client connection.
// Do server stuff with newSocket...
}
However you need to know the port to use (if you let the system decide what port to use then how is a client supposed to know how to connect to the server?). Also the port will almost certainly need to be > 1024 (out of the reserved port range). However I haven't ever tried to create a Server on iOS.

Ejabberd + iOS XMPPFramework.. not connecting to server

I am attempting to connect to an ejabberd server hosted here:
198.199.106.154:5280
The issue is that this block of code is not calling iOS XMPP Framework's delegate:
- (void)xmppStreamDidConnect:(XMPPStream *)sender
I am confident that my server has made a connection because the following log appears on the server after the code has executed:
- (void)setupStream {
xmppStream = [[XMPPStream alloc] init];
xmppStream.hostName = #"198.199.106.154";
xmppStream.hostPort = 5280;
NSString * jabberID = [[NSString alloc] initWithFormat:#"admin#%#", #"localhost"];
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
NSError *error2 = nil;
[xmppStream connectWithTimeout:10.0f error:&error2];
NSLog(#"here is the connect error %#", [error2 localizedDescription]); //NO ERROR IS CALLED!
dispatch_async(dispatch_get_main_queue(), ^{
[self authWithServer];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(authWithServer) userInfo:nil repeats:YES];
//I GET THE FOLLOWING MESSAGE:: "Please wait until the stream is connected"
});
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
I am absolutely lost folks! Any guidance would be immensely helpful
XMPPFramework uses standard XMPP TCP connection (which handled by ejabberd_c2s module usually on 5222 port), but you are trying connect to http-bind module, which is not implemented in XMPPFramework.

XMPPFramework - Connect via SSL on Openfire

I'm trying to connect my users via SSL from my iOS XMPP chat client to Openfire server.
In my iOS client:
- (void)setupStream
{
...
// BOOL values for security settings
customCertEvaluation = NO;
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
}
In my Openfire server's Security Settings > Client Connection Security, I've set:
Required - Clients can only connect to the server using secured connections.
Thus, the following delegate method will be called:
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
NSString *expectedCertName = [xmppStream.myJID domain];
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
if (allowSSLHostNameMismatch)
[settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];
else
if (expectedCertName)
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
I attempted this solution from this thread: XMPPFramework TLS/SSL connection with Openfire
However, when I run my application and attempt to connect to the server, I'd receive this error:
Security option unavailable - kCFStreamSSLAllowsAnyRoot - You must use manual trust evaluation
I looked through the GCDAsyncSocket class and realized kCFStreamSSLAllowsAnyRoot is stated as deprecated. An NSAssert was implemented to deliberately throw the error.
Next, I decided to change my BOOL values as such:
- (void)setupStream
{
...
// BOOL values for security settings
// Manually evaluate trust
customCertEvaluation = YES;
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
}
This time, again, no connection could be made to the server but, no error was prompted.
I could connect to Openfire fine if I changed the Client Connection Security back to the original setting > Optional. But, I wouldn't be connected via SSL as indicated by a lock icon beside every user's status in Client Sessions.
My Android client (using Smack API for XMPP) connects to Openfire via SSL without issues. So I'm wondering if there's workaround I have to implement for my iOS client using XMPPFramework.
I would greatly appreciate any advices.
Explanation
In the latest version of XMPP (after April 22), you can no longer use allowSelfSignedCertificates = YES with the following:
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];`
This is because kCFStreamSSLAllowsAnyRoot & SSLSetAllowsAnyRoot have been deprecated.
/*
* ==== The following UNAVAILABLE KEYS are: (with throw an exception)
* - kCFStreamSSLAllowsAnyRoot (UNAVAILABLE)
* You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust).
* Corresponding deprecated method: SSLSetAllowsAnyRoot
*/
See XMPPFramework/GCDAsyncSocket.h & Deprecated Secure Transport Functions.
Solution
Go to Openfire server > Security Settings > Client Connection Security
Check: Required - Clients can only connect to the server using secured connections.
Define variable in AppDelegate
BOOL customCertEvaluation;
Set variable in setupStream
- (void)setupStream
{
...
customCertEvaluation = YES;
}
Set security settings in willSecureWithSettings
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
/*
* Properly secure your connection by setting kCFStreamSSLPeerName
* to your server domain name
*/
[settings setObject:xmppStream.myJID.domain forKey:(NSString *)kCFStreamSSLPeerName];
/*
* Use manual trust evaluation
* as stated in the XMPPFramework/GCDAsyncSocket code documentation
*/
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
}
Validate peer manually
/*
* This is only called if the stream is secured with settings that include:
* - GCDAsyncSocketManuallyEvaluateTrust == YES
* That is, if a delegate implements xmppStream:willSecureWithSettings:, and plugs in that key/value pair.
*/
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
/* Custom validation for your certificate on server should be performed */
completionHandler(YES); // After this line, SSL connection will be established
}
I was having the same issue, after i updated my XMPPFramework. After days of trying to find out what went wrong i came across this question, but the solution didn't work for me.
Here is what worked for me. The problem seems to originate from your xmppStream.startTLSPolicy. Setting startTLSPolicy explicitly worked for me.
xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyPreferred; // or
xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyRequired;
Here is an EXPLANATION of why it works.
In XMPPStream's handleStreamFeatures method, it turns out that. If your XMPP Server doesn't return starttls as 'required' and you don't set startTLSPolicy(default=XMPPStreamStartTLSPolicyAllowed) explicitly. The client will just do a normal connection and not a TLS one.
Here is section of code(for reference) in XMPPStream that is doing the checks.
/**
* This method is called anytime we receive the server's stream features.
* This method looks at the stream features, and handles any requirements so communication can continue.
**/
- (void)handleStreamFeatures
{
NSAssert(dispatch_get_specific(xmppQueueTag), #"Invoked on incorrect queue");
XMPPLogTrace();
// Extract the stream features
NSXMLElement *features = [rootElement elementForName:#"stream:features"];
// Check to see if TLS is required
// Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found)
NSXMLElement *f_starttls = [features elementForName:#"starttls" xmlns:#"urn:ietf:params:xml:ns:xmpp-tls"];
if (f_starttls)
{
if ([f_starttls elementForName:#"required"] || [self startTLSPolicy] >= XMPPStreamStartTLSPolicyPreferred)
{
// TLS is required for this connection
// Update state
state = STATE_XMPP_STARTTLS_1;
// Send the startTLS XML request
[self sendStartTLSRequest];
// We do not mark the stream as secure yet.
// We're waiting to receive the <proceed/> response from the
// server before we actually start the TLS handshake.
// We're already listening for the response...
return;
}
}
else if (![self isSecure] && [self startTLSPolicy] == XMPPStreamStartTLSPolicyRequired)
{
// We must abort the connection as the server doesn't support our requirements.
NSString *errMsg = #"The server does not support startTLS. And the startTLSPolicy is Required.";
NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
otherError = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info];
// Close the TCP connection.
[self disconnect];
// The socketDidDisconnect:withError: method will handle everything else
return;
}
// Check to see if resource binding is required
// Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found)
NSXMLElement *f_bind = [features elementForName:#"bind" xmlns:#"urn:ietf:params:xml:ns:xmpp-bind"];
if (f_bind)
{
// Start the binding process
[self startBinding];
// We're already listening for the response...
return;
}
// It looks like all has gone well, and the connection should be ready to use now
state = STATE_XMPP_CONNECTED;
if (![self isAuthenticated])
{
[self setupKeepAliveTimer];
// Notify delegates
[multicastDelegate xmppStreamDidConnect:self];
}
}
You are trying to use outdated API, check iPhoneXMPP sample for the new one - https://github.com/robbiehanson/XMPPFramework/commit/73f3c35a930b91d27e62bc19e91d9cdcc02c6e42
customCertEvaluation = YES;
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
try these this might help

XMPPFramework Socket closed by remote peer

I'm trying to implement the XMPPFramework by robbiehanson. The problem is, that I get the following error message:
Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote peer" UserInfo=0x9517440 {NSLocalizedDescription=Socket closed by remote peer}
I already tried everything I could find on the internet (XMPPPing etc.) but nothing could fix my problem. Here is the code I'm using:
- (void)connect {
stream = [[XMPPStream alloc] init];
[stream setEnableBackgroundingSocket:YES];
[stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
reconnect = [[XMPPReconnect alloc] init];
[reconnect activate:stream];
[stream setHostName:_hostName];
[stream setPort:5223];
[stream setMyJID:[XMPPJID jidWithString:_username];
NSError *e;
if(![stream connectWithTimeout:20 error:&e]) {
NSLog(#"%#", e);
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
NSError *e;
[sender authenticateWithPassword:_password];
if(e) {
NSLog(#"%#", e);
}
}
I'm getting this error message immediately, not after several seconds. I already thought it might be, because our server requires SSL, but the only solution I found for SSL was running [stream secureConnection:nil]; and this only works if connected.
I also never get the -xmppStreamDidConnect: delegate method.
stream oldSchoolSecureConnectWithTimeout: will connect to 5223/SSL

Resources