Beispiel #1
0
/* Destroys a ClientListener object and sets the pointer to NULL. */
void delClientListener(ClientListener** listener)
{
	if(!listener || !*listener)
		return;

	/* Notify our threads that we are deleting the object. */
	flag_raise(&(*listener)->flag_pole, OBJECT_DELETE_STATE);
	pthread_cond_broadcast(&(*listener)->t_cond);

	/* Delete dynamic members. */
	delArrayList(&(*listener)->client_list);

	/* Close open file descriptors. */
	if((*listener)->ep.efd)
		close((*listener)->ep.efd);

	/* Call destruction callbacks. */
	if((*listener)->free_extended_data && (*listener)->ex_data)
		(*listener)->free_extended_data((*listener)->ex_data);

	pthread_mutex_destroy(&(*listener)->mutex);
	pthread_cond_destroy(&(*listener)->t_cond);

	free(*listener);
	*listener = NULL;
}
Beispiel #2
0
/* Calls for the process waiter to stop, but it will
 * continue to run until at least one process exits. */
void proc_waiter_stop()
{
	if(!proc_waiter_is_initialized())
		return;

	/* Raise the flag to stop the thread, this should stop
	 * the thread whenever a child process closes. */
	flag_raise(&PROC_WAITER_FLAG_POLE, THREAD_STOP);

	/* Wake up the thread if it is waiting for a condition change. */
	pthread_cond_broadcast(PROC_WAITER_T_COND);
}
Beispiel #3
0
/* Similar to 'TcpClient_read_stop()', however it will not
 * block, but simply raise a flag for the reading thread to stop.
 *
 * This is good in many cases, however it is not as safe as the
 * synchronous version whenever the reading thread will be restarted.
 * If the reading thread is restarted before the thread returns, it
 * is possible that the restart will fail without warning.
 * To ensure the thread has returned after requesting for it to stop
 * asynchronously, call 'TcpClient_read_thread_wait()'. */
void TcpClient_read_stop_async(TcpClient* client)
{
	if(!client)return;

	flag_raise(&client->flag_pole, THREAD_STOP);
	if((client->flag_pole & THREAD_CREATED) &&
			(client->flag_pole & THREAD_IS_RUNNING))
	{
		pthread_detach(client->read_thread);
		flag_lower(&client->flag_pole, THREAD_CREATED);
	}
}
Beispiel #4
0
/* Stops the reading process on the client.
 * This function call WILL BLOCK until the reading thread returns
 * which may be several seconds, depending on the timeout set for recv().
 *
 * If immediate return is required, then call 'TcpClient_read_stop_async()'. */
void TcpClient_read_stop(TcpClient* client)
{
	if(!client)return;

	if(client->flag_pole & THREAD_CREATED)
	{
		flag_raise(&client->flag_pole, THREAD_STOP);
		pthread_join(client->read_thread, NULL);
		flag_lower(&client->flag_pole, THREAD_CREATED);
	}
	else if(client->flag_pole & THREAD_IS_RUNNING)
		TcpClient_read_thread_wait(client);
}
Beispiel #5
0
/* Function used to start listening to client events on a separate
 * thread. */
static void* threaded_run(void* v_listener)
{
	ClientListener* listener = (ClientListener*)v_listener;

	flag_raise(&listener->flag_pole, THREAD_IS_RUNNING);
	flag_lower(&listener->flag_pole, THREAD_STOP);
	listen_loop(listener);
	flag_lower(&listener->flag_pole, THREAD_IS_RUNNING);

	/* Epoll is no longer in use, we should close
	 * the file descriptor. */
	close_epoll_tsafe(listener);
	return(NULL);
}
Beispiel #6
0
/* Disconnects the client and destroys the object. */
void delTcpClient(TcpClient** client)
{
	if(!client || !*client ||
			((*client)->flag_pole & OBJECT_DELETE_STATE))return;

	/* Place the object in a delete state. */
	flag_raise(&(*client)->flag_pole, OBJECT_DELETE_STATE);
    TcpClient_disconnect(*client);
	
    if((*client)->free_data_cb)
		(*client)->free_data_cb((*client)->ex_data);

	free(*client);
	client = NULL;
}
Beispiel #7
0
/* Starts clients in the ClientListener on a separate thread.  The
 * thread is managed internally and can be stopped by calling
 * 'ClientListener_stop()' or 'delClientListener()'.
 *
 * Returns:
 * 		ALIB_OK: Thread is already running, or thread was started without error.
 * 			Any error that occurs after this was raised in the listen loop.
 * 		Anything else: Error code related to the error.
 */
