示例#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.
	}
}
示例#2
0
static void
connectTimeoutCallback(ConnectState *connectState) {
	connectState->alarm = NULL;

	NetDescriptor_close(connectState->nd);
	connectState->nd = NULL;

	connectState->infoPtr = connectState->infoPtr->ai_next;
	connectHostNext(connectState);
}
示例#3
0
// Close and release a NetConnection.
void
NetConnection_close(NetConnection *conn) {
	if (conn->nd != NULL) {
		NetDescriptor_setCloseCallback(conn->nd, NULL);
				// We're not interested in the close callback of the
				// NetDescriptor anymore.
		NetDescriptor_close(conn->nd);
				// This would queue the close callback.
		conn->nd = NULL;
	}
	if (!conn->stateFlags.disconnected)
		NetConnection_doClose(conn);
	NetConnection_delete(conn);
}
示例#4
0
// Decrements ref count byh 1
void
ListenState_close(ListenState *listenState) {
	if (listenState->resolveState != NULL) {
		Resolve_close(listenState->resolveState);
		listenState->resolveState = NULL;
	}
	if (listenState->nds != NULL) {
		while (listenState->numNd > 0) {
			listenState->numNd--;
			NetDescriptor_close(listenState->nds[listenState->numNd]);
		}
		free(listenState->nds);
		listenState->nds = NULL;
	}
	listenState->state = Listen_closed;
	ListenState_decRef(listenState);
}
示例#5
0
// decrements ref count by 1
void
ConnectState_close(ConnectState *connectState) {
	if (connectState->resolveState != NULL) {
		Resolve_close(connectState->resolveState);
		connectState->resolveState = NULL;
	}
	if (connectState->alarm != NULL) {
		Alarm_remove(connectState->alarm);
		connectState->alarm = NULL;
	}
	if (connectState->nd != NULL) {
		NetDescriptor_close(connectState->nd);
		connectState->nd = NULL;
	}
	if (connectState->info != NULL) {
		freeaddrinfo(connectState->info);
		connectState->info = NULL;
		connectState->infoPtr = NULL;
	}
	connectState->state = Connect_closed;
	ConnectState_decRef(connectState);
}
示例#6
0
void
dataReadyCallback(NetDescriptor *nd) {
	NetConnection *conn = (NetConnection *) NetDescriptor_getExtra(nd);
	Socket *socket = NetDescriptor_getSocket(nd);

	for (;;) {
		ssize_t numRead;
		ssize_t numProcessed;

		numRead = Socket_recv(socket, conn->readEnd,
				NETPLAY_READBUFSIZE - (conn->readEnd - conn->readBuf), 0);
		if (numRead == 0) {
			// Other side closed the connection.
			NetDescriptor_close(nd);
			return;
		}

		if (numRead == -1) {
			switch (errno) {
				case EAGAIN:  // No more data for now.
					return;
				case EINTR:  // System call was interrupted. Retry.
					continue;
				default: {
					int savedErrno = errno;
					log_add(log_Error, "recv() failed: %s.\n",
							strerror(errno));
					NetConnection_doErrorCallback(conn, savedErrno);
					NetDescriptor_close(nd);
					return;
				}
			}
		}

		conn->readEnd += numRead;

		numProcessed = dataReceivedMulti(conn, conn->readBuf,
				conn->readEnd - conn->readBuf);
		if (numProcessed == -1) {
			// An error occured during processing.
			// errno is set.
			NetConnection_doErrorCallback(conn, errno);
			NetDescriptor_close(nd);
			return;
		}
		if (numProcessed == 0) {
			// No packets could be processed. This means we need to receive
			// more data first.
			return;
		}
		
		// Some packets have been processed.
		// We more any rest to the front of the buffer, to make room
		// for more data.
		// A cyclic buffer would obviate the need for this move,
		// but it would complicate things a lot.
		memmove(conn->readBuf, conn->readBuf + numProcessed,
				(conn->readEnd - conn->readBuf) - numProcessed);
		conn->readEnd -= numProcessed;
	}
}
示例#7
0
static inline int
NetManager_processEvent(size_t index) {
	WSANETWORKEVENTS networkEvents;
	int enumRes;

	enumRes = WSAEnumNetworkEvents(netDescriptors[index]->socket->sock,
			events[index], &networkEvents);
	if (enumRes == SOCKET_ERROR) {
		errno = getWinsockErrno();
		return -1;
	}

	if (networkEvents.lNetworkEvents & FD_READ) {
		bool closed;
		if (networkEvents.iErrorCode[FD_READ_BIT] != 0) {
			// No special handling is required; the callback function
			// will try to do a recv() and will get the error then.
		}

		closed = NetManager_doReadCallback(netDescriptors[index]);
		if (closed)
			goto closed;
	}
	if (networkEvents.lNetworkEvents & FD_WRITE) {
		bool closed;
		if (networkEvents.iErrorCode[FD_WRITE_BIT] != 0) {
			// No special handling is required; the callback function
			// will try to do a send() and will get the error then.
		}

		closed = NetManager_doWriteCallback(netDescriptors[index]);
		if (closed)
			goto closed;
	}
	if (networkEvents.lNetworkEvents & FD_OOB) {
		bool closed;
		if (networkEvents.iErrorCode[FD_OOB_BIT] != 0) {
			// No special handling is required; the callback function
			// will get the error then when it tries to do a recv().
		}

		closed = NetManager_doExceptionCallback(netDescriptors[index]);
		if (closed)
			goto closed;
	}
	if (networkEvents.lNetworkEvents & FD_ACCEPT) {
		// There is no specific accept callback (because the BSD sockets
		// don't work with specific notification for accept); we use
		// the read callback instead.
		bool closed;
		if (networkEvents.iErrorCode[FD_READ_BIT] != 0) {
			// No special handling is required; the callback function
			// will try to do an accept() and will get the error then.
		}

		closed = NetManager_doReadCallback(netDescriptors[index]);
		if (closed)
			goto closed;
	}
#if 0
	// No need for this. Windows also sets FD_WRITE in this case, and
	// writability is what we check for anyhow.
	if (networkEvents.lNetworkEvents & FD_CONNECT) {
		// There is no specific connect callback (because the BSD sockets
		// don't work with specific notification for connect); we use
		// the write callback instead.
		bool closed;
		if (networkEvents.iErrorCode[FD_WRITE_BIT] != 0) {
			// No special handling is required; the callback function
			// should do getsockopt() with SO_ERROR to get the error.
		}

		closed = NetManager_doWriteCallback(netDescriptors[index]);
		if (closed)
			goto closed;
	}
#endif
	if (networkEvents.lNetworkEvents & FD_CLOSE) {
		// The close event is handled last, in case there was still
		// data in the buffers which could be processed.
		NetDescriptor_close(netDescriptors[index]);
		goto closed;
	}

closed:  /* No special actions required for now. */

	return 0;
}