Пример #1
0
/** 
 * @internal noPoll select implementation for the "add to" on fd set
 * operation.
 * 
 * @param fds The socket descriptor to be added.
 *
 * @param fd_set The fd set where the socket descriptor will be added.
 */
nopoll_bool  nopoll_io_wait_select_add_to (int               fds, 
					   noPollCtx       * ctx,
					   noPollConn      * conn,
					   noPollPtr         __fd_set)
{
	noPollSelect * select = (noPollSelect *) __fd_set;

	if (fds < 0) {
		nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL,
			    "received a non valid socket (%d), unable to add to the set", fds);
		return nopoll_false;
	}

	/* set the value */
	FD_SET (fds, &(select->set));

	/* update length */
	select->length++;

	/* update max fds */
	if (fds > select->max_fds)
		select->max_fds = fds;

	return nopoll_true;
}
Пример #2
0
/** 
 * @internal Function used to detected which connections has something
 * interesting to be notified.
 *
 */
nopoll_bool nopoll_loop_process (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data)
{
	int        * conn_changed = (int *) user_data;

	/* check if the connection have something to notify */
	if (ctx->io_engine->isset (ctx, conn->session, ctx->io_engine->io_object)) {

		/* call to notify action according to role */
		switch (conn->role) {
		case NOPOLL_ROLE_CLIENT:
		case NOPOLL_ROLE_LISTENER:
			/* received data, notify */
			nopoll_loop_process_data (ctx, conn);
			break;
		case NOPOLL_ROLE_MAIN_LISTENER:
			/* call to handle */
			nopoll_conn_accept (ctx, conn);
			break;
		default:
			nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Found connection with unknown role, closing and dropping");
			nopoll_conn_shutdown (conn);
			break;
		}
		
		/* reduce connection changed */
		(*conn_changed)--;
	} /* end if */
	
	return (*conn_changed) == 0;
}
Пример #3
0
/** 
 * @internal Function used to init internal io wait mechanism...
 *
 * @param ctx The noPoll context to be initialized if it wasn't
 */
void nopoll_loop_init (noPollCtx * ctx) 
{
	if (ctx == NULL)
		return;

	/* grab the mutex for the following check */
	if (ctx->io_engine == NULL) {
		ctx->io_engine = nopoll_io_get_engine (ctx, NOPOLL_IO_ENGINE_DEFAULT);
		if (ctx->io_engine == NULL) {
			nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Failed to create IO wait engine, unable to implement wait call");
			return;
		} 
	} /* end if */
	/* release the mutex */

	return;
}
Пример #4
0
/** 
 * @internal Function used by nopoll_loop_wait to register all
 * connections into the io waiting object.
 */
nopoll_bool nopoll_loop_register (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data)
{
	/* do not add connections that aren't working */
	if (! nopoll_conn_is_ok (conn)) {
		
		/* remove this connection from registry */
		nopoll_ctx_unregister_conn (ctx, conn);

		return nopoll_false; /* keep foreach, don't stop */
	}

	/* register the connection socket */
	/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Adding socket id: %d", conn->session);*/
	if (! ctx->io_engine->addto (conn->session, ctx, conn, ctx->io_engine->io_object)) {

		/* remove this connection from registry */
		nopoll_ctx_unregister_conn (ctx, conn);
		nopoll_log (ctx, NOPOLL_LEVEL_WARNING, "Failed to add socket %d to the watching set", conn->session);

	}

	return nopoll_false; /* keep foreach, don't stop */
}
Пример #5
0
/** 
 * @brief Allows to implement a wait over all connections registered
 * under the provided context during the provided timeout until
 * something is detected meaningful to the user, calling to the action
 * handler defined, optionally receving the user data pointer.
 *
 * @param ctx The context object where the wait will be implemented.
 *
 * @param timeout The timeout to wait for changes. If no changes
 * happens, the function returns. The function will block the caller
 * until a call to \ref nopoll_loop_stop is done in the case timeout
 * passed is 0.
 *
 * @return The function returns 0 when finished or -2 in the case ctx
 * is NULL or timeout is negative.
 */
int nopoll_loop_wait (noPollCtx * ctx, long timeout)
{
	struct timeval start;
	struct timeval stop;
	struct timeval diff;
	long           ellapsed;
	int            wait_status;

	nopoll_return_val_if_fail (ctx, ctx, -2);
	nopoll_return_val_if_fail (ctx, timeout >= 0, -2);
	
	/* call to init io engine */
	nopoll_loop_init (ctx);

	/* get as reference current time */
	if (timeout > 0)
#if defined(NOPOLL_OS_WIN32)
		nopoll_win32_gettimeofday (&start, NULL);
#else
		gettimeofday (&start, NULL);
#endif
	
	/* set to keep looping everything this function is called */
	ctx->keep_looping = nopoll_true;

	while (ctx->keep_looping) {
		/* ok, now implement wait operation */
		ctx->io_engine->clear (ctx, ctx->io_engine->io_object);
		
		/* add all connections */
		/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Adding connections to watch: %d", ctx->conn_num);  */
		nopoll_ctx_foreach_conn (ctx, nopoll_loop_register, NULL);

		/* if (errno == EBADF) { */
			/* detected some descriptor not properly
			 * working, try to check them */
			/* nopoll_ctx_foreach_conn (ctx, nopoll_loop_clean_descriptors, NULL); */
		/* nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Found some descriptor is not valid (errno==%d)", errno);
		   continue; */ 
		/* } */ /* end if */
		
		/* implement wait operation */
		/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Waiting for changes into %d connections", ctx->conn_num); */
		wait_status = ctx->io_engine->wait (ctx, ctx->io_engine->io_object);
		/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Waiting finished with result %d", wait_status);  */
		if (wait_status == -1) {
			nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Received error from wait operation, error code was: %d", errno);
			break;
		} /* end if */

		/* check how many connections changed and restart */
		if (wait_status > 0) {
			/* check and call for connections with something
			 * interesting */
			nopoll_ctx_foreach_conn (ctx, nopoll_loop_process, &wait_status);
		}

		/* check to stop wait operation */
		if (timeout > 0) {
#if defined(NOPOLL_OS_WIN32)
			nopoll_win32_gettimeofday (&stop, NULL);
#else
			gettimeofday (&stop, NULL);
#endif
			nopoll_timeval_substract (&stop, &start, &diff);
			ellapsed = (diff.tv_sec * 1000000) + diff.tv_usec;
			if (ellapsed > timeout)
				break;
		} /* end if */
	} /* end while */

	/* release engine */
	nopoll_io_release_engine (ctx->io_engine);
	ctx->io_engine = NULL;

	return 0;
}