Skip to content
Snippets Groups Projects
pathComp_RESTapi.c 75.4 KiB
Newer Older
	struct sockaddr_in client_addr;
	socklen_t client = sizeof(client_addr);
	
martinezric's avatar
martinezric committed
	if ((cond == G_IO_HUP) || (cond == G_IO_ERR) || (G_IO_NVAL)) {
		//DEBUG_PC ("Something happening with the channel and fd ... cond: %d", cond);		
		// Find the associated client (by the fd) and remove from PATH COMP client list. 
		// Stop all the operations over that PATH COMP client bound channel
		struct pathComp_client *pathComp_client = NULL;
		gint fd = g_io_channel_unix_get_fd (source);
		GList *found = g_list_find_custom (RESTapi_tcp_client_list, &fd, find_rl_client_by_fd);
martinezric's avatar
martinezric committed
		if (found != NULL) 	{
			pathComp_client = (struct pathComp_client*)(found->data);
			// remove client
			RESTapi_client_close(pathComp_client);
			// Stop operations over that channel
			RESTapi_close_operations(source);
			close (fd);
			return FALSE;
martinezric's avatar
martinezric committed
	if (cond == G_IO_IN) 	{
		gint new = accept(g_io_channel_unix_get_fd(source), (struct sockaddr*)&client_addr, &client);
martinezric's avatar
martinezric committed
		if (new < 0) {
			//DEBUG_PC ("Unable to accept new connection");
			return FALSE;
		}

martinezric's avatar
martinezric committed
		// new channel
		GIOChannel * new_channel = g_io_channel_unix_new (new);		
		//DEBUG_PC ("TCP Connection (REST API) is UP; (socket: %d)", new);
martinezric's avatar
martinezric committed
		// create pathComp client		
		struct pathComp_client *new_client = RESTapi_client_create (new_channel, new);
		
martinezric's avatar
martinezric committed
		// force binary encoding with NULL
martinezric's avatar
martinezric committed
		if ( g_io_channel_set_encoding (new_channel, NULL, &error) != G_IO_STATUS_NORMAL) {		
			DEBUG_PC ("Error: %s", error->message);
			exit (-1);
		}
		g_io_channel_set_close_on_unref (new_channel, TRUE);
		// On unbuffered channels, it is safe to mix read
		// & write calls from the new and old APIs.
		g_io_channel_set_buffered (new_channel, FALSE);
martinezric's avatar
martinezric committed
		if (g_io_channel_set_flags (new_channel, G_IO_FLAG_NONBLOCK, &error) != G_IO_STATUS_NORMAL ) {
			DEBUG_PC ("Error: %s", error->message);
			exit (-1);
		}
		//Adds the new channel into the main event loop.
		g_io_add_watch (new_channel, G_IO_IN, RESTapi_activity, new_client);
    }	
	return TRUE;
}

///////////////////////////////////////////////////////////////////////////////////////
/**
 * 	@file pathComp_RESTapi.c
 * 	@brief enabling the reuse of the addr for the Server TCP
 * 	
 * 	@param sock
 *
 *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
 *	@date 2022
 */
/////////////////////////////////////////////////////////////////////////////////////////
void RESTapi_tcp_enable_reuseaddr (gint sock)
{
	gint tmp = 1;
	if (sock < 0)
	{
		DEBUG_PC (" socket: %d !!!",sock);
		exit (-1);
	}
	if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (gchar *)&tmp, sizeof (tmp)) == -1)
	{
		DEBUG_PC ("bad setsockopt ...");
		exit (-1);
	}
	return;
}

////////////////////////////////////////////////////////////////////////////////////////
/**
 * 	@file pathComp_RESTapi.c
 * 	@brief Main function for the creating / maintaining TCP session for the REST API
 *
 *  @ port 
 * 
 *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
 *	@date 2022
 */
/////////////////////////////////////////////////////////////////////////////////////////
void RESTapi_init(gint port)
{     
    DEBUG_PC ("REST API PORT (listening): %d", port);     
	
	// File Descriptor - FD - for the socket
	gint s = socket (AF_INET, SOCK_STREAM, 0);
	if (s == -1)
	{
		DEBUG_PC ("Socket creation: FAILED!!");
		exit (-1);
	}
	DEBUG_PC (" CREATED TCP Connection [@fd: %d]", s);

	// Re-bind
	RESTapi_tcp_enable_reuseaddr(s);	
	struct sockaddr_in addr;
	memset (&addr, 0, sizeof (addr));
	addr.sin_family       = AF_INET;
	addr.sin_port         = htons ((u_short)port);
	addr.sin_addr.s_addr  = INADDR_ANY;      

	// Associate IP address and Port to the created socket
	if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		close (s);
		DEBUG_PC ("Socket bind: FAILED!!");
		exit (-1);
	}
	DEBUG_PC ("Bind to Fd: %d DONE!!", s);

	/** Set up queue for incoming connections */
	if (listen (s, 10) == -1)
	{
		close (s);
		DEBUG_PC ("Socket listen: FAILED!!");
		exit (-1);
	}
	
	//DEBUG_PC ("Listen (up to 10) to Fd: %d Done", s);

	/** Create NEW channel to handle the socket operations*/
	GIOChannel *channel = g_io_channel_unix_new (s);
	gsize buffersize = g_io_channel_get_buffer_size (channel);
	//DEBUG_PC ("GIOChannel with Buffer Size: %d", (gint)buffersize);

	gsize newBufferSize = MAX_GIO_CHANNEL_BUFFER_SIZE;
	g_io_channel_set_buffer_size (channel, newBufferSize);
	buffersize = g_io_channel_get_buffer_size (channel);

	//DEBUG_PC ("GIOChannel with Buffer Size: %d", (gint)buffersize);
	//DEBUG_PC ("Channel associated to fd: %d is created", s);
	
	// Adds the new channel into the main event loop.
	g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, RESTapi_tcp_new_connection, NULL);
	return;     
}