// Helper to fully shut down the listen socket; helps quite a bit on OS X. static void shutdownListenSocket() { if (gListenSocket) { lmLogDebug(gAssetAgentLogGroup, "Shutting down listen socket..."); loom_net_closeTCPSocket(gListenSocket); lmLog(gAssetAgentLogGroup, "Done! Goodbye."); gListenSocket = 0; } }
// Service our connection to the asset agent. static void loom_asset_serviceServer() { loom_mutex_lock(gAssetServerSocketLock); // Try to connect to the asset server if we aren't already, and it is set. if ((gAssetServerSocket == NULL) && ((ASSET_STREAM_HOST != NULL) && (strlen(ASSET_STREAM_HOST) > 0)) && ((platform_getMilliseconds() - gAssetServerLastConnectTryTime) > gAssetServerConnectTryInterval)) { lmLog(gAssetLogGroup, "Attempting to stream assets from %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT); gAssetServerLastConnectTryTime = platform_getMilliseconds(); gAssetServerSocket = loom_net_openTCPSocket(ASSET_STREAM_HOST, ASSET_STREAM_PORT, 0); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } if ((gAssetServerSocket != NULL) && (gAssetConnectionOpen == false)) { // We are waiting on the connection, see if it's writable... If not, return. if (loom_net_isSocketWritable(gAssetServerSocket) == 0) { loom_mutex_unlock(gAssetServerSocketLock); return; } if (loom_net_isSocketDead(gAssetServerSocket) == 1) { // Might be DOA, ie, connect failed. lmLog(gAssetLogGroup, "Failed to connect to asset server %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT); loom_net_closeTCPSocket(gAssetServerSocket); gAssetServerSocket = NULL; lmSafeDelete(NULL, gAssetProtocolHandler); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } lmLog(gAssetLogGroup, "Successfully connected to asset server %s:%d!", ASSET_STREAM_HOST, ASSET_STREAM_PORT); // Do this now to avoid clobbering error state and seeing the socket as // "open" when it is really dead. loom_net_enableSocketKeepalive(gAssetServerSocket); gAssetConnectionOpen = true; loom_asset_notifyPendingCountChange(); // Make sure we have a protocol handler. if (!gAssetProtocolHandler) { gAssetProtocolHandler = lmNew(NULL) AssetProtocolHandler(gAssetServerSocket); gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolFileMessageListener()); gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolCommandListener()); } loom_mutex_unlock(gAssetServerSocketLock); return; } // See if the socket is dead, and if so, clean up. if ((gAssetServerSocket != NULL) && (loom_net_isSocketDead(gAssetServerSocket) == 1)) { lmLog(gAssetLogGroup, "Lost connection to asset server."); loom_net_closeTCPSocket(gAssetServerSocket); gAssetServerSocket = NULL; lmSafeDelete(NULL, gAssetProtocolHandler); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } // Bail if we don't have a connection. if (!gAssetServerSocket || !gAssetConnectionOpen) { loom_mutex_unlock(gAssetServerSocketLock); return; } // Ping if we need to. if (platform_getMilliseconds() - gAssetServerLastPingTime > gAssetServerPingInterval) { gAssetProtocolHandler->sendPing(); gAssetServerLastPingTime = platform_getMilliseconds(); } // Service the asset server connection. gAssetProtocolHandler->process(); loom_mutex_unlock(gAssetServerSocketLock); }
// Entry point for the socket thread. Listen for connections and incoming data, // and route it to the protocol handlers. static int socketListeningThread(void *payload) { // Listen for incoming connections. int listenPort = 12340; gListenSocket = (loom_socketId_t)-1; for ( ; ; ) { gListenSocket = loom_net_listenTCPSocket(listenPort); if (gListenSocket != (loom_socketId_t)-1) { break; } lmLogWarn(gAssetAgentLogGroup, " - Failed to acquire port %d, trying port %d", listenPort, listenPort + 1); listenPort++; } lmLog(gAssetAgentLogGroup, "Listening on port %d", listenPort); while (loom_socketId_t acceptedSocket = loom_net_acceptTCPSocket(gListenSocket)) { // Check to see if we got anybody... if (!acceptedSocket || ((int)(long)acceptedSocket == -1)) { // Process the connections. loom_mutex_lock(gActiveSocketsMutex); for (UTsize i = 0; i < gActiveHandlers.size(); i++) { AssetProtocolHandler* aph = gActiveHandlers[i]; aph->process(); // Check for ping timeout int msSincePing = loom_readTimer(aph->lastActiveTime); if (msSincePing > socketPingTimeoutMs) { gActiveHandlers.erase(i); i--; lmLog(gAssetAgentLogGroup, "Client timed out (%x)", aph->socket); loom_net_closeTCPSocket(aph->socket); lmDelete(NULL, aph); } } loom_mutex_unlock(gActiveSocketsMutex); loom_thread_sleep(10); continue; } lmLog(gAssetAgentLogGroup, "Client connected (%x)", acceptedSocket); loom_mutex_lock(gActiveSocketsMutex); gActiveHandlers.push_back(lmNew(NULL) AssetProtocolHandler(acceptedSocket)); AssetProtocolHandler *handler = gActiveHandlers.back(); handler->registerListener(lmNew(NULL) TelemetryListener()); if (TelemetryServer::isRunning()) handler->sendCommand("telemetryEnable"); // Send it all of our files. // postAllFiles(gActiveHandlers[gActiveHandlers.size()-1]->getId()); loom_mutex_unlock(gActiveSocketsMutex); } return 0; }