Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenchannels.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*- 00002 rdesktop: A Remote Desktop Protocol client. 00003 Protocol services - Virtual channels 00004 Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003 00005 Copyright (C) Matthew Chapman 2003-2005 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License along 00018 with this program; if not, write to the Free Software Foundation, Inc., 00019 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 */ 00021 00022 #include <precomp.h> 00023 00024 #define MAX_CHANNELS 6 00025 #define CHANNEL_CHUNK_LENGTH 1600 00026 #define CHANNEL_FLAG_FIRST 0x01 00027 #define CHANNEL_FLAG_LAST 0x02 00028 #define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 00029 00030 extern BOOL g_use_rdp5; 00031 extern BOOL g_encryption; 00032 00033 VCHANNEL g_channels[MAX_CHANNELS]; 00034 unsigned int g_num_channels; 00035 00036 /* FIXME: We should use the information in TAG_SRV_CHANNELS to map RDP5 00037 channels to MCS channels. 00038 00039 The format of TAG_SRV_CHANNELS seems to be 00040 00041 global_channel_no (uint16le) 00042 number_of_other_channels (uint16le) 00043 ..followed by uint16les for the other channels. 00044 */ 00045 00046 VCHANNEL * 00047 channel_register(char *name, uint32 flags, void (*callback) (STREAM)) 00048 { 00049 VCHANNEL *channel; 00050 00051 if (!g_use_rdp5) 00052 return NULL; 00053 00054 if (g_num_channels >= MAX_CHANNELS) 00055 { 00056 error("Channel table full, increase MAX_CHANNELS\n"); 00057 return NULL; 00058 } 00059 00060 channel = &g_channels[g_num_channels]; 00061 channel->mcs_id = MCS_GLOBAL_CHANNEL + 1 + g_num_channels; 00062 strncpy(channel->name, name, 8); 00063 channel->flags = flags; 00064 channel->process = callback; 00065 g_num_channels++; 00066 return channel; 00067 } 00068 00069 STREAM 00070 channel_init(VCHANNEL * channel, uint32 length) 00071 { 00072 STREAM s; 00073 00074 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, length + 8); 00075 s_push_layer(s, channel_hdr, 8); 00076 return s; 00077 } 00078 00079 void 00080 channel_send(STREAM s, VCHANNEL * channel) 00081 { 00082 uint32 length, flags; 00083 uint32 thislength, remaining; 00084 uint8 *data; 00085 00086 /* first fragment sent in-place */ 00087 s_pop_layer(s, channel_hdr); 00088 length = s->end - s->p - 8; 00089 00090 DEBUG_CHANNEL(("channel_send, length = %d\n", length)); 00091 00092 thislength = MIN(length, CHANNEL_CHUNK_LENGTH); 00093 /* Note: In the original clipboard implementation, this number was 00094 1592, not 1600. However, I don't remember the reason and 1600 seems 00095 to work so.. This applies only to *this* length, not the length of 00096 continuation or ending packets. */ 00097 remaining = length - thislength; 00098 flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST; 00099 if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) 00100 flags |= CHANNEL_FLAG_SHOW_PROTOCOL; 00101 00102 out_uint32_le(s, length); 00103 out_uint32_le(s, flags); 00104 data = s->end = s->p + thislength; 00105 DEBUG_CHANNEL(("Sending %d bytes with FLAG_FIRST\n", thislength)); 00106 sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); 00107 00108 /* subsequent segments copied (otherwise would have to generate headers backwards) */ 00109 while (remaining > 0) 00110 { 00111 thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH); 00112 remaining -= thislength; 00113 flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0; 00114 if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) 00115 flags |= CHANNEL_FLAG_SHOW_PROTOCOL; 00116 00117 DEBUG_CHANNEL(("Sending %d bytes with flags %d\n", thislength, flags)); 00118 00119 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8); 00120 out_uint32_le(s, length); 00121 out_uint32_le(s, flags); 00122 out_uint8p(s, data, thislength); 00123 s_mark_end(s); 00124 sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); 00125 00126 data += thislength; 00127 } 00128 } 00129 00130 void 00131 channel_process(STREAM s, uint16 mcs_channel) 00132 { 00133 uint32 length, flags; 00134 uint32 thislength; 00135 VCHANNEL *channel = NULL; 00136 unsigned int i; 00137 STREAM in; 00138 00139 for (i = 0; i < g_num_channels; i++) 00140 { 00141 channel = &g_channels[i]; 00142 if (channel->mcs_id == mcs_channel) 00143 break; 00144 } 00145 00146 if (i >= g_num_channels) 00147 return; 00148 00149 in_uint32_le(s, length); 00150 in_uint32_le(s, flags); 00151 if ((flags & CHANNEL_FLAG_FIRST) && (flags & CHANNEL_FLAG_LAST)) 00152 { 00153 /* single fragment - pass straight up */ 00154 channel->process(s); 00155 } 00156 else 00157 { 00158 /* add fragment to defragmentation buffer */ 00159 in = &channel->in; 00160 if (flags & CHANNEL_FLAG_FIRST) 00161 { 00162 if (length > in->size) 00163 { 00164 in->data = (uint8 *) xrealloc(in->data, length); 00165 in->size = length; 00166 } 00167 in->p = in->data; 00168 } 00169 00170 thislength = MIN(s->end - s->p, in->data + in->size - in->p); 00171 memcpy(in->p, s->p, thislength); 00172 in->p += thislength; 00173 00174 if (flags & CHANNEL_FLAG_LAST) 00175 { 00176 in->end = in->p; 00177 in->p = in->data; 00178 channel->process(in); 00179 } 00180 } 00181 } Generated on Mon May 28 2012 04:17:07 for ReactOS by
1.7.6.1
|