/** * \fn void rq_state_start_stream(void) * \brief Send the command to start the streaming mode * If the stream doesn't start, return to state init. * Set the next state to \ref RQ_STATE_RUN */ static void rq_state_start_stream() { if(rq_com_start_stream() == -1) { #if defined(_WIN32)||defined(WIN32) //For Windows stop_connection(); #endif current_state = RQ_STATE_INIT; } current_state = RQ_STATE_RUN; }
/** * @brief read from a connection */ void *connection_reader(void *arg) { struct message *msg; conn_node *c; c=(conn_node *) arg; #ifndef NDEBUG print( DEBUG, "started (fd=%d, tid=%lu)", c->fd, pthread_self() ); #endif while((msg = read_message(c->fd))) { pthread_mutex_lock(&(c->control.mutex)); while(c->freeze) { pthread_cond_wait(&(c->control.cond), &(c->control.mutex)); } pthread_mutex_unlock(&(c->control.mutex)); if(enqueue_message(&(c->incoming), msg)) { print( ERROR, "cannot enqueue received message" ); dump_message(msg); free_message(msg); } } stop_connection(c); pthread_mutex_lock(&(c->control.mutex)); while(!c->writer_done || !c->worker_done) { pthread_cond_wait(&(c->control.cond), &(c->control.mutex)); } pthread_mutex_unlock(&(c->control.mutex)); pthread_mutex_lock(&(connections.control.mutex)); list_del(&(connections.list), (node *)c); pthread_mutex_unlock(&(connections.control.mutex)); pthread_cond_broadcast(&(connections.control.cond)); close(c->fd); #ifndef NDEBUG print( DEBUG, "connection closed (fd=%d)", c->fd ); #endif // add me to the death list send_me_to_graveyard(); free_connection(c); return 0; }
/** * \fn void rq_state_run() * \brief Capture and read the stream from the sensor. * If the stream is not valid, return to state * \ref RQ_STATE_INIT */ static void rq_state_run() { rq_com_listen_stream(); if(rq_com_get_valid_stream() == false) { #if defined(_WIN32)||defined(WIN32) //For Windows stop_connection(); #endif current_state = RQ_STATE_INIT; } }
/** * @brief close all connections from ::connections */ void close_connections() { register conn_node *c; pthread_mutex_lock(&(connections.control.mutex)); // equivalent to control_deactivate connections.control.active = 0; for(c=(conn_node *) connections.list.head;c;c=(conn_node *) c->next) { stop_connection(c); } // wait that all connection threads ends while(connections.list.head) { pthread_cond_wait(&(connections.control.cond), &(connections.control.mutex)); } pthread_mutex_unlock(&(connections.control.mutex)); }
/** * @brief start a @connection_handler for a new client. * @param fd file descriptor of the new client * @returns 0 on success, -1 on error. */ int serve_new_client(int fd) { conn_node *c; pthread_t dummy; int writer_created, worker_created; pthread_mutex_lock(&(connections.control.mutex)); writer_created = connections.control.active; // OPTIMIZATION pthread_mutex_unlock(&(connections.control.mutex)); if(!writer_created) { print( ERROR, "connections disabled" ); return -1; } writer_created = worker_created = 0; c = malloc(sizeof(conn_node)); if(!c) { print( ERROR, "malloc: %s", strerror(errno) ); return -1; } memset(c, 0, sizeof(conn_node)); if(control_init(&(c->control)) || control_init(&(c->incoming.control)) || control_init(&(c->outcoming.control))) { print( ERROR, "cannot init cotnrols" ); free_connection(c); return -1; } c->fd = fd; pthread_mutex_lock(&(connections.control.mutex)); if( (writer_created = pthread_create(&dummy, NULL, &connection_writer, (void *)c)) || (worker_created = pthread_create(&dummy, NULL, &connection_worker, (void *)c)) || pthread_create(&dummy, NULL, &connection_reader, (void *)c)) { pthread_mutex_unlock(&(connections.control.mutex)); print( ERROR, "pthread_create: %s", strerror(errno) ); goto create_error; } list_add(&(connections.list), (node *) c); pthread_mutex_unlock(&(connections.control.mutex)); pthread_cond_broadcast(&(connections.control.cond)); return 0; create_error: if(writer_created || worker_created) { stop_connection(c); pthread_mutex_lock(&(c->control.mutex)); while((writer_created && !c->writer_done) || (worker_created && !c->worker_done)) { pthread_cond_wait(&(c->control.cond), &(c->control.mutex)); } pthread_mutex_unlock(&(c->control.mutex)); } free_connection(c); return -1; }