/* called by main thread add item to linked list and inform worker thread that there is data */ static void queue_data_and_signal_data_received(railCorePlugin * plugin) { struct data_in_item * item; item = (struct data_in_item *) malloc(sizeof(struct data_in_item)); item->data = plugin->data_in; item->data_size = plugin->data_in_size; item->next = NULL; plugin->data_in = NULL; plugin->data_in_size = 0; pthread_mutex_lock(plugin->in_mutex); if (plugin->in_list_tail == NULL) { plugin->in_list_head = item; plugin->in_list_tail = item; } else { plugin->in_list_tail->next = item; plugin->in_list_tail = item; } pthread_mutex_unlock(plugin->in_mutex); wait_obj_set(plugin->data_in_event); }
/* called by main thread add item to linked list and inform worker thread that there is data */ static void signal_data_in(rdpsndPlugin * plugin) { struct data_in_item * item; item = (struct data_in_item *) malloc(sizeof(struct data_in_item)); item->next = 0; item->data = plugin->data_in; plugin->data_in = 0; item->data_size = plugin->data_in_size; plugin->data_in_size = 0; pthread_mutex_lock(plugin->in_mutex); if (plugin->in_list_tail == 0) { plugin->in_list_head = item; plugin->in_list_tail = item; } else { plugin->in_list_tail->next = item; plugin->in_list_tail = item; } pthread_mutex_unlock(plugin->in_mutex); wait_obj_set(plugin->data_in_event); }
static void __serial_check_fds(SERIAL_DEVICE* serial) { IRP* irp; IRP* prev; SERIAL_TTY* tty; uint32 result = 0; memset(&serial->tv, 0, sizeof(struct timeval)); tty = serial->tty; /* scan every pending */ irp = list_peek(serial->pending_irps); while (irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_READ: if (FD_ISSET(tty->fd, &serial->read_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_read(serial, irp); } break; case IRP_MJ_WRITE: if (FD_ISSET(tty->fd, &serial->write_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_write(serial, irp); } break; case IRP_MJ_DEVICE_CONTROL: if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; stream_write_uint32(irp->output, result); irp->Complete(irp); } break; default: DEBUG_SVC("no request found"); break; } prev = irp; irp = (IRP*)list_next(serial->pending_irps, irp); if (prev->IoStatus == STATUS_SUCCESS) { list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); } } }
/* can be called from any thread */ static uint32 FREERDP_CC MyVirtualChannelWrite(uint32 openHandle, void* pData, uint32 dataLength, void* pUserData) { rdpChannels* chan_man; struct channel_data* lchan; struct sync_data* item; int index; chan_man = freerdp_channels_find_by_open_handle(openHandle, &index); if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad chanhan"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (!chan_man->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } if (pData == 0) { DEBUG_CHANNELS("error bad pData"); return CHANNEL_RC_NULL_DATA; } if (dataLength == 0) { DEBUG_CHANNELS("error bad dataLength"); return CHANNEL_RC_ZERO_LENGTH; } lchan = chan_man->chans + index; if (lchan->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } freerdp_mutex_lock(chan_man->sync_data_mutex); /* lock channels->sync* vars */ if (!chan_man->is_connected) { freerdp_mutex_unlock(chan_man->sync_data_mutex); DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } item = xnew(struct sync_data); item->data = pData; item->data_length = dataLength; item->user_data = pUserData; item->index = index; list_enqueue(chan_man->sync_data_list, item); freerdp_mutex_unlock(chan_man->sync_data_mutex); /* set the event */ wait_obj_set(chan_man->signal); return CHANNEL_RC_OK; }
int transport_write(rdpTransport* transport, STREAM* s) { int status = -1; int length; length = stream_get_length(s); stream_set_pos(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { printf("Local > Remote\n"); freerdp_hexdump(s->data, length); } #endif while (length > 0) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->tls, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->tcp, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TSG) status = tsg_write(transport->tsg, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* blocking while sending */ freerdp_usleep(transport->usleep_interval); /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) { /* and in case we do have buffered some data, we set the event so next loop will get it */ if (transport_read_nonblocking(transport) > 0) wait_obj_set(transport->recv_event); } } length -= status; stream_seek(s, status); } if (status < 0) { /* A write error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; } return status; }
static void InitEventProcessTerminated(void * pInitHandle) { rdpsndPlugin * plugin; int index; struct data_in_item * in_item; struct data_out_item * out_item; plugin = (rdpsndPlugin *) chan_plugin_find_by_init_handle(pInitHandle); if (plugin == NULL) { LLOGLN(0, ("InitEventProcessConnected: error no match")); return; } wait_obj_set(plugin->term_event); index = 0; while ((plugin->thread_status > 0) && (index < 100)) { index++; usleep(250 * 1000); } wait_obj_free(plugin->term_event); wait_obj_free(plugin->data_in_event); pthread_mutex_destroy(plugin->in_mutex); free(plugin->in_mutex); /* free the un-processed in/out queue */ while (plugin->in_list_head != 0) { in_item = plugin->in_list_head; plugin->in_list_head = in_item->next; free(in_item->data); free(in_item); } while (plugin->out_list_head != 0) { out_item = plugin->out_list_head; plugin->out_list_head = out_item->next; free(out_item->data); free(out_item); } if (plugin->device_plugin) { plugin->device_plugin->free(plugin->device_plugin); free(plugin->device_plugin); plugin->device_plugin = NULL; } chan_plugin_uninit((rdpChanPlugin *) plugin); free(plugin); }
void freerdp_thread_stop(freerdp_thread* thread) { int i = 0; wait_obj_set(thread->signals[0]); while (thread->status > 0 && i < 1000) { i++; freerdp_usleep(100000); } }
static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item) { WTSVirtualChannelManager* vcm; vcm = channel->vcm; item->channel_id = channel->channel_id; WaitForSingleObject(vcm->mutex, INFINITE); list_enqueue(vcm->send_queue, item); ReleaseMutex(vcm->mutex); wait_obj_set(vcm->send_event); }
static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 abort_io, uint32 io_status) { IRP* irp = NULL; uint32 major; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; switch (abort_io) { case SERIAL_ABORT_IO_NONE: major = 0; break; case SERIAL_ABORT_IO_READ: major = IRP_MJ_READ; break; case SERIAL_ABORT_IO_WRITE: major = IRP_MJ_WRITE; break; default: DEBUG_SVC("unexpected abort_io code %d", abort_io); return; } irp = (IRP*)list_peek(serial->pending_irps); while (irp) { if (irp->FileId != file_id || irp->MajorFunction != major) { irp = (IRP*)list_next(serial->pending_irps, irp); continue; } /* Process a SINGLE FileId and MajorFunction */ list_remove(serial->pending_irps, irp); irp->IoStatus = io_status; stream_write_uint32(irp->output, 0); irp->Complete(irp); wait_obj_set(serial->in_event); break; } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); }
static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item) { WTSVirtualChannelManager* vcm; vcm = channel->vcm; item->channel_id = channel->channel_id; freerdp_mutex_lock(vcm->mutex); list_enqueue(vcm->send_queue, item); freerdp_mutex_unlock(vcm->mutex); wait_obj_set(vcm->send_event); }
//------------------------------------------------------------------------------ static void InitEventProcessTerminated(void * pInitHandle) { railCorePlugin * plugin; int index; struct data_in_item * in_item; LLOGLN(10, ("rail_core_plugin:InitEventProcessTerminated: pInitHandle=0x%p", pInitHandle)); plugin = (railCorePlugin *) chan_plugin_find_by_init_handle(pInitHandle); if (plugin == NULL) { LLOGLN(0, ("rail_core_plugin:InitEventProcessTerminated: error no match")); return; } wait_obj_set(plugin->term_event); index = 0; while ((plugin->thread_status > 0) && (index < 100)) { index++; usleep(250 * 1000); } wait_obj_free(plugin->term_event); wait_obj_free(plugin->data_in_event); pthread_mutex_destroy(plugin->in_mutex); free(plugin->in_mutex); /* free the un-processed in/out queue */ while (plugin->in_list_head != NULL) { in_item = plugin->in_list_head; plugin->in_list_head = in_item->next; free(in_item->data); free(in_item); } if (plugin->data_in != NULL) { free(plugin->data_in); } chan_plugin_uninit((rdpChanPlugin *) plugin); rail_on_channel_terminated(plugin->session); free(plugin); }
static void wts_queue_receive_data(rdpPeerChannel* channel, const uint8* buffer, uint32 length) { wts_data_item* item; item = xnew(wts_data_item); item->length = length; item->buffer = xmalloc(length); memcpy(item->buffer, buffer, length); freerdp_mutex_lock(channel->mutex); list_enqueue(channel->receive_queue, item); freerdp_mutex_unlock(channel->mutex); wait_obj_set(channel->receive_event); }
static void wts_queue_receive_data(rdpPeerChannel* channel, const uint8* buffer, uint32 length) { wts_data_item* item; item = xnew(wts_data_item); item->length = length; item->buffer = xmalloc(length); memcpy(item->buffer, buffer, length); WaitForSingleObject(channel->mutex, INFINITE); list_enqueue(channel->receive_queue, item); ReleaseMutex(channel->mutex); wait_obj_set(channel->receive_event); }
static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp) { uint32 timeout = 0; uint32 itv_timeout = 0; SERIAL_TTY* tty; tty = serial->tty; switch (irp->MajorFunction) { case IRP_MJ_WRITE: DEBUG_SVC("handling IRP_MJ_WRITE"); break; case IRP_MJ_READ: DEBUG_SVC("handling IRP_MJ_READ"); serial_get_timeouts(serial, irp, &timeout, &itv_timeout); /* Check if io request timeout is smaller than current (but not 0). */ if (timeout && (serial->select_timeout == 0 || timeout < serial->select_timeout)) { serial->select_timeout = timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } if (itv_timeout && (serial->select_timeout == 0 || itv_timeout < serial->select_timeout)) { serial->select_timeout = itv_timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u", serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id); break; default: DEBUG_SVC("no need to handle %d", irp->MajorFunction); return; } irp->IoStatus = STATUS_PENDING; list_enqueue(serial->pending_irps, irp); wait_obj_set(serial->in_event); }
static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, STREAM* s, uint32 length) { uint32 CreationStatus; if (length < 4) return; stream_read_uint32(s, CreationStatus); if ((sint32)CreationStatus < 0) { DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (sint32)CreationStatus); channel->dvc_open_state = DVC_OPEN_STATE_FAILED; } else { DEBUG_DVC("ChannelId %d creation succeeded", channel->channel_id); channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED; } wait_obj_set(channel->receive_event); }
boolean WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ uint8* Buffer, /* __in */ uint32 Length, /* __out */ uint32* pBytesWritten) { uint32 written = 0; wts_data_item* item; boolean result = false; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; WTSVirtualChannelManager* vcm ; if (channel == NULL) return false; vcm = channel->vcm ; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = xnew(wts_data_item); item->channel_id = channel->channel_id; item->buffer = xmalloc(Length); item->length = Length; memcpy(item->buffer, Buffer, Length); freerdp_mutex_lock(vcm->mutex); list_enqueue(vcm->send_queue, item); freerdp_mutex_unlock(vcm->mutex); wait_obj_set(vcm->send_event); written = Length; result = true; } else { /* TODO: Send to DVC channel */ } if (pBytesWritten != NULL) *pBytesWritten = written; return result; }
static void serial_check_for_events(SERIAL_DEVICE* serial) { IRP* irp = NULL; IRP* prev; uint32 result = 0; SERIAL_TTY* tty; tty = serial->tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); irp = (IRP*)list_peek(serial->pending_irps); while (irp) { prev = NULL; if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) { if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; stream_write_uint32(irp->output, result); irp->Complete(irp); prev = irp; irp = (IRP*)list_next(serial->pending_irps, irp); list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); } } if (!prev) irp = (IRP*)list_next(serial->pending_irps, irp); } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); }
static uint32 FREERDP_CC MyVirtualChannelEventPush(uint32 openHandle, RDP_EVENT* event) { rdpChannels* chan_man; struct channel_data* lchan; int index; chan_man = freerdp_channels_find_by_open_handle(openHandle, &index); if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad chanhan"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (!chan_man->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } if (event == NULL) { DEBUG_CHANNELS("error bad event"); return CHANNEL_RC_NULL_DATA; } lchan = chan_man->chans + index; if (lchan->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } freerdp_sem_wait(chan_man->event_sem); /* lock channels->event */ if (!chan_man->is_connected) { freerdp_sem_signal(chan_man->event_sem); DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } chan_man->event = event; /* set the event */ wait_obj_set(chan_man->signal); return CHANNEL_RC_OK; }
void test_wait_obj(void) { struct wait_obj* wo; int set; wo = wait_obj_new(); set = wait_obj_is_set(wo); CU_ASSERT(set == 0); wait_obj_set(wo); set = wait_obj_is_set(wo); CU_ASSERT(set == 1); wait_obj_clear(wo); set = wait_obj_is_set(wo); CU_ASSERT(set == 0); wait_obj_select(&wo, 1, 1000); wait_obj_free(wo); }
static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8* data, int size, int flags, int total_size) { wts_data_item* item; if (flags & CHANNEL_FLAG_FIRST) { stream_set_pos(channel->receive_data, 0); } stream_check_size(channel->receive_data, size); stream_write(channel->receive_data, data, size); if (flags & CHANNEL_FLAG_LAST) { if (stream_get_length(channel->receive_data) != total_size) { printf("WTSProcessChannelData: read error\n"); } if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC) { /* TODO: Receive DVC channel data */ } else { item = xnew(wts_data_item); item->length = stream_get_length(channel->receive_data); item->buffer = xmalloc(item->length); memcpy(item->buffer, stream_get_head(channel->receive_data), item->length); freerdp_mutex_lock(channel->mutex); list_enqueue(channel->receive_queue, item); freerdp_mutex_unlock(channel->mutex); wait_obj_set(channel->receive_event); } stream_set_pos(channel->receive_data, 0); } }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; uint16 length; STREAM* received; rdpTransport* transport = *ptransport; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->recv_buffer); if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == false) status = -1; stream_free(received); if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; if (transport->process_single_pdu) { /* one at a time but set event if data buffered * so the main loop will call freerdp_check_fds asap */ if (stream_get_pos(transport->recv_buffer) > 0) wait_obj_set(transport->recv_event); break; } } return 0; }