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); }
static void acceptSingleConnection(ListenState *listenState, NetDescriptor *nd) { Socket *sock; Socket *acceptResult; struct sockaddr_storage addr; socklen_t addrLen; NetDescriptor *newNd; sock = NetDescriptor_getSocket(nd); addrLen = sizeof (addr); acceptResult = Socket_accept(sock, (struct sockaddr *) &addr, &addrLen); if (acceptResult == Socket_noSocket) { switch (errno) { case EWOULDBLOCK: case ECONNABORTED: // Nothing serious. Keep listening. return; case EMFILE: case ENFILE: case ENOBUFS: case ENOMEM: #ifdef ENOSR case ENOSR: #endif // Serious problems, but future connections may still // be possible. log_add(log_Warning, "accept() reported '%s'", strerror(errno)); return; default: // Should not happen. log_add(log_Fatal, "Internal error: accept() reported " "'%s'", strerror(errno)); explode(); } } (void) Socket_setReuseAddr(acceptResult); // Ignore errors; it's not a big deal. if (Socket_setNonBlocking(acceptResult) == -1) { int savedErrno = errno; log_add(log_Error, "Could not make socket non-blocking: %s.", strerror(errno)); Socket_close(acceptResult); errno = savedErrno; return; } (void) Socket_setInlineOOB(acceptResult); // Ignore errors; it's not a big deal as the other // party is not not supposed to send any OOB data. (void) Socket_setKeepAlive(sock); // Ignore errors; it's not a big deal. #ifdef DEBUG { char hostname[NI_MAXHOST]; int gniRes; gniRes = getnameinfo((struct sockaddr *) &addr, addrLen, hostname, sizeof hostname, NULL, 0, 0); if (gniRes != 0) { log_add(log_Error, "Error while performing hostname " "lookup for incoming connection: %s", (gniRes == EAI_SYSTEM) ? strerror(errno) : gai_strerror(gniRes)); } else { log_add(log_Debug, "Accepted incoming connection from '%s'.", hostname); } } #endif newNd = NetDescriptor_new(acceptResult, NULL); if (newNd == NULL) { int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.", strerror(errno)); Socket_close(acceptResult); errno = savedErrno; return; } doListenConnectCallback(listenState, nd, newNd, (struct sockaddr *) &addr, addrLen); // NB: newNd is now handed over to the callback function, and should // no longer be referenced from here. }
static NetDescriptor * listenPortSingle(struct ListenState *listenState, struct addrinfo *info) { Socket *sock; int bindResult; int listenResult; NetDescriptor *nd; sock = Socket_openNative(info->ai_family, info->ai_socktype, info->ai_protocol); if (sock == Socket_noSocket) { int savedErrno = errno; log_add(log_Error, "socket() failed: %s.", strerror(errno)); errno = savedErrno; return NULL; } (void) Socket_setReuseAddr(sock); // Ignore errors; it's not a big deal. if (Socket_setNonBlocking(sock) == -1) { int savedErrno = errno; // Error message is already printed. Socket_close(sock); errno = savedErrno; return NULL; } bindResult = Socket_bind(sock, info->ai_addr, info->ai_addrlen); if (bindResult == -1) { int savedErrno = errno; if (errno == EADDRINUSE) { #ifdef DEBUG log_add(log_Warning, "bind() failed: %s.", strerror(errno)); #endif } else log_add(log_Error, "bind() failed: %s.", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } listenResult = Socket_listen(sock, listenState->flags.backlog); if (listenResult == -1) { int savedErrno = errno; log_add(log_Error, "listen() failed: %s.", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } nd = NetDescriptor_new(sock, (void *) listenState); if (nd == NULL) { int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } NetDescriptor_setReadCallback(nd, acceptCallback); return nd; }