struct chansrv_drdynvc
{ int chan_id; int status; /* see CHANSRV_DRDYNVC_STATUS_* */ int flags; int pad0; int (*open_response)(int chan_id, int creation_status); int (*close_response)(int chan_id); int (*data_first)(int chan_id, char *data, int bytes, int total_bytes); int (*data)(int chan_id, char *data, int bytes); struct trans *xrdp_api_trans;
};
staticstruct chansrv_drdynvc g_drdynvcs[256];
/* data in struct trans::callback_data */ struct xrdp_api_data
{ int chan_flags; int chan_id;
};
// Session state passed to xrdpapi // Whenever a single member of this struct changes, the whole // block is sent to xrdpapi. This simplifies the interface, but // complicates xrdpapi somewhat staticstruct xrdp_chan_session_state g_session_state;
/*****************************************************************************/ int
g_is_term(void)
{ return g_is_wait_obj_set(g_term_event);
}
/*****************************************************************************/ /* send data to a static virtual channel sizecanbe>MAX_CHANNEL_FRAG_BYTES,inwhichcase,>1message
will be sent*/ /* returns error */ int
send_channel_data(int chan_id, constchar *data, int size)
{ int sending_bytes; int chan_flags; int error; int total_size; struct stream *s;
if ((chan_id < 0) || (chan_id > 31) ||
(data == NULL) ||
(size < 1) || (size > MAX_CHANNEL_BYTES))
{ /* bad param */ return1;
}
total_size = size;
chan_flags = 1; /* first */ while (size > 0)
{
sending_bytes = MIN(MAX_CHANNEL_FRAG_BYTES, size); if (sending_bytes >= size)
{
chan_flags |= 2; /* last */
}
s = trans_get_out_s(g_con_trans, 26 + sending_bytes); if (s == NULL)
{ return2;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 26 + sending_bytes);
out_uint32_le(s, 8); /* msg id */
out_uint32_le(s, 18 + sending_bytes);
out_uint16_le(s, chan_id);
out_uint16_le(s, chan_flags);
out_uint16_le(s, sending_bytes);
out_uint32_le(s, total_size);
out_uint8a(s, data, sending_bytes);
s_mark_end(s);
size -= sending_bytes;
data += sending_bytes;
error = trans_write_copy(g_con_trans); if (error != 0)
{ return3;
}
chan_flags = 0;
} return0;
}
/*****************************************************************************/ /* returns error */ int
send_rail_drawing_orders(char *data, int size)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "chansrv::send_rail_drawing_orders: size %d", size);
struct stream *s; int error;
s = trans_get_out_s(g_con_trans, 8192); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 8 + 8 + size); /* size */
out_uint32_le(s, 10); /* msg id */
out_uint32_le(s, 8 + size); /* size */
out_uint8a(s, data, size);
s_mark_end(s);
error = trans_force_write(g_con_trans); if (error != 0)
{ return1;
} return0;
}
if (g_cliprdr_index >= 0)
{
clipboard_init();
xfuse_init();
}
if (g_rdpsnd_index >= 0)
{
sound_init();
}
if (g_rdpdr_index >= 0)
{
devredir_init();
xfuse_init();
}
if (g_rail_index >= 0)
{
rail_init();
}
audin_init();
return rv;
}
/*****************************************************************************/ /* returns error */ staticint
process_message_channel_data(struct stream *s)
{ int chan_id; int chan_flags; int rv; int length; int total_length; int index; int found; struct stream *ls; struct trans *ltran; struct xrdp_api_data *api_data;
/*****************************************************************************/ /* open call from chansrv */ int
chansrv_drdynvc_open(constchar *name, int flags, struct chansrv_drdynvc_procs *procs, int *chan_id)
{ struct stream *s; int name_bytes; int lchan_id; int error;
/*****************************************************************************/ /* close call from chansrv */ int
chansrv_drdynvc_close(int chan_id)
{ struct stream *s; int error;
s = trans_get_out_s(g_con_trans, 8192); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 20);
out_uint32_le(s, 14); /* msg id */
out_uint32_le(s, 12);
out_uint32_le(s, chan_id);
s_mark_end(s);
error = trans_write_copy(g_con_trans);
g_drdynvcs[chan_id].status = CHANSRV_DRDYNVC_STATUS_CLOSE_SENT; return error;
}
/*****************************************************************************/ int
chansrv_drdynvc_data_first(int chan_id, constchar *data, int data_bytes, int total_data_bytes)
{ struct stream *s; int error;
/*****************************************************************************/ int
chansrv_drdynvc_data(int chan_id, constchar *data, int data_bytes)
{ struct stream *s; int error;
// LOG_DEVEL(LOG_LEVEL_DEBUG, "chansrv_drdynvc_data: data_bytes %d", data_bytes);
s = trans_get_out_s(g_con_trans, 8192); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 24 + data_bytes);
out_uint32_le(s, 18); /* msg id */
out_uint32_le(s, 16 + data_bytes);
out_uint32_le(s, chan_id);
out_uint32_le(s, data_bytes);
out_uint8a(s, data, data_bytes);
s_mark_end(s);
error = trans_write_copy(g_con_trans); return error;
}
/*****************************************************************************/ int
chansrv_drdynvc_send_data(int chan_id, constchar *data, int data_bytes)
{ int this_send_bytes;
// LOG_DEVEL(LOG_LEVEL_DEBUG, "chansrv_drdynvc_send_data: data_bytes %d", data_bytes); if (data_bytes > 1590)
{ if (chansrv_drdynvc_data_first(chan_id, data, 1590, data_bytes) != 0)
{ return1;
}
data_bytes -= 1590;
data += 1590;
} while (data_bytes > 0)
{
this_send_bytes = MIN(1590, data_bytes); if (chansrv_drdynvc_data(chan_id, data, this_send_bytes) != 0)
{ return1;
}
data_bytes -= this_send_bytes;
data += this_send_bytes;
} return0;
}
/*****************************************************************************/ /* returns error */ staticint
process_message(void)
{ struct stream *s = (struct stream *)NULL; int size = 0; int id = 0; int rv = 0; char *next_msg = (char *)NULL;
/* Send the status back to the caller */ struct stream *out_s = trans_get_out_s(trans, 8192); if (out_s == NULL)
{ return1;
}
out_uint32_pe(out_s, rv);
s_mark_end(out_s); if (trans_write_copy(trans) != 0)
{ return1;
}
/* *calledwhenVirtualChannelOpen()isinvokedinxrdpapi.c,andlater, *whenthechanneliswrittento *
******************************************************************************/ int
my_api_trans_data_in(struct trans *trans)
{ struct stream *s; struct xrdp_api_data *ad; int rv; int bytes;
//LOG_DEVEL(LOG_LEVEL_DEBUG, "my_api_trans_data_in: extra_flags %d", trans->extra_flags);
rv = 0;
ad = (struct xrdp_api_data *) (trans->callback_data);
s = trans_get_in_s(trans); if (trans->extra_flags == 0)
{
trans->header_size = XRDPAPI_CONNECT_PDU_LEN; // Need more data
trans->extra_flags = 1;
} elseif (trans->extra_flags == 1)
{ // We've got a complete connection request on the channel */
handle_xrdpapi_connection_request(trans);
init_stream(s, 0);
trans->extra_flags = 2; // Mark the connection phase as complete
trans->header_size = 0;
} else
{
bytes = g_sck_recv(trans->sck, s->data, s->size, 0); if (bytes < 1)
{ //LOG_DEVEL(LOG_LEVEL_DEBUG, "my_api_trans_data_in: disconnect"); return1;
} if (ad->chan_flags == 0)
{ if (ad->chan_id == CHAN_ID_XRDP_SESSION_INFO)
{ // Ignore data sent to this channel
rv = 0;
} else
{ /* SVC */
rv = send_channel_data(ad->chan_id, s->data, bytes);
}
} else
{ /* DVS */ //LOG_DEVEL(LOG_LEVEL_DEBUG, "my_api_trans_data_in: s->size %d bytes %d", s->size, bytes);
rv = chansrv_drdynvc_send_data(ad->chan_id, s->data, bytes);
}
init_stream(s, 0);
} return rv;
}
/*****************************************************************************/ int
my_trans_conn_in(struct trans *trans, struct trans *new_trans)
{ if (trans == 0)
{ return1;
}
if (trans != g_lis_trans)
{ return1;
}
if (g_con_trans != 0) /* if already set, error */
{ return1;
}
/* Tell any xrdpapi listeners the session is connected. The
* previous state is guaranteed to be 'disconnected' at this point */
g_session_state.is_connected = 1;
xrdpapi_send_session_state_event_all();
/* *calledwhenWTSVirtualChannelOpenExisinvokedinxrdpapi.c *
******************************************************************************/ int
my_api_trans_conn_in(struct trans *trans, struct trans *new_trans)
{ struct xrdp_api_data *ad;
if (error != 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "setup_api_listen: trans_listen failed for port %s",
port); return1;
}
return0;
}
/*****************************************************************************/ staticint
api_con_trans_list_get_wait_objs_rw(intptr_t *robjs, int *rcount,
intptr_t *wobjs, int *wcount, int *timeout)
{ int api_con_index; struct trans *ltran;
/*****************************************************************************/ staticint
api_con_trans_list_check_wait_objs(void)
{ int api_con_index; int drdynvc_index; struct trans *ltran; struct xrdp_api_data *ad;
for (api_con_index = g_api_con_trans_list->count - 1;
api_con_index >= 0;
api_con_index--)
{
ltran = (struct trans *)
list_get_item(g_api_con_trans_list, api_con_index); if (ltran != NULL)
{ if (trans_check_wait_objs(ltran) != 0)
{ /* disconnect */
list_remove_item(g_api_con_trans_list, api_con_index);
ad = (struct xrdp_api_data *) (ltran->callback_data); if (ad->chan_flags != 0)
{
chansrv_drdynvc_close(ad->chan_id);
} for (drdynvc_index = 0;
drdynvc_index < (int) ARRAYSIZE(g_drdynvcs);
drdynvc_index++)
{ if (g_drdynvcs[drdynvc_index].xrdp_api_trans == ltran)
{
g_drdynvcs[drdynvc_index].xrdp_api_trans = NULL;
}
}
g_free(ad);
trans_delete(ltran);
}
}
} return0;
}
/*****************************************************************************/ staticint
api_con_trans_list_remove_all(void)
{ int api_con_index; struct trans *ltran;
/*****************************************************************************/
THREAD_RV THREAD_CC
channel_thread_loop(void *in_val)
{
tbus objs[32];
tbus wobjs[32]; int num_objs; int num_wobjs; int timeout; int error;
THREAD_RV rv;
if (g_lis_trans != 0)
{ if (trans_check_wait_objs(g_lis_trans) != 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "channel_thread_loop: " "trans_check_wait_objs error");
}
}
if (g_con_trans != 0)
{ if (trans_check_wait_objs(g_con_trans) != 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "channel_thread_loop: " "trans_check_wait_objs error resetting");
clipboard_deinit();
sound_deinit();
devredir_deinit();
rail_deinit(); /* delete g_con_trans */
trans_delete(g_con_trans);
g_con_trans = 0; /* Tell any xrdpapi listeners the session is *disconnected.Thepreviousstateisguaranteed
* to be 'connected' at this point */
g_session_state.is_connected = 0;
(void)xrdpapi_send_session_state_event_all(); /* create new listener */
error = setup_listen();
if (error != 0)
{ break;
}
}
}
if (g_api_lis_trans != 0)
{ if (trans_check_wait_objs(g_api_lis_trans) != 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "channel_thread_loop: trans_check_wait_objs failed");
}
} /* check the wait_objs in g_api_con_trans_list */
api_con_trans_list_check_wait_objs();
xcommon_check_wait_objs();
sound_check_wait_objs();
devredir_check_wait_objs();
xfuse_check_wait_objs();
timeout = -1;
num_objs = 0;
num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs_rw(g_lis_trans, objs, &num_objs,
wobjs, &num_wobjs, &timeout);
trans_get_wait_objs_rw(g_con_trans, objs, &num_objs,
wobjs, &num_wobjs, &timeout);
trans_get_wait_objs_rw(g_api_lis_trans, objs, &num_objs,
wobjs, &num_wobjs, &timeout); /* get the wait_objs from in g_api_con_trans_list */
api_con_trans_list_get_wait_objs_rw(objs, &num_objs,
wobjs, &num_wobjs,
&timeout);
xcommon_get_wait_objs(objs, &num_objs, &timeout);
sound_get_wait_objs(objs, &num_objs, &timeout);
devredir_get_wait_objs(objs, &num_objs, &timeout);
xfuse_get_wait_objs(objs, &num_objs, &timeout);
get_timeout(&timeout);
} /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */
}
trans_delete(g_lis_trans);
g_lis_trans = 0;
trans_delete(g_con_trans);
g_con_trans = 0; /* Tell any xrdpapi listeners the session is disconnected */ if (g_session_state.is_connected)
{
g_session_state.is_connected = 0;
(void)xrdpapi_send_session_state_event_all();
}
trans_delete(g_api_lis_trans);
g_api_lis_trans = 0;
api_con_trans_list_remove_all();
list_delete(g_api_con_trans_list);
LOG_DEVEL(LOG_LEVEL_INFO, "channel_thread_loop: thread stop");
g_set_wait_obj(g_thread_done_event); return rv;
}
/*****************************************************************************/ staticvoid
x_server_fatal_handler(void)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xserver_fatal_handler: entered......."); /* At this point the X server has gone away. Dont make any X calls. */
xfuse_deinit(); exit(0);
}
/*****************************************************************************/ int
main_cleanup(void)
{ if (g_term_event != 0)
{
g_delete_wait_obj(g_term_event);
} if (g_sigchld_event != 0)
{
g_delete_wait_obj(g_sigchld_event);
} if (g_thread_done_event != 0)
{
g_delete_wait_obj(g_thread_done_event);
} if (g_exec_event != 0)
{
g_delete_wait_obj(g_exec_event);
tc_mutex_delete(g_exec_mutex);
tc_sem_delete(g_exec_sem);
}
log_end();
config_free(g_cfg);
g_deinit(); /* os_calls */ return0;
}
/*****************************************************************************/ staticint
get_log_path(char *path, int bytes)
{ char *log_path; int rv;
display_text = g_getenv("DISPLAY"); if (display_text == NULL)
{
g_writeln("DISPLAY is not set");
main_cleanup(); return1;
}
g_display_num = g_get_display_num_from_display(display_text); if (g_display_num < 0)
{
g_writeln("Unable to get display from DISPLAY='%s'", display_text);
main_cleanup(); return1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.