void CTCPSocket::connect(const CNetworkAddress& addr) { { CLock lock(&m_mutex); // fail on attempts to reconnect if (m_socket == NULL || m_connected) { sendConnectionFailedEvent("busy"); return; } try { if (ARCH->connectSocket(m_socket, addr.getAddress())) { sendEvent(getConnectedEvent()); onConnected(); } else { // connection is in progress m_writable = true; } } catch (XArchNetwork& e) { throw XSocketConnect(e.what()); } } setJob(newJob()); }
void CClientListener::handleUnknownClient(const CEvent&, void* vclient) { CClientProxyUnknown* unknownClient = reinterpret_cast<CClientProxyUnknown*>(vclient); // we should have the client in our new client list assert(m_newClients.count(unknownClient) == 1); // get the real client proxy and install it CClientProxy* client = unknownClient->orphanClientProxy(); if (client != NULL) { // handshake was successful m_waitingClients.push_back(client); EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this)); // watch for client to disconnect while it's in our queue EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client, new TMethodEventJob<CClientListener>(this, &CClientListener::handleClientDisconnected, client)); } // now finished with unknown client EVENTQUEUE->removeHandler(CClientProxyUnknown::getSuccessEvent(), client); EVENTQUEUE->removeHandler(CClientProxyUnknown::getFailureEvent(), client); m_newClients.erase(unknownClient); delete unknownClient; }
void CClient::handshakeComplete() { m_ready = true; m_screen->enable(); sendEvent(getConnectedEvent(), NULL); }
void CIpcClient::handleConnected(const CEvent&, void*) { EVENTQUEUE->addEvent(CEvent( getConnectedEvent(), this, m_server, CEvent::kDontFreeData)); CIpcHelloMessage message(kIpcClientNode); send(message); }
ISocketMultiplexerJob* CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bool, bool write, bool error) { CLock lock(&m_mutex); // should only check for errors if error is true but checking a new // socket (and a socket that's connecting should be new) for errors // should be safe and Mac OS X appears to have a bug where a // non-blocking stream socket that fails to connect immediately is // reported by select as being writable (i.e. connected) even when // the connection has failed. this is easily demonstrated on OS X // 10.3.4 by starting a synergy client and telling to connect to // another system that's not running a synergy server. it will // claim to have connected then quickly disconnect (i guess because // read returns 0 bytes). unfortunately, synergy attempts to // reconnect immediately, the process repeats and we end up // spinning the CPU. luckily, OS X does set SO_ERROR on the // socket correctly when the connection has failed so checking for // errors works. (curiously, sometimes OS X doesn't report // connection refused. when that happens it at least doesn't // report the socket as being writable so synergy is able to time // out the attempt.) if (error || true) { try { // connection may have failed or succeeded ARCH->throwErrorOnSocket(m_socket); } catch (XArchNetwork& e) { sendConnectionFailedEvent(e.what().c_str()); onDisconnected(); return newJob(); } } if (write) { sendEvent(getConnectedEvent()); onConnected(); return newJob(); } return job; }