alib_error ClientListener_start_async(ClientListener* listener)
{
	if(!listener)return(ALIB_BAD_ARG);

	int err = ALIB_OK;
	/* Check to see if the thread is running. */
	if(listener->flag_pole & THREAD_IS_RUNNING)
	{
		/* If we are supposed to stop the thread, then stop the
		 * ClientListener. */
		if(listener->flag_pole & THREAD_STOP)
			ClientListener_stop(listener);
		/* Otherwise, the thread is already running, there is nothing to do. */
		else
			return(ALIB_OK);
	}

	flag_lower(&listener->flag_pole, THREAD_STOP);

	/* Initialize the epoll. */
	err = init_epoll_tsafe(listener);
	if(err)	return(err);
	/* Add the clients to the epoll. */
	err = add_clients_to_epoll_tsafe(listener);
	if(err)goto f_error;


	/* Create the thread. */
	if(listener->flag_pole & THREAD_CREATED)
		pthread_join(listener->thread, NULL);
	else
		flag_raise(&listener->flag_pole, THREAD_CREATED);

	if(pthread_create(&listener->thread, NULL, threaded_run, listener))
	{
		/* If creation failed, then we need to return an error. */
		flag_lower(&listener->flag_pole, THREAD_CREATED);
		err = ALIB_THREAD_ERR;
		goto f_error;
	}

	return(ALIB_OK);
f_error:
	ClientListener_stop(listener);

	return(err);
}
Beispiel #8
0
/* Starts the thread.  If the thread is already running
 * ALIB_OK will be returned.
 *
 * Waiting for child processes to close is handled on a separate thread. */
alib_error proc_waiter_start()
{
	int err = allocate_globals();
	if(err)return(err);

	/* Make sure we don't call start at the same time from two different threads. */
	pthread_mutex_lock(PROC_WAITER_MUTEX);

	/* Setup the flags as needed. */
	flag_lower(&PROC_WAITER_FLAG_POLE, THREAD_STOP);

	if((PROC_WAITER_FLAG_POLE & THREAD_IS_RUNNING) &&
			(PROC_WAITER_FLAG_POLE & THREAD_CREATED))
	{
		err = ALIB_OK;
		goto f_unlock;
	}

	/* Check to see if we are still running. */
	if(PROC_WAITER_FLAG_POLE & THREAD_IS_RUNNING)
		proc_waiter_stop_now();

	/* Ensure our thread is cleaned up. */
	if(PROC_WAITER_FLAG_POLE & THREAD_CREATED)
		pthread_join(*PROC_WAITER_THREAD, NULL);

	/* Raise the THREAD_IS_RUNNING flag before creating the thread so that the flag
	 * will never misrepresent the state of the thread. */
	flag_raise(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING | THREAD_CREATED);
	if(pthread_create(PROC_WAITER_THREAD, NULL, thread_proc, NULL))
	{
		flag_lower(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING | THREAD_CREATED);
		err = ALIB_THREAD_ERR;
		goto f_unlock;
	}

f_unlock:
	pthread_mutex_unlock(PROC_WAITER_MUTEX);

	return(err);
}
Beispiel #9
0
/* Stops a currently running ClientListener object.  If the object
 * is already stopped, nothing will happen.
 *
 * This should be called whenever the object is no longer running. */
