示例#1
0
/**
 * Add a socket to the list of socket to check with select
 * @param newSd the new socket to add
 */
int Socket_addSocket(int newSd)
{
	int rc = 0;

	FUNC_ENTRY;
	if (ListFindItem(s.clientsds, &newSd, intcompare) == NULL) /* make sure we don't add the same socket twice */
	{
		int* pnewSd = (int*)malloc(sizeof(newSd));
		*pnewSd = newSd;
		ListAppend(s.clientsds, pnewSd, sizeof(newSd));
		FD_SET(newSd, &(s.rset_saved));
		s.maxfdp1 = max(s.maxfdp1, newSd + 1);
		rc = Socket_setnonblocking(newSd);
	}
	else
		Log(TRACE_MIN, -1, "addSocket: socket %d already in the list", newSd);

	FUNC_EXIT_RC(rc);
	return rc;
}
示例#2
0
/**
 * Fully initialize the socket module for in and outbound communications.
 * In single-listener mode.
 * @param anAddress IP address string
 * @param port number
 * @param ipv6 flag to indicate ipv6 should be used
 * @return completion code
 */
int Socket_initialize(char* anAddress, int aPort, int ipv6)
{
	int flag = 1;
	int rc = SOCKET_ERROR;
	int ipv4 = 1; /* yes we can drop down to ipv4 */

	FUNC_ENTRY;
	s.port = aPort;
	if (anAddress == NULL || strcmp(anAddress, "INADDR_ANY") == 0)
	{
		s.addr.sin_addr.s_addr = htonl(INADDR_ANY);
		s.addr6.sin6_addr = in6addr_any;
	}
	else
	{
		if (anAddress[0] == '[')
		{
			int changed = ipv6_format(anAddress);
			inet_pton(AF_INET6, &anAddress[1], &(s.addr6.sin6_addr));
			ipv4 = 0;
			if (changed)
				(anAddress)[changed] = ']';
		}
		else
		{
			inet_pton(AF_INET, anAddress, &(s.addr.sin_addr.s_addr));
			ipv6 = 0;
		}
	}
	Socket_outInitialize();
	s.mySocket = -1;
	if (ipv6)
		s.mySocket = socket(AF_INET6, SOCK_STREAM, 0);
	if (s.mySocket < 0 && ipv4)
	{
		s.mySocket = socket(AF_INET, SOCK_STREAM, 0);
		ipv6 = 0;
	}
	s.maxfdp1 = 0;
	Log(TRACE_MAX, 6, NULL, FD_SETSIZE);
	if (s.mySocket < 0)
	{
		Socket_error("socket", s.mySocket);
		Log(LOG_WARNING, 77, NULL);
		rc = s.mySocket;
		goto exit;
	}

#if !defined(WIN32)
	if (setsockopt(s.mySocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)) != 0)
		Log(LOG_WARNING, 109, NULL, aPort);
#endif
	if (ipv6)
	{
		s.addr6.sin6_family = AF_INET6;
		s.addr6.sin6_port = htons(s.port);
		rc = bind(s.mySocket, (struct sockaddr *)&(s.addr6), sizeof(s.addr6));
	}
	else
	{
		s.addr.sin_family = AF_INET;
		s.addr.sin_port = htons(s.port);
		memset(s.addr.sin_zero, 0, sizeof(s.addr.sin_zero));
		rc = bind(s.mySocket, (struct sockaddr *)&(s.addr), sizeof(s.addr));
	}
	if (rc == SOCKET_ERROR)
	{
		Socket_error("bind", s.mySocket);
		Log(LOG_WARNING, 78, NULL, aPort);
		goto exit;
	}
	if (listen(s.mySocket, SOMAXCONN) == SOCKET_ERROR) /* second parm is max no of connections */
	{
		Socket_error("listen", s.mySocket);
		Log(LOG_WARNING, 79, NULL, aPort);
		goto exit;
	}
	if (Socket_setnonblocking(s.mySocket) == SOCKET_ERROR)
	{
		Socket_error("setnonblocking", s.mySocket);
		goto exit;
	}
	FD_SET((u_int)s.mySocket, &(s.rset));         /* Add the current socket descriptor */
	s.maxfdp1 = s.mySocket + 1;
	memcpy((void*)&(s.rset_saved), (void*)&(s.rset), sizeof(s.rset_saved));
	rc = 0;
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}
示例#3
0
/**
 * Create the server socket in multi-listener mode.
 * @param list pointer to a listener structure
 * @return completion code
 */
