void channel_send(STREAM s, VCHANNEL * channel) { uint32 length, flags; uint32 thislength, remaining; uint8 *data; #ifdef WITH_SCARD scard_lock(SCARD_LOCK_CHANNEL); #endif /* first fragment sent in-place */ s_pop_layer(s, channel_hdr); length = s->end - s->p - 8; DEBUG_CHANNEL(("channel_send, length = %d\n", length)); thislength = MIN(length, CHANNEL_CHUNK_LENGTH); /* Note: In the original clipboard implementation, this number was 1592, not 1600. However, I don't remember the reason and 1600 seems to work so.. This applies only to *this* length, not the length of continuation or ending packets. */ remaining = length - thislength; flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST; if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) flags |= CHANNEL_FLAG_SHOW_PROTOCOL; out_uint32_le(s, length); out_uint32_le(s, flags); data = s->end = s->p + thislength; DEBUG_CHANNEL(("Sending %d bytes with FLAG_FIRST\n", thislength)); sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); /* subsequent segments copied (otherwise would have to generate headers backwards) */ while (remaining > 0) { thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH); remaining -= thislength; flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0; if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) flags |= CHANNEL_FLAG_SHOW_PROTOCOL; DEBUG_CHANNEL(("Sending %d bytes with flags %d\n", thislength, flags)); s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8); out_uint32_le(s, length); out_uint32_le(s, flags); out_uint8p(s, data, thislength); s_mark_end(s); sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); data += thislength; } #ifdef WITH_SCARD scard_unlock(SCARD_LOCK_CHANNEL); #endif }
int vchan_send(rdpChannels * chan, int mcs_id, char * data, int total_length) { STREAM s; int sec_flags; int length; int sent; int chan_flags; int chan_index; rdpSet * settings; struct rdp_chan * channel; settings = chan->mcs->sec->rdp->settings; chan_index = (mcs_id - MCS_GLOBAL_CHANNEL) - 1; if ((chan_index < 0) || (chan_index >= settings->num_channels)) { ui_error(chan->mcs->sec->rdp->inst, "error\n"); return 0; } channel = &(settings->channels[chan_index]); chan_flags = CHANNEL_FLAG_FIRST; sent = 0; sec_flags = settings->encryption ? SEC_ENCRYPT : 0; while (sent < total_length) { length = MIN(CHANNEL_CHUNK_LENGTH, total_length); length = MIN(total_length - sent, length); if ((sent + length) >= total_length) { chan_flags |= CHANNEL_FLAG_LAST; } if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) { chan_flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } s = sec_init(chan->mcs->sec, sec_flags, length + 8); out_uint32_le(s, total_length); out_uint32_le(s, chan_flags); out_uint8p(s, data + sent, length); s_mark_end(s); sec_send_to_channel(chan->mcs->sec, s, sec_flags, mcs_id); sent += length; chan_flags = 0; } return sent; }