static void connectCallback(NetDescriptor *nd) { // Called by the NetManager when a connection has been established. ConnectState *connectState = (ConnectState *) NetDescriptor_getExtra(nd); int err; if (connectState->alarm != NULL) { Alarm_remove(connectState->alarm); connectState->alarm = NULL; } if (connectState->state == Connect_closed) { // The connection attempt has been aborted. #ifdef DEBUG log_add(log_Debug, "Connection attempt was aborted."); #endif ConnectState_decRef(connectState); return; } if (Socket_getError(NetDescriptor_getSocket(nd), &err) == -1) { log_add(log_Fatal, "Socket_getError() failed: %s.", strerror(errno)); explode(); } if (err != 0) { #ifdef DEBUG log_add(log_Debug, "connect() failed: %s.", strerror(err)); #endif NetDescriptor_close(nd); connectState->nd = NULL; connectState->infoPtr = connectState->infoPtr->ai_next; connectHostNext(connectState); return; } #ifdef DEBUG log_add(log_Debug, "Connection established."); #endif // Notify the higher layer. connectState->nd = NULL; // The callback function takes over ownership of the // NetDescriptor. NetDescriptor_setWriteCallback(nd, NULL); // Note that connectState->info and connectState->infoPtr are cleaned up // when ConnectState_close() is called by the callback function. ConnectState_incRef(connectState); doConnectCallback(connectState, nd, connectState->infoPtr->ai_addr, connectState->infoPtr->ai_addrlen); { // The callback called should release the last reference to // the connectState, by calling ConnectState_close(). bool released = ConnectState_decRef(connectState); assert(released); (void) released; // In case assert() evaluates to nothing. } }
static void connectHostNext(ConnectState *connectState) { Socket *sock; while (connectState->infoPtr != NULL) { sock = tryConnectHostNext(connectState); if (sock != Socket_noSocket) { // Connection succeeded or connection in progress connectState->nd = NetDescriptor_new(sock, (void *) connectState); if (connectState->nd == NULL) { ConnectError error; int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.\n", strerror(errno)); Socket_close(sock); freeaddrinfo(connectState->info); connectState->info = NULL; connectState->infoPtr = NULL; connectState->state = Connect_closed; error.state = Connect_connecting; error.err = savedErrno; doConnectErrorCallback(connectState, &error); return; } NetDescriptor_setWriteCallback(connectState->nd, connectCallback); setConnectTimeout(connectState); return; } connectState->infoPtr = connectState->infoPtr->ai_next; } // Connect failed to all addresses. if (connectState->flags.retryDelayMs == Connect_noRetry) { connectHostReportAllFailed(connectState); return; } setConnectRetryAlarm(connectState); }