Possible reasons for QSSLSocket to stop sending/receiving data - facebook

Can anybody give me a possible reason why my QSSLSocket would stop sending and receiving data without firing a stateChanged or disconnected signal.
My app starts a thread which connects to Facebooks XMPP server, authenticates and then goes into a while loop calling waitForReadyReady(10000) and then if this returns true it will read the data. Sometimes, After a while this call to waitForReadyReady will never return true even though there should be something to read and if I try to send data at this point the server won't receive anything.
I am sending pings to the XMPP server and can detect when this has happened after not receiving a reply to my ping but it's not really usable as an app until I get to the bottom of why communication is sometimes just breaking down between client and server.
Can anybody offer any insights please?

Related

swift HTTP Requests

I have created an instant messenger chat application where by messages are posted to my server via a php service and stored in a mysql backed.
If a user has their 'inbox' page open and a new message is received I would need to update the table to show any new messages. The way I am doing this at the moment is by sending an http request to the server every 5 seconds.
As you can imagine this is pretty inefficient. What methods are available which would be more suitable and less resource heavy?
I have looked at keep alive connections and web sockets but Im not sure which direction I should be going in?
any help much appreciated!
Your approach is called polling, which is not efficient because it consumes more electricity from your phone and you have extra load to your server. The correct way of doing it is though Apple's push notification. Here is the tutorial for that. Basically your server will send request to Apple's push notification center when a new message is received.
However in your case it's a bit more complicated. You want this notification only after user entering the mail page. So you need to tweak your php server to send notification only after user entered the mail page. In this case you are sending only one request to your server telling it to start sending notifications, instead of constantly polling your server

xmpp messages are lost when client connection lost suddently