int Socket_addServerSocket(Listener* list)
{
	int flag = 1;
	int rc = SOCKET_ERROR;
	int ipv4 = 1; /* yes we can drop down to ipv4 */

	FUNC_ENTRY;
	if (!list->address || strcmp(list->address, "INADDR_ANY") == 0)
	{
		struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
		list->addr.sin_addr.s_addr = htonl(INADDR_ANY);
		list->addr6.sin6_addr = in6addr_any;
	}
	else
	{
		if (list->address[0] == '[')
		{
			int changed = ipv6_format(list->address);
#if defined(WIN32)
			/*wchar_t buf[(INET6_ADDRSTRLEN+1)*2];
			int buflen = sizeof(list->addr6);
			mbstowcs(buf, &list->address[1], sizeof(buf));
			rc = WSAStringToAddress(buf, AF_INET6, NULL, (struct sockaddr*)&list->addr6, &buflen);*/
			rc = win_inet_pton(AF_INET6, &list->address[1], &(list->addr6.sin6_addr));
#else
			rc = inet_pton(AF_INET6, &list->address[1], &(list->addr6.sin6_addr));
#endif
			ipv4 = 0;
			if (changed)
				(list->address)[changed] = ']';
		}
		else
		{
#if defined(WIN32)
			/*wchar_t buf[(INET6_ADDRSTRLEN+1)*2];
			int buflen = sizeof(list->addr);
			mbstowcs(buf, list->address, sizeof(buf));
			rc = WSAStringToAddress(buf, AF_INET, NULL, (struct sockaddr*)&list->addr, &buflen);*/
			rc = win_inet_pton(AF_INET, list->address, &(list->addr.sin_addr.s_addr));
#else
			rc = inet_pton(AF_INET, list->address, &(list->addr.sin_addr.s_addr));
#endif
			list->ipv6 = 0;
		}
#if defined(WIN32)
		if (rc != 0)
#else
		if (rc != 1)
#endif
		{
			Log(LOG_WARNING, 67, NULL, list->address);
			rc = -1;
			goto exit;
		}
	}
	list->socket = -1;
	if (list->protocol == PROTOCOL_MQTT)
	{
		if (list->ipv6)
			list->socket = socket(AF_INET6, SOCK_STREAM, 0);
		if (list->socket < 0 && ipv4)
		{
			list->socket = socket(AF_INET, SOCK_STREAM, 0);
			list->ipv6 = 0;
		}
	}
#if defined(MQTTS)
	else if (list->protocol == PROTOCOL_MQTTS)
	{
		if (list->ipv6)
			list->socket = socket(AF_INET6, SOCK_DGRAM, 0);
		if (list->socket < 0 && ipv4)
		{
			list->socket = socket(AF_INET, SOCK_DGRAM, 0);
			list->ipv6 = 0;
		}
	}
#endif
	Log(TRACE_MAX, 6, NULL, FD_SETSIZE);
	if (list->socket < 0)
	{
		Socket_error("socket", list->socket);
		Log(LOG_WARNING, 77, NULL);
		rc = list->socket;
		goto exit;
	}

#if !defined(WIN32)
	if (setsockopt(list->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)) != 0)
		Log(LOG_WARNING, 109, NULL, list->port);
#endif
	if (list->ipv6)
	{
		list->addr6.sin6_family = AF_INET6;
		list->addr6.sin6_port = htons(list->port);
		rc = bind(list->socket, (struct sockaddr *)&(list->addr6), sizeof(list->addr6));
	}
	else
	{
		list->addr.sin_family = AF_INET;
		list->addr.sin_port = htons(list->port);
		memset(list->addr.sin_zero, 0, sizeof(list->addr.sin_zero));
		rc = bind(list->socket, (struct sockaddr *)&(list->addr), sizeof(list->addr));
	}
	if (rc == SOCKET_ERROR)
	{
		Socket_error("bind", list->socket);
		Log(LOG_WARNING, 78, NULL, list->port);
		goto exit;
	}

	/* Only listen if this is mqtt/tcp */
	if (list->protocol == PROTOCOL_MQTT &&
			listen(list->socket, SOMAXCONN) == SOCKET_ERROR) /* second parm is max no of connections */
	{
		Socket_error("listen", list->socket);
		Log(LOG_WARNING, 79, NULL, list->port);
		goto exit;
	}

	if (Socket_setnonblocking(list->socket) == SOCKET_ERROR)
	{
		Socket_error("setnonblocking", list->socket);
		goto exit;
	}

#if defined(MQTTS)
	/* If mqtts/udp, add to the list of clientsds to test for reading */
	if (list->protocol == PROTOCOL_MQTTS)
	{
		ListElement* current = NULL;
		int loopback = list->loopback;

#if !defined(USE_POLL)
		int* pnewSd = (int*)malloc(sizeof(list->socket));

		*pnewSd = list->socket;
		ListAppend(s.clientsds, pnewSd, sizeof(list->socket));
#endif
		Log(LOG_INFO, 300, NULL, list->port);

		if (setsockopt(list->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)) == SOCKET_ERROR)
			Socket_error("set listener IP_MULTICAST_LOOP", list->socket);

		/* join any multicast groups */
		while (ListNextElement(list->multicast_groups, &current))
			Socket_joinMulticastGroup(list->socket, list->ipv6, (char*)(current->content));
	}
	else
#endif
		Log(LOG_INFO, 14, NULL, list->port);

#if defined(USE_POLL)
	/* add new socket to the epoll descriptor with epoll_ctl */
	struct socket_info* si = malloc(sizeof(struct socket_info));
	si->listener = list;
	si->fd = list->socket;
	si->connect_pending = 0;
	si->event.events = EPOLLIN;
	si->event.data.ptr = si;
	TreeAdd(s.fds_tree, si, sizeof(struct socket_info));
	if (epoll_ctl(s.epoll_fds, EPOLL_CTL_ADD, list->socket, &si->event) != 0)
		Socket_error("epoll_ctl add", list->socket);
#else
	FD_SET((u_int)list->socket, &(s.rset));         /* Add the current socket descriptor */
	s.maxfdp1 = max(s.maxfdp1+1, list->socket+1);

	memcpy((void*)&(s.rset_saved), (void*)&(s.rset), sizeof(s.rset_saved));
#endif

	rc = 0;
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}