static void test_foreach_message_queue() { message_queue *queue = create_message_queue(); assert_true( queue != NULL ); buffer *first_buf = alloc_buffer(); append_string( first_buf, "first_buffer" ); assert_true( enqueue_message( queue, first_buf ) ); assert_int_equal( queue->length, 1 ); buffer *second_buf = alloc_buffer(); append_string( second_buf, "second_buffer" ); assert_true( enqueue_message( queue, second_buf ) ); assert_int_equal( queue->length, 2 ); buffer *third_buf = alloc_buffer(); append_string( third_buf, "third_buffer" ); assert_true( enqueue_message( queue, third_buf ) ); assert_int_equal( queue->length, 3 ); buffer *deq_buf = dequeue_message( queue ); assert_true( deq_buf == first_buf ); char *user_data = xstrdup( "user_data" ); count = 0; foreach_message_queue( queue, test_foreach_message_queue_helper, user_data ); assert_int_equal( count, 2 ); xfree( user_data ); assert_true( delete_message_queue( queue ) ); }
static void test_multiple_queueing() { message_queue *queue = create_message_queue(); assert_true( queue != NULL ); buffer *first_buf = alloc_buffer(); assert_true( enqueue_message( queue, first_buf ) ); assert_int_equal( queue->length, 1 ); buffer *deq_buf = dequeue_message( queue ); assert_true( deq_buf == first_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 0 ); first_buf = alloc_buffer(); assert_true( enqueue_message( queue, first_buf ) ); assert_int_equal( queue->length, 1 ); buffer *second_buf = alloc_buffer(); assert_true( enqueue_message( queue, second_buf ) ); assert_int_equal( queue->length, 2 ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == first_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 1 ); buffer *third_buf = alloc_buffer(); assert_true( enqueue_message( queue, third_buf ) ); assert_int_equal( queue->length, 2 ); buffer *fourth_buf = alloc_buffer(); assert_true( enqueue_message( queue, fourth_buf ) ); assert_int_equal( queue->length, 3 ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == second_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 2 ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == third_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 1 ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == fourth_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 0 ); assert_true( delete_message_queue( queue ) ); }
static INLINE void * remote_context_create_rasterizer_state(struct pipe_context *_pipe, const struct pipe_rasterizer_state *state) { ALLOC_OUT_MESSAGE(create_rast_state, message); message->base.opcode = REMREQ_CREATE_RAST_STATE; message->pipe = PIPE_HANDLE(_pipe); message->state = *state; // Struct copy uint32_t handle = get_fresh_rast_handle(_pipe->screen); message->handle = handle; DBG("Create new rasterizer state: handle %u\n", handle); enqueue_message(message); struct remote_opaque_rast_state* remote_rast = CALLOC_STRUCT(remote_opaque_rast_state); PANIC_IF_NULL(remote_rast); remote_rast->handle = handle; return remote_rast; }
/** * @brief notify the command receiver that a chid printed a line on it's stderr. * @param c the child hat generated @p line * @param line the line received from the child stderr * @returns 0 on success, -1 on error. */ int on_cmd_stderr(child_node *c, char *line) { message *m; struct cmd_stderr_info *stderr_info; size_t len; uint16_t seq; seq = get_sequence(&(c->conn->ctrl_seq), &(c->conn->control.mutex)); len = strlen(line) + 1; m = create_message(seq, sizeof(struct cmd_stderr_info) + len, CTRL_ID); if(!m) { print(ERROR, "cannot create messages"); return -1; } stderr_info = (struct cmd_stderr_info *) m->data; stderr_info->cmd_action = CMD_STDERR; stderr_info->id = c->id; memcpy(stderr_info->line, line, len); if(enqueue_message(&(c->conn->outcoming), m)) { print(ERROR, "cannot enqueue messages"); dump_message(m); free_message(m); return -1; } return 0; }
static INLINE void remote_context_bind_sampler_states(struct pipe_context *_pipe, unsigned num_states, void **states) { DBG("Bind sampler states: %u states\n", num_states); struct remreq_bind_sampler_state* header = allocate_message_memory( sizeof(struct remreq_bind_sampler_state) + (num_states * sizeof(uint32_t))); header->base.opcode = REMREQ_BIND_SAMPLER_STATE; header->pipe = PIPE_HANDLE(_pipe); header->nstates = num_states; uint32_t* state_handles = (uint32_t*)((char*)header + sizeof(struct remreq_bind_sampler_state)); unsigned i; for(i = 0; i < num_states; i++) { state_handles[i] = SAMPLER_HANDLE(states[i]); } enqueue_message(header); }
static void test_enqueue_message_if_queue_is_not_created() { message_queue *queue = NULL; buffer *enq_buf = alloc_buffer(); expect_assert_failure( enqueue_message( queue, enq_buf ) ); free_buffer( enq_buf ); }
static INLINE void remote_context_set_constant_buffer(struct pipe_context *_pipe, uint shader, uint index, const struct pipe_constant_buffer *buffer) { DBG("Set constant buffer for shader %u, index %u\n", shader, index); ALLOC_OUT_MESSAGE(set_constant_buffer, message); message->base.opcode = REMREQ_SET_CONSTANT_BUFFER; message->pipe = PIPE_HANDLE(_pipe); message->shader = shader; message->index = index; message->buffer_size = buffer->size; message->buffer = BUFFER_HANDLE(buffer->buffer); /* char* mapped = (char*)pipe_buffer_map(_pipe->screen, buffer->buffer, PIPE_BUFFER_USAGE_CPU_READ); printf("On setting, constant buffer goes like this:\n"); int i; for(i = 0; i < buffer->size; i++) { printf("%4d ", (int)mapped[i]); if(i % 8 == 7) printf("\n"); } printf("\n"); pipe_buffer_unmap(_pipe->screen, buffer->buffer); */ enqueue_message(message); }
static INLINE void remote_context_set_edgeflags(struct pipe_context *_pipe, const unsigned *bitfield) { if(bitfield) { DBG("Set edge flags: %u\n", *bitfield); } else { DBG("Set edge flags: null\n"); } ALLOC_OUT_MESSAGE(set_edgeflags, message); message->base.opcode = REMREQ_SET_EDGEFLAGS; message->pipe = PIPE_HANDLE(_pipe); if(bitfield) { message->isnull = 0; message->flag = *bitfield; } else { message->isnull = 1; } enqueue_message(message); }
static INLINE void remote_context_set_framebuffer_state(struct pipe_context *_pipe, const struct pipe_framebuffer_state *state) { unsigned i; ALLOC_OUT_MESSAGE(set_framebuffer_state, message); message->base.opcode = REMREQ_SET_FRAMEBUFFER_STATE; message->pipe = PIPE_HANDLE(_pipe); message->fbwidth = state->width; message->fbheight = state->height; message->fbnum_cbufs = state->num_cbufs; message->fbzsbuf = state->zsbuf ? SURFACE_HANDLE(state->zsbuf) : 0; for(i = 0; i < PIPE_MAX_COLOR_BUFS; i++) message->fbcbufs[i] = state->cbufs[i] ? SURFACE_HANDLE(state->cbufs[i]) : 0; DBG("Set framebuffer state: %dx%d\n", state->width, state->height); if(message->fbzsbuf) { DBG("Z/stencil buffer: %u\n", message->fbzsbuf); } else { DBG("No Z/stencil buffer\n"); } for(i = 0; i < PIPE_MAX_COLOR_BUFS; i++) if(message->fbcbufs[i]) DBG("Colour buffer %d: texture %u\n", i, message->fbcbufs[i]); enqueue_message(message); struct remote_context* rctx = (struct remote_context*)_pipe; rctx->current_framebuffer_state = *state; // Struct copy }
static INLINE struct pipe_query * remote_context_create_query(struct pipe_context *_pipe, unsigned query_type) { // Despite appearances, pipe_query is actually an opaque struct. ALLOC_OUT_MESSAGE(create_query, message); message->base.opcode = REMREQ_CREATE_QUERY; message->pipe = PIPE_HANDLE(_pipe); message->query_type = query_type; uint32_t handle = get_fresh_query_handle(_pipe->screen); DBG("New query %u, type %x\n", handle, query_type); message->handle = handle; enqueue_message(message); struct remote_pipe_query* opaque = CALLOC_STRUCT(remote_pipe_query); PANIC_IF_NULL(opaque); opaque->handle = handle; return (struct pipe_query*)opaque; }
static INLINE void * remote_context_create_vs_state(struct pipe_context *_pipe, const struct pipe_shader_state *state) { int tokens = tgsi_num_tokens(state->tokens); struct remreq_create_vs_state* header = allocate_message_memory( sizeof(struct remreq_create_vs_state) + (tokens * sizeof(struct tgsi_token))); uint32_t handle = get_fresh_vs_handle(_pipe->screen); DBG("Create new VS state: handle %u\n", handle); header->base.opcode = REMREQ_CREATE_VS_STATE; header->pipe = PIPE_HANDLE(_pipe); header->vs_handle = handle; char* copy_dest = ((char*)header) + sizeof(struct remreq_create_vs_state); memcpy(copy_dest, (char*)(state->tokens), sizeof(struct tgsi_token) * tokens); enqueue_message(header); struct opaque_remote_vs* retval = CALLOC_STRUCT(opaque_remote_vs); PANIC_IF_NULL(retval); retval->handle = handle; return retval; }
/** * @brief handle a command request. * @param c the connection that send @p msg * @param msg the request ::message * @returns 0 on success, -1 on error. */ int on_command_request(conn_node *c, message *msg) { message *reply; switch(msg->data[0]) { case CMD_START: reply = on_cmd_start(c, msg); break; case CMD_SIGNAL: reply = on_cmd_signal(c, msg); break; default: print( ERROR, "unknown command '%02hhX'", msg->data[0] ); reply = NULL; break; } if(!reply) return 0; if(enqueue_message(&(c->outcoming), reply)) { print( ERROR, "cannot enqueue message" ); dump_message(reply); free_message(reply); return -1; } return 0; }
static INLINE void remote_context_set_sampler_textures(struct pipe_context *_pipe, unsigned num_textures, struct pipe_texture **textures) { // Similar to below DBG("Set sampler textures\n"); struct remreq_set_sampler_textures* header = (struct remreq_set_sampler_textures*) allocate_message_memory( sizeof(struct remreq_set_sampler_textures) + num_textures * sizeof(uint32_t)); header->base.opcode = REMREQ_SET_SAMPLER_TEXTURES; header->pipe = PIPE_HANDLE(_pipe); header->num_textures = num_textures; uint32_t* texhandles = (uint32_t*) ((char*)header + sizeof(struct remreq_set_sampler_textures)); unsigned i; for(i = 0; i < num_textures; i++) { texhandles[i] = textures[i] ? TEXTURE_HANDLE(textures[i]) : 0; DBG("Sampler slot %d: texture %u\n", i, texhandles[i]); } enqueue_message(header); }
static INLINE boolean remote_context_draw_arrays(struct pipe_context *_pipe, unsigned mode, unsigned start, unsigned count) { DBG("Draw arrays: mode %u, start %u, count %u\n", mode, start, count); mark_framebuffer_dirty(_pipe); ALLOC_OUT_MESSAGE(draw_arrays, message); message->base.opcode = REMREQ_DRAW_ARRAYS; message->pipe = PIPE_HANDLE(_pipe); message->mode = mode; message->start = start; message->count = count; enqueue_message(message); return true; /* QUEUE_AND_WAIT(message, draw_arrays, reply); PANIC_IF_NULL(reply); boolean success = reply->success; free_message(reply); return success; */ }
static INLINE void remote_context_set_vertex_elements(struct pipe_context *_pipe, unsigned num_elements, const struct pipe_vertex_element *elements) { // Send array DBG("Set vertex elements: %u elements\n", num_elements); struct remreq_set_vertex_elements* header = (struct remreq_set_vertex_elements*) allocate_message_memory( sizeof(struct remreq_set_vertex_elements) + num_elements * sizeof(struct pipe_vertex_element)); header->base.opcode = REMREQ_SET_VERTEX_ELEMENTS; header->pipe = PIPE_HANDLE(_pipe); header->num_elements = num_elements; char* dest = ((char*)header) + sizeof(struct remreq_set_vertex_elements); memcpy(dest, (void*)elements, num_elements * sizeof(struct pipe_vertex_element)); enqueue_message(header); }
static INLINE void remote_context_surface_copy(struct pipe_context *_pipe, boolean do_flip, struct pipe_surface *dest, unsigned destx, unsigned desty, struct pipe_surface *src, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { DBG("Surface copy: %u-%ux%u-%ux%u --> %u-%ux%u\n", SURFACE_HANDLE(src), srcx, srcy, srcx + width, srcy + height, SURFACE_HANDLE(dest), destx, desty); ALLOC_OUT_MESSAGE(surface_copy, message); message->base.opcode = REMREQ_SURFACE_COPY; message->pipe = PIPE_HANDLE(_pipe); message->src = SURFACE_HANDLE(src); message->dest = SURFACE_HANDLE(dest); message->sx = srcx; message->sy = srcy; message->dx = destx; message->dy = desty; message->w = width; message->h = height; message->do_flip = do_flip; enqueue_message(message); }
static void test_enqueue_message_if_message_is_NULL() { message_queue *queue = create_message_queue(); assert_true( queue != NULL ); assert_int_equal( queue->length, 0 ); expect_assert_failure( enqueue_message( queue, NULL ) ); assert_true( delete_message_queue( queue ) ); }
void respond_cd(t_socket *connection, t_message packet) { char *params = (char *) malloc(sizeof(char) * packet.size - 2); strncpy(params, packet.data, packet.size - 3); params[packet.size - 3] = '\0'; char buffer[2048]; if (!cd(params)) { sprintf(buffer, "remote chdir at '%s'\n", params); text_message(connection, TYPE_SCREEN, buffer); } else if (errno == EACCES) enqueue_message(connection, error_message(2, packet.sequence)); else enqueue_message(connection, error_message(1, packet.sequence)); if (params != NULL) free(params); }
static void recv_from_secure_channel( int fd, void *user_data ) { UNUSED( fd ); UNUSED( user_data ); // all queued messages should be processed before receiving new messages from remote if ( recv_queue->length > 0 ) { return; } if ( fragment_buf == NULL ) { fragment_buf = alloc_buffer_with_length( RECEIVE_BUFFFER_SIZE ); } size_t remaining_length = RECEIVE_BUFFFER_SIZE - fragment_buf->length; char *recv_buf = ( char * ) fragment_buf->data + fragment_buf->length; ssize_t recv_length = read( connection.fd, recv_buf, remaining_length ); if ( recv_length < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { return; } error( "Receive error ( errno = %s [%d] ).", strerror( errno ), errno ); return; } if ( recv_length == 0 ) { debug( "Connection closed by peer." ); disconnected(); reconnect( NULL ); return; } fragment_buf->length += ( size_t ) recv_length; size_t read_total = 0; while ( fragment_buf->length >= sizeof( struct ofp_header ) ) { struct ofp_header *header = fragment_buf->data; uint16_t message_length = ntohs( header->length ); if ( message_length > fragment_buf->length ) { break; } buffer *message = alloc_buffer_with_length( message_length ); char *p = append_back_buffer( message, message_length ); memcpy( p, fragment_buf->data, message_length ); remove_front_buffer( fragment_buf, message_length ); enqueue_message( recv_queue, message ); read_total += message_length; } // remove headroom manually for next call if ( read_total > 0 ) { memmove( ( char * ) fragment_buf->data - read_total, fragment_buf->data, fragment_buf->length ); fragment_buf->data = ( char * ) fragment_buf->data - read_total; } while ( recv_message_from_secure_channel() == true ); }
/** * @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; }
static void test_enqueue_and_delete_message_queue() { message_queue *queue = create_message_queue(); assert_true( queue != NULL ); assert_int_equal( queue->length, 0 ); buffer *buf = alloc_buffer(); assert_true( enqueue_message( queue, buf ) ); assert_int_equal( queue->length, 1 ); assert_true( delete_message_queue( queue ) ); }
/** * @brief send handlers definitions * @param conn the ::connection to send these definitions * @returns 0 on success, -1 on error. */ int send_handlers_list(conn_node *conn) { handler *h; message *m; struct hndl_list_info *handlers_info; struct hndl_info *handler_info; int ret; size_t array_size; ret=-1; array_size=0; for(h=(handler *) handlers.head; h; h=(handler *) h->next) { array_size += sizeof(struct hndl_info); array_size += strlen(h->name) +1; } m = create_message(get_sequence(&(conn->ctrl_seq), &(conn->control.mutex)), sizeof(struct hndl_list_info) + array_size, CTRL_ID); if(!m) { print( ERROR, "cannot create messages" ); goto exit; } handlers_info = (struct hndl_list_info *) m->data; handlers_info->hndl_code = HNDL_LIST; handler_info = handlers_info->list; for(h=(handler *) handlers.head; h; h=(handler *) h->next) { handler_info->id = h->id; handler_info->have_stdin = h->have_stdin; handler_info->have_stdout = h->have_stdout; strcpy(handler_info->name, h->name); handler_info = (struct hndl_info *) ( ((char *) handler_info) + sizeof(struct hndl_info) + strlen(h->name) + 1); } if(enqueue_message(&(conn->outcoming), m)) { print( ERROR, "cannot enqueue message" ); dump_message(m); free_message(m); } else { ret = 0; } exit: return ret; }
int send_to_secure_channel( struct switch_info *sw_info, buffer *buf ) { assert( sw_info != NULL ); assert( buf != NULL ); assert( buf->length > 0 ); if ( sw_info->send_queue == NULL ) { return -1; } return ( enqueue_message( sw_info->send_queue, buf ) == true ) ? 0 : -1; }
static INLINE void remote_context_bind_rasterizer_state(struct pipe_context *_pipe, void *state) { ALLOC_OUT_MESSAGE(bind_rast_state, message); message->base.opcode = REMREQ_BIND_RAST_STATE; message->pipe = PIPE_HANDLE(_pipe); message->rast_handle = RAST_HANDLE(state); enqueue_message(message); }
static INLINE void remote_context_destroy(struct pipe_context *_pipe) { ALLOC_OUT_MESSAGE(destroy_context, message); DBG("Destroying context %u\n", PIPE_HANDLE(_pipe)); message->base.opcode = REMREQ_DESTROY_CONTEXT; message->pipe = PIPE_HANDLE(_pipe); enqueue_message(message); FREE((struct remote_context*)_pipe); }
static INLINE void remote_context_delete_blend_state(struct pipe_context *_pipe, void *state) { DBG("Delete blend state %u\n", BLEND_HANDLE(state)); ALLOC_OUT_MESSAGE(delete_blend_state, message); message->base.opcode = REMREQ_DELETE_BLEND_STATE; message->pipe = PIPE_HANDLE(_pipe); message->blend_handle = BLEND_HANDLE(state); enqueue_message(message); }
static INLINE void remote_context_delete_rasterizer_state(struct pipe_context *_pipe, void *state) { DBG("Delete rasterizer state %u\n", RAST_HANDLE(state)); ALLOC_OUT_MESSAGE(delete_rast_state, message); message->base.opcode = REMREQ_DELETE_RAST_STATE; message->pipe = PIPE_HANDLE(_pipe); message->rast_handle = RAST_HANDLE(state); enqueue_message(message); }
static INLINE void remote_context_delete_sampler_state(struct pipe_context *_pipe, void *state) { DBG("Delete sampler state %u\n", SAMPLER_HANDLE(state)); ALLOC_OUT_MESSAGE(delete_sampler_state, message); message->base.opcode = REMREQ_DELETE_SAMPLER_STATE; message->pipe = PIPE_HANDLE(_pipe); message->sampler_handle = SAMPLER_HANDLE(state); enqueue_message(message); }
static INLINE void remote_context_delete_fs_state(struct pipe_context *_pipe, void *state) { DBG("Delete fragment shader %u\n", FS_HANDLE(state)); ALLOC_OUT_MESSAGE(delete_fs_state, message); message->base.opcode = REMREQ_DELETE_FS_STATE; message->pipe = PIPE_HANDLE(_pipe); message->fs_handle = FS_HANDLE(state); enqueue_message(message); }
static INLINE void remote_context_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, void *state) { DBG("Delete depth/stencil/alpha state %u\n", DSA_HANDLE(state)); ALLOC_OUT_MESSAGE(delete_dsa_state, message); message->base.opcode = REMREQ_DELETE_DSA_STATE; message->pipe = PIPE_HANDLE(_pipe); message->dsa_handle = DSA_HANDLE(state); enqueue_message(message); }