I am using ejabberd server and ios xmppframework.
there are two clients, A and B.
When A and B are online, A can send message to B successfully.
If B is offline, B can receive the message when B is online again.
But when B is suddenly/unexpectedly lost connection, such as manually close wi-fi, the message sent by A is lost. B will never
receive this message.
I guess the reason is that B lost connection suddenly and the server still think B is online. Thus the offline message does work under this condition.
So my question is how to ensure the message that sent by A will be received by B? To ensure there is no messages lost.
I've spent the last week trying to track down missing messages in my XMPPFramework and eJabberd messaging app. Here are the full steps I went through to guarantee message delivery and what the effects of each step are.
Mod_offline
In the ejabberd.yml config file ensure that you have this in the access rules:
max_user_offline_messages:
admin: 5000
all: 100
and this in the modules section:
mod_offline:
access_max_user_messages: max_user_offline_messages
When the server knows the recipient of a message is offline they will store it and deliver it when they re-connect.
Ping (XEP-199)
xmppPing = XMPPPing()
xmppPing.respondsToQueries = true
xmppPing.activate(xmppStream)
xmppAutoPing = XMPPAutoPing()
xmppAutoPing.pingInterval = 2 * 60
xmppAutoPing.pingTimeout = 10.0
xmppAutoPing.activate(xmppStream)
Ping acts like a heartbeat so the server knows when the user is offline but didn't disconnect normally. It's a good idea to not rely on this by disconnecting on applicationDidEnterBackground but when the client looses connectivity or the stream disconnects for unknown reasons there is a window of time where a client is offline but the server doesn't know it yet because the ping wasn't expected until sometime in the future. In this scenario the message isn't delivered and isn't stored for offline delivery.
Stream Management (XEP-198)
xmppStreamManagement = XMPPStreamManagement(storage: XMPPStreamManagementMemoryStorage(), dispatchQueue: dispatch_get_main_queue())
xmppStreamManagement.autoResume = true
xmppStreamManagement.addDelegate(self, delegateQueue: dispatch_get_main_queue())
xmppStreamManagement.activate(xmppStream)
and then in xmppStreamDidAuthenticate
xmppStreamManagement.enableStreamManagementWithResumption(true, maxTimeout: 100)
Nearly there. The final step is to go back to the ejabberd.yml and add this line to the listening ports section underneath access: c2s:
resend_on_timeout: true
Stream Management adds req/akn handshakes after each message delivery. On it's own it won't have any effect on the server side unless that resend_on_timeout is set (which it isn't by default on eJabberd).
There is a final edge case which needs to be considered when the acknowledgement of a received message doesn't get to the server and it decides to hold it for offline delivery. The next time the client logs in they are likely to get a duplicate message. To handle this we set that delegate for the XMPPStreamManager. Implement the xmppStreamManagement getIsHandled: and if the message has a chat body set the isHandledPtr to false. When you construct an outbound message add an xmppElement with a unique id:
let xmppMessage = XMPPMessage(type: "chat", to: partnerJID)
let xmppElement = DDXMLElement(name: "message")
xmppElement.addAttributeWithName("id", stringValue: xmppStream.generateUUID())
xmppElement.addAttributeWithName("type", stringValue: "chat")
xmppElement.addAttributeWithName("to", stringValue: partnerJID.bare())
xmppMessage.addBody(message)
xmppMessage.addChild(xmppElement)
xmppMessage.addReceiptRequest()
xmppStream.sendElement(xmppMessage)
Then when you receive a message, inform the stream manager that the message has been handled with xmppStreamManager.markHandledStanzaId(message.from().resource)
The purpose of this final step is to establish a unique identifier that you can add to the XMPPMessageArchivingCoreDataStorage and check for duplicates before displaying.
I guess the reason is that B lost connection suddenly and the server
still think B is online. Thus the offline message does work under this
condition
Yes you are absolutely correct,this is well known limitation of TCP connections.
There are two approaches to your problem
1 Server side
As I can see you are using ejabbed as XMPP server you can implement
mod_ping , Enabling this module will enables server side
heartbeat[ping] ,in case of broken connection to server[ejabbed] will
try to send heartbeat to connection and will detect connection is lost
between server and client. Use of this approach has one
drawback,module mod_ping has property called ping_interval which
states how often to send heartbeat to connected clients, here lower
limit is 32 seconds any value below 32 is ignored by ejabbed,means
you have 32 seconds black window in which messages can be lost if user
is sowing as online
2 Client side
From client side you can implement Message Delivery Receipts
mechanism .With each Chat message send a receipt to receiver user of
as soon as receiver user receives message send back this receipt
id. This way you can detect that your message is actually delivered to
receiver. If you don't receive such acknowledgement between certain
time interval you can show user as offline locally(on mobile
phone),store any further messages to this user as offline message
locally[in SQLLight database ],and wait for offline presence stanza for that user
,as soon as you receive offline presence stanza it means that server
has finally detected connection to that user is lost and makes user
status as offline ,now you can send all messages to that user ,which
will be again stored as offline messages on server.This is best
approach to avoid black-window.
Conclusion
You can either use Approach 2 and design you client such way ,you can also use Approach 1 along with approach 2 to minimize server broken connection detraction time.
If B goes offline suddenly then user A have to check if B is online/offline while sending message to user B. If user B is offline then user A have to upload that message on Server using Web service. And user B have to call web service on below function.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
So user B will get that all offline message which was lost due to connection Lost.
At last, I use Ping together with Stream Management:
http://xmpp.org/extensions/xep-0198.html
This problem is solved.

XMPP offline message(s) received every time user logs in

I am working with XMPP server, backend enabled with BuddyCloud. Everything is working fine.
My only issue is, when someone sends me an offline message (means when I am offline), so when I logs in again and send my Presence all the offline message start receiving.
Scenario:
If I am offline, and someone sends me the message, I should not receive it and it happens correctly. And when I came online, I should receive that message. Which I receives and it is correct till this point.
Now when I come online any next time, I always receive that message, which I have received already. Tell me If I am still not clear with my issue.
Can anyone help me?

Using FIX protocol to connect to the broker

I am currently trying to build a program using FIX protocol to communicate with a broker (currenex). I sent my (self-generated) logon message to the server and got something back.
This is what I sent
8=FIX.4.49=8835=A49=xxxxxxxx56=CNX34=152=20140718-11:40:18.24498=0108=30141=Y554=xxxxxx10=128
(the SenderCompID and the password were replaced)
and I got
8=FIX.4.49=7635=A34=149=CNX52=20140718-11:40:33.22456=xxxxxxxx141=Y98=0108=3010=1458=FIX.4.49=7035=h34=249=CNX52=20140718-11:40:33.22656=xxxxxxxx336=0340=210=128
back from the server.
I think I built the logon message correct (or did I?). But when I sent a second request MarketDataRequest
8=FIX.4.49=13735=V49=xxxxxxxx56=CNX34=252=20140718-11:42:53.504262=363263=1264=0265=1266=N267=2269=1269=0146=155=GBP/USD554=xxxx10=013
I had no response at all. I asked the broker and they said the connection dropped right away every time after I logged in.
I thought it was some connection problem and I tried using RESTClient (Postman) to send the message but the result was the same.
Could any one take a look at my messages and point out if there is something stupid please?
All I need is the real-time exchange rate so a simple FIX message example will be very helpful. Thanks a lot!
Regards,
Bo
Your logon response message says that your trading session is open (340=2) so it's not broker-side problem. I think your program disconnects TCP/IP connection from server after login message. FIX protocol insists that TCP/IP connection must be kept alive during the whole FIX session - otherwise the session will be closed. So you need rewrite your program to keep connection alive and just send there yor requests and listen for responses. Don't close the connection.
Try using Minifix tool which will maintain the heartbeats and the session connection.
Ideally for a 35=V request you should get
35=W = Market Data-Snapshot/Full Refresh
35=X = Market Data-Incremental Refresh
35=Y = Market Data Request Reject
you get a 35=3 (reject) or 35=4 (or a seq reset) in response to a 35=A request.

What is better practice for error notification by email

This question is language independent.
I have an application that handles requests in a loop. During this loop for each request multiple actions are taken. These actions are sitting inside try / catch / log blocks.
I am now extending this to notify administrators of severe errors via email.
This is all very easy, except for one thing. We are relying on the client/s to implement their own email delivery redundancy, and I know from experience there will always be one client who just has one SMTP exchange server, and this is bound to go down from time to time.
So here is the dilemma:
Scenario 1 (don't handle the error during failed send) - when I send an email to admin and SMTP is down it will break the app (app will stop running, and additional loops will stop processing, because the error is unhandled) This means that the error reporting which was supposed to be beneficial to the app suddenly becomes the reason why 99/100 requests don't get processed because there was an issue with request 1.
Scenario 2 (handle the exception during failed send) - this means that I surround send code in try/catch/log blocks, great! the application processes all requests 99 of them, except one, but the admin now has no notification of this one error via email because when it tried to send SMTP was down, and that error was simply logged to the application log, the admin who doesn't check this log for days (even weeks) at a time now has no way to know that error took place.
So is there a win/win way to solve this problem or am I always going to be at a loss, and in the mercy of SMTP being up. Remember it is out of our scope to manage email server redundancy.
Extend scenario 2 to keep a record of which entries in the application log didn't get sent via email, and periodically poll this log for unsent entries and try to resend them - eventually the smtp service will be available again. (You might want to stop any resent errors from going back in the resend queue tho...)
I would suggest the "win-win" way would be to have a server admin who actually administrates the server, rather than one who is entirely unreachable when his mail server is down, and doesn't bother to check up on it afterwards to see if he missed any notifications.