ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

channels.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.