4

I'm trying to write own jabber bot on c++/gloox. Everything goes fine, but when internet connection is down - bot thinks that it's still connected, and when connection is up again - of course bot doesn't respond to any message.

Each time since bot is successfully connected gloox' recv() returns ConnNoError, even if interface is down and cable unplugged.

Tried use blocking and non-blocking gloox' connection and recv() and all was without any result. Periodic checks of availability of xmpp server in different thread is not seems like a good idea, so how to properly check is bot connected right now or no?

If it's not possible to do with gloox only - please point me on some good method, but let it be availible in unix.

user427852
  • 41
  • 2

2 Answers2

3

I have the same question, and found the reason why recv always retrun ConnNoError. Here is what I found. When the connection is established, the recv calls a funciton named dataAvailable In ConnectionTCPBase.cpp which return

( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 ) && FD_ISSET( m_socket, &fds ) != 0 )

searching google, I found this thread, it said FD_ISSET( m_socket, &fds ) would detect the socket is readble but not is closed ... Return value of FD_ISSET( m_socket, &fds ) is always 0, even the network is down. In such case, the return value of dataAvailable is false, so the code below finally returns ConnNoError in recv.

if( !dataAvailable( timeout ) )
{
  m_recvMutex.unlock();
  return ConnNoError;
}

I don't know whether it is a bug or what, seems not.

Later I tried another way, write to the socket directly, and this will cause a SIGPIPE if the socket is closed, catch that signal, then use cleanup to disconnect.

I finally figure out a graceful solution to this problem, using heartbeat.

in the gloox thread, call heartBeat(), where m_pClient is an pointer to a instance of gloox::Client

void    CXmpp::heartBeat()
{
    m_pClient->xmppPing(m_pClient->jid(), this);
    if (++heart) > 3) {
        m_pClient->disconnect();
    }
}

xmppPing will register itself to eventhandler, when ping comes back, it will call handleEvent, and in handleEvent

void CEventHandler::handleEvent(const Event& event)  
{  
    std::string sEvent;  
    switch (event.eventType())  
    {  
        case Event::PingPing:   
            sEvent = "PingPing";  
            break;  
        case Event::PingPong:   
            sEvent = "PingPong";  
            //recieve from server, decrease the count of heart
            --heart;  
            break;  
        case Event::PingError:  
            sEvent = "PingError";  
            break;  
        default:  
            break;  
    }  
    return;  
}  

connect to the server, turn off the network, 3 seconds later, I got a disconnect!

Community
  • 1
  • 1
buaacss
  • 757
  • 6
  • 10
0

You have to define the onDisconnect(ConnectionError e) to be able to handle the disconnect event. The address to documentation is http://camaya.net/api/gloox-0.9.9.12/classgloox_1_1ConnectionListener.html#a2

v01d
  • 1,457
  • 1
  • 11
  • 22