Example #1
0
static void esif_ws_http_send_error_code (
	ClientRecordPtr connection,
	int error_code
	)
{
	char buffer[MAX_PATH]={0};
	char *message = (error_code==404 ? "Not Found" : "Error");

	esif_ccb_sprintf(sizeof(buffer), buffer, (char*)"HTTP/1.1 %d %s\r\n\r\n<h1>%d %s</h1>", error_code, message, error_code, message);

	send(connection->socket, buffer, (int)esif_ccb_strlen(buffer, sizeof(buffer)), ESIF_WS_SEND_FLAGS);
	esif_ws_client_close_client(connection);
}
Example #2
0
int esif_ws_init(void)
{
	int index=0;
	int retVal=0;
	char *ipaddr = (char*)g_ws_ipaddr;
	char *portPtr = g_ws_port;

	struct sockaddr_in addrSrvr = {0};
	struct sockaddr_in addrClient = {0};
	socklen_t len_inet = 0;
	
	esif_ccb_socket_t client_socket = INVALID_SOCKET;
	
	int option = 1;
	eEsifError req_results = ESIF_OK;
	ClientRecordPtr clientPtr = NULL;

	int selRetVal = 0;
	int maxfd = 0;
	int setsize = 0;
	
	struct timeval tv={0}; 	/* Timeout value */
	fd_set workingSet = {0};

	esif_ccb_mutex_init(&g_web_socket_lock);
	atomic_inc(&g_ws_threads);
	atomic_set(&g_ws_quit, 0);

	CMD_OUT("Starting WebServer %s %s\n", ipaddr, portPtr);

	esif_ccb_socket_init();

	// Allocate pool of Client Records and HTTP input buffer
	g_clients = (ClientRecordPtr )esif_ccb_malloc(MAX_CLIENTS * sizeof(*g_clients));
	g_ws_http_buffer = (char *)esif_ccb_malloc(WS_BUFFER_LENGTH);
	if (NULL == g_clients || NULL == g_ws_http_buffer) {
		ESIF_TRACE_DEBUG("Out of memory");
		goto exit;
	}

	esif_ws_server_initialize_clients();

	len_inet = sizeof(addrSrvr);

	retVal   = esif_ws_server_create_inet_addr(&addrSrvr, &len_inet, ipaddr, portPtr, (char*)"top");
	if (retVal < 0 && !addrSrvr.sin_port) {
		ESIF_TRACE_DEBUG("Invalid server address/port number");
		goto exit;
	}

	g_listen = socket(PF_INET, SOCK_STREAM, 0);
	if (g_listen == SOCKET_ERROR) {
		ESIF_TRACE_DEBUG("open socket error");
		goto exit;
	}
	
	retVal = setsockopt(g_listen, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option));
	if (retVal < 0) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
		ESIF_TRACE_DEBUG("setsockopt failed");
		goto exit;
	}

	retVal = bind(g_listen, (struct sockaddr*)&addrSrvr, len_inet);
	if (retVal < -1) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
		ESIF_TRACE_DEBUG("bind sysem call failed");
		goto exit;
	}
	
	retVal = listen(g_listen, MAX_CLIENTS);
	if (retVal < 0) {
		ESIF_TRACE_DEBUG("listen system call failed");
		goto exit;
	}

	/* Accept client requests and new connections until told to quit */
	while (!atomic_read(&g_ws_quit)) {
	
		/* Build file descriptor set of active sockets */
		maxfd = 0;
		setsize = 0;

		/* Clear the FD set we will check after each iteration */
		FD_ZERO(&workingSet);

		/* Add our listner to the FD set to check */
		if (g_listen != INVALID_SOCKET) {
			FD_SET((u_int)g_listen, &workingSet);
			maxfd = (int)g_listen + 1;
			setsize++;
		}

		/* Add our current clients to the FD set to check */
		for (index = 0; index <  MAX_CLIENTS && setsize < FD_SETSIZE; index++) {
			if (g_clients[index].socket != INVALID_SOCKET) {
				FD_SET((u_int)g_clients[index].socket, &workingSet);
				maxfd = esif_ccb_max(maxfd, (int)g_clients[index].socket + 1);
				setsize++;
			}
		}
		/* If we have nothing functional in te FD set to check; break */
		if (maxfd == 0) {
			break;
		}

		/*
		 *  timeout of N + 0.05 secs
		 */
		tv.tv_sec  = 2;
		tv.tv_usec = 50000;

		/* Check our FD set for sockets ready to be accepted (listener) or read (others already accepted) */
		selRetVal  = select(maxfd, &workingSet, NULL, NULL, &tv);

		if (selRetVal == SOCKET_ERROR) {
			break;
		} else if (!selRetVal) {
			continue;
		}

		/* Accept any new connections on the listening socket */
		if (FD_ISSET(g_listen, &workingSet)) {
			int sockets = (g_listen == INVALID_SOCKET ? 0 : 1);
			len_inet = sizeof addrClient;

			client_socket = (int)accept(g_listen, (struct sockaddr*)&addrClient, &len_inet);

			if (client_socket == SOCKET_ERROR) {
				ESIF_TRACE_DEBUG("accept(2)");
				goto exit;
			}

			/* Find the first empty client in our list */
			for (index = 0; index < MAX_CLIENTS && sockets < FD_SETSIZE; index++) {
				if (g_clients[index].socket == INVALID_SOCKET) {
					esif_ws_client_initialize_client(&g_clients[index]);
					g_clients[index].socket = client_socket;
					break;
				}
				sockets++;
			}

			/* If all clients are in use, close the new client */
			if (index >= MAX_CLIENTS || sockets >= FD_SETSIZE) {
				ESIF_TRACE_DEBUG("Connection Limit Exceeded (%d)", MAX_CLIENTS);
				esif_ccb_socket_close(client_socket);
				client_socket = INVALID_SOCKET;
				continue;
			}
		}

		/* Go through our client list and check if the FD set indicates any have activity */
		for (index = 0; index < MAX_CLIENTS; index++) {
			client_socket = g_clients[index].socket;
			if (client_socket == INVALID_SOCKET || client_socket == g_listen) {
				continue;
			}

			/* Process client if it is in the set of active file descriptors */
			if (FD_ISSET(client_socket, &workingSet)) {
				ESIF_TRACE_DEBUG("Client %d connected\n", client_socket);

				/******************** Process the client request ********************/
				clientPtr = &g_clients[index];
				req_results = esif_ws_client_process_request(clientPtr);

				if (req_results == ESIF_E_WS_DISC) {
					ESIF_TRACE_DEBUG("Client %d disconnected\n", client_socket);
					esif_ws_client_initialize_client(clientPtr); /* reset */
				}
				else if (req_results == ESIF_E_NO_MEMORY) {
					ESIF_TRACE_DEBUG("Out of memory\n");
					esif_ws_client_initialize_client(clientPtr); /* reset */
				}

				/* Clear everything after use */
				esif_ws_protocol_initialize(&clientPtr->prot);
			}
		}
	}

exit:
	/* cleanup */
	if (g_listen != INVALID_SOCKET) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
	}
	if (g_clients) {
		for (index = 0; index < MAX_CLIENTS; index++) {
			esif_ws_client_close_client(&g_clients[index]);
		}
		esif_ccb_free(g_clients);
		g_clients = NULL;
	}
	esif_ccb_free(g_rest_out);
	esif_ccb_free(g_ws_http_buffer);
	g_rest_out = NULL;
	g_ws_http_buffer = NULL;
	esif_ccb_socket_exit();
	atomic_dec(&g_ws_threads);
	return 0;
}