alib_error ClientListener_stop(ClientListener* listener)
{
	if(!listener)return(ALIB_BAD_ARG);

	/* Set the stop flag for the thread. */
	if(listener->flag_pole & THREAD_IS_RUNNING)
		flag_raise(&listener->flag_pole, THREAD_STOP);

	/* Close the epoll socket to break epoll_wait(). */
	close_epoll_tsafe(listener);

	/* If a thread has been created, join it. */
	if(listener->flag_pole & THREAD_CREATED)
	{
		pthread_cond_broadcast(&listener->t_cond);
		pthread_join(listener->thread, NULL);
		flag_lower(&listener->flag_pole, THREAD_CREATED);
	}

	return(ALIB_OK);
}
Beispiel #10
0
/* Called whenever a client is removed from the array list. */
static void remove_client_cb(void* v_sock_pack)
{
	socket_package* sp = (socket_package*)v_sock_pack;
	ClientListener* listener = (ClientListener*)sp->parent;

	/* Call the server's client disconnected callback. */
	if(listener->disconnected)
	{
		int rval = listener->disconnected(listener, sp);
		if(rval & SCB_RVAL_STOP_SERVER)
		{
			flag_raise(&listener->flag_pole, THREAD_STOP);
			close(listener->ep.efd);
			listener->ep.efd = -1;
		}
	}

	/* Free the socket package. */
	close_and_free_socket_package(sp);
	pthread_cond_broadcast(&listener->t_cond);
}
task main()
{
	waitForStart();

	while (true)
	{
		getJoystickSettings(joystick);
		//driver controls
		int cont1_left_yval = avoidWeird(joystick.joy1_y1, 20); //y coordinate for the left joystick on controller 1
		int cont1_left_xval = avoidWeird(joystick.joy1_x1, 75); //x coordinate for the left joystick on controller 1
		int cont1_right_yval = avoidWeird(joystick.joy1_y2, 20); //y coordinate for the right joystick on controller 1
		//arm/hand controls
		int cont2_right_yval = avoidWeird(joystick.joy2_y2, 20);
		int cont2_left_yval = avoidWeird(joystick.joy2_y1, 20);
		//int cont1_dPad = joystick.joy1_TopHat; //Value of the dPad for controller 2

		drive(cont1_left_yval, cont1_left_xval);
		shoulderMovement(cont2_right_yval);
		handMovement(cont2_left_yval);
		flag_raise(cont1_right_yval);

	}
}
Beispiel #12
0
/* Starts the reading process on the client. */
alib_error TcpClient_read_start(TcpClient* client)
{
	if(!client)return(ALIB_BAD_ARG);
	else if((client->flag_pole & THREAD_IS_RUNNING) &&
			!(client->flag_pole & THREAD_STOP))
		return(ALIB_OK);
	/* Thread has been called to stop, but hasn't yet. */
	else
		TcpClient_read_stop(client);

	if(client->data_in_cb && client->sock >= 0)
	{
		flag_lower(&client->flag_pole, THREAD_STOP);
		flag_raise(&client->flag_pole, THREAD_CREATED);
		if(pthread_create(&client->read_thread, NULL, read_loop_proc, client))
		{
			flag_lower(&client->flag_pole, THREAD_CREATED);
			return(ALIB_THREAD_ERR);
		}
	}

	return(ALIB_OK);
}
Beispiel #13
0
/*******Private Functions*******/
static void* thread_proc(void* unused)
{
	int status;
	int pid;
	proc_waiter** pw_it;
	size_t pw_it_count;

	if(!proc_waiter_is_initialized())
		return(NULL);

	flag_raise(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING);
	while(PROC_WAITER_CB_LIST && !(PROC_WAITER_FLAG_POLE & THREAD_STOP))
	{
#ifdef __ANDROID__
		pid = wait(&status);
#else
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
		pid = wait(&status);
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#endif

		/* There are no child processes connected to the current process. */
		if(pid < 0)
		{
			pthread_mutex_lock(PROC_WAITER_MUTEX);
			if(!PROC_WAITER_CB_LIST)
			{
				pthread_mutex_unlock(PROC_WAITER_MUTEX);
				break;
			}

			if(!ArrayList_get_count(PROC_WAITER_CB_LIST))
			{
				while(PROC_WAITER_CB_LIST &&
						!ArrayList_get_count(PROC_WAITER_CB_LIST) &&
						!(PROC_WAITER_FLAG_POLE & THREAD_STOP))
				{
					pthread_cond_wait(PROC_WAITER_T_COND, PROC_WAITER_MUTEX);
				}
			}
			else if(PROC_WAITER_SLEEP_TIME < 0)
				pthread_cond_wait(PROC_WAITER_T_COND, PROC_WAITER_MUTEX);
			else
			{
				struct timespec sleepTo;
				clock_gettime(CLOCK_REALTIME, &sleepTo);
				sleepTo.tv_nsec += PROC_WAITER_SLEEP_TIME;
				timespec_fix_values(&sleepTo);
				pthread_cond_timedwait(PROC_WAITER_T_COND, PROC_WAITER_MUTEX, &sleepTo);
			}

			pthread_mutex_unlock(PROC_WAITER_MUTEX);
		}
		else
		{
			/* Iterate through the list and call the registered callbacks. */
			ArrayList_lock(PROC_WAITER_CB_LIST);
			for(pw_it = (proc_waiter**)ArrayList_get_array_ptr(PROC_WAITER_CB_LIST), pw_it_count = 0;
					pw_it_count < ArrayList_get_count(PROC_WAITER_CB_LIST);++pw_it)
			{
				if(*pw_it)
				{
					++pw_it_count;

					/* Call the registered callback. */
					if(((*pw_it)->pid < 0 || (*pw_it)->pid == pid))
					{
						if((*pw_it)->cb)
							(*pw_it)->cb(pid, status, (*pw_it)->user_data);

						/* Deregister an event callback if the pid is not a wildcard
						 * number. Check 'pw_it' again to ensure it wasn't deleted in
						 * the callback. */
						if(*pw_it && (*pw_it)->pid > -1)
							ArrayList_remove_by_ptr(PROC_WAITER_CB_LIST, (void**)pw_it);
					}
				}
			}
			ArrayList_unlock(PROC_WAITER_CB_LIST);
		}
	}

	flag_lower(&PROC_WAITER_FLAG_POLE, THREAD_IS_RUNNING);
	pthread_cond_broadcast(PROC_WAITER_T_COND);
	return(NULL);
}
Beispiel #14
0
/* Calls receive on the client's socket until either an error happens
 * or the socket is closed. */
static void* read_loop_proc(void* void_client)
{
	TcpClient* client = (TcpClient*)void_client;
	char in_buff[64 * 1024];
	int in_count;
	int rval;
	struct timeval tv;
	socklen_t tv_len = sizeof(tv);

	flag_raise(&client->flag_pole, THREAD_IS_RUNNING);
	pthread_cond_broadcast(&client->read_cond);

	/* Ensure there is a timeout set for the socket.  If one does not
	 * exist, then set the timeout to 1 second. */
	if(getsockopt(client->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len))
		goto f_return;
	if(!tv.tv_sec && !tv.tv_usec)
	{
		tv.tv_sec = 1;
		if(setsockopt(client->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, tv_len))
				goto f_return;
	}

	while(!(client->flag_pole & THREAD_STOP) && client->sock > -1 &&
			client->data_in_cb)
	{
		/* Wait for data. */
		in_count = recv(client->sock, in_buff, sizeof(in_buff), 0);

		/* Disconnected/error occurred. */
		if(in_count <= 0)
		{
			if(errno == EWOULDBLOCK)
			{
				errno = 0;
				continue;
			}
			else
			{
				/* We can't call 'TcpClient_disconnect()' if the object is in a delete
				 * state because it has already been called. */
				if(!(client->flag_pole & OBJECT_DELETE_STATE))
					TcpClient_disconnect(client);
				break;
			}
		}
		/* Data received. */
		else
		{
			rval = client->data_in_cb(client, in_buff, in_count);
			if(rval & (SCB_RVAL_CLOSE_CLIENT | SCB_RVAL_STOP_SERVER))
				TcpClient_disconnect(client);
			if(rval & (SCB_RVAL_DELETE))
			{
				pthread_detach(client->read_thread);
				flag_lower(&client->flag_pole, THREAD_CREATED);
				delTcpClient(&client);
			}
		}
	}

f_return:
	flag_lower(&client->flag_pole, THREAD_IS_RUNNING);
	pthread_cond_broadcast(&client->read_cond);

	if(client->thread_returning_cb)
		client->thread_returning_cb(client);

	return(NULL);
}
Beispiel #15
0
/* The main listening loop for the object. */
static alib_error listen_loop(ClientListener* listener)
{
	if(!listener)return(ALIB_BAD_ARG);

	int rval;
	int event_count;
	struct epoll_event* event_it;
	long data_in_count;
	void* data_in_buff = malloc(DEFAULT_INPUT_BUFF_SIZE);

	/* Ensure we were able to allocate the data in buffer. */
	if(!data_in_buff)
	{
		rval = ALIB_MEM_ERR;
		goto f_return;
	}

	/* While our socket is open, then we will keep running. */
	while(!(listener->flag_pole & THREAD_STOP))
	{
		/* If the array list is empty, then we simply wait until something is added
		 * to it or our thread is called to stop. */
		if(!ArrayList_get_count(listener->client_list))
		{
			/* Call the empty list callback. */
			if(listener->client_list_empty)
			{
				int rval = listener->client_list_empty(listener);
				if(rval & SCB_RVAL_STOP_SERVER)
					break;
			}

			pthread_mutex_lock(&listener->mutex);
			while(!ArrayList_get_count(listener->client_list) && !(listener->flag_pole & THREAD_STOP))
				pthread_cond_wait(&listener->t_cond, &listener->mutex);
			pthread_mutex_unlock(&listener->mutex);
			continue;
		}

		/* Wait for an event to come. */
		event_count = epoll_wait(listener->ep.efd, listener->ep.triggered_events, DEFAULT_BACKLOG_SIZE,
				1000);
		if(!event_count)continue;

		/* The the event_count is less than zero, then an error occurred. */
		if(event_count < 0)
		{
			if(listener->flag_pole & THREAD_STOP)
				rval = ALIB_OK;
			else
			{
				if(listener->ep.efd > -1)
					continue;
				rval = ALIB_CHECK_ERRNO;
			}

			goto f_return;
		}

		/* Iterate through the events. */
		if(pthread_mutex_lock(&listener->mutex))
		{
			rval = ALIB_MUTEX_ERR;
			goto f_return;
		}
		for(event_it = listener->ep.triggered_events; event_count > 0; ++event_it, --event_count)
		{
			/* Use compare_int_ptr as the first member in the socket package
			 * is an integer. */
			socket_package* client = (socket_package*)ArrayList_find_item_by_value_tsafe(
					listener->client_list, &event_it->data.fd, compare_int_ptr);
			if(!client)
			{
				close(listener->ep.triggered_events->data.fd);
				continue;
			}

			/* Error occurred on the socket. */
			if((event_it->events & (EPOLLERR | EPOLLHUP)) ||
					!(event_it->events & EPOLLIN))
			{
				ArrayList_remove_tsafe(listener->client_list, client);
				continue;
			}

			/* Call the client_data_ready callback. */
			if(listener->data_ready)
			{
				rval = listener->data_ready(listener, client, &data_in_buff,
						&data_in_count);
				if(rval & SCB_RVAL_CLOSE_CLIENT)
					ArrayList_remove_tsafe(listener->client_list, client);
				if(rval & SCB_RVAL_STOP_SERVER)
				{
					rval = ALIB_OK;
					flag_raise(&listener->flag_pole, THREAD_STOP);
					if(pthread_mutex_unlock(&listener->mutex))
						rval = ALIB_MUTEX_ERR;
					goto f_return;
				}

				if(rval & (SCB_RVAL_HANDLED | SCB_RVAL_CLOSE_CLIENT))
					continue;

			}
			else
			{
				data_in_count = recv(client->sock, data_in_buff,
						DEFAULT_INPUT_BUFF_SIZE, 0);
			}

			/* If the client's socket was closed, then we just remove it
			 * from the list. */
			if(data_in_count < 1)
				ArrayList_remove_tsafe(listener->client_list, client);
			/* Call the client data in callback. */
			else if(listener->data_in)
			{
				rval = listener->data_in(listener, client, data_in_buff,
						data_in_count);
				if(rval & SCB_RVAL_CLOSE_CLIENT)
					ArrayList_remove_tsafe(listener->client_list, client);
				if(rval & SCB_RVAL_STOP_SERVER)
				{
					rval = ALIB_OK;
					if(pthread_mutex_unlock(&listener->mutex))
						rval = ALIB_MUTEX_ERR;
					goto f_return;
				}
			}
		}
		if(pthread_mutex_unlock(&listener->mutex))
		{
			rval = ALIB_MUTEX_ERR;
			goto f_return;
		}
	}

	rval = ALIB_OK;

f_return:
	if(data_in_buff)
		free(data_in_buff);

	return(rval);
}