Ejemplo n.º 1
0
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.
	}
}
Ejemplo n.º 2
0
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);
}