/[rdesktop]/sourceforge.net/trunk/rdesktop/channels.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/channels.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 400 by forsberg, Fri Jun 6 10:10:19 2003 UTC revision 1475 by jsorg71, Fri Jul 11 03:51:23 2008 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Channel register     Protocol services - Virtual channels
4     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5       Copyright (C) Matthew Chapman 2003-2008
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 21 
21    
22  #include "rdesktop.h"  #include "rdesktop.h"
23    
24  static uint16 num_channels;  #define MAX_CHANNELS                    6
25  static rdp5_channel *channels[MAX_RDP5_CHANNELS];  #define CHANNEL_CHUNK_LENGTH            1600
26    #define CHANNEL_FLAG_FIRST              0x01
27    #define CHANNEL_FLAG_LAST               0x02
28    #define CHANNEL_FLAG_SHOW_PROTOCOL      0x10
29    
30    extern RD_BOOL g_use_rdp5;
31    extern RD_BOOL g_encryption;
32    
33    VCHANNEL g_channels[MAX_CHANNELS];
34    unsigned int g_num_channels;
35    
36    /* FIXME: We should use the information in TAG_SRV_CHANNELS to map RDP5
37       channels to MCS channels.
38    
39       The format of TAG_SRV_CHANNELS seems to be
40    
41       global_channel_no (uint16le)
42       number_of_other_channels (uint16le)
43       ..followed by uint16les for the other channels.
44    */
45    
46  uint16  VCHANNEL *
47  get_num_channels(void)  channel_register(char *name, uint32 flags, void (*callback) (STREAM))
48  {  {
49          return num_channels;          VCHANNEL *channel;
50    
51            if (!g_use_rdp5)
52                    return NULL;
53    
54            if (g_num_channels >= MAX_CHANNELS)
55            {
56                    error("Channel table full, increase MAX_CHANNELS\n");
57                    return NULL;
58            }
59    
60            channel = &g_channels[g_num_channels];
61            channel->mcs_id = MCS_GLOBAL_CHANNEL + 1 + g_num_channels;
62            strncpy(channel->name, name, 8);
63            channel->flags = flags;
64            channel->process = callback;
65            g_num_channels++;
66            return channel;
67    }
68    
69    STREAM
70    channel_init(VCHANNEL * channel, uint32 length)
71    {
72            STREAM s;
73    
74            s = sec_init(g_encryption ? SEC_ENCRYPT : 0, length + 8);
75            s_push_layer(s, channel_hdr, 8);
76            return s;
77  }  }
78    
79  void  void
80  register_channel(char *name, uint32 flags, void (*callback) (STREAM, uint16))  channel_send(STREAM s, VCHANNEL * channel)
81  {  {
82          if (num_channels > MAX_RDP5_CHANNELS)          uint32 length, flags;
83            uint32 thislength, remaining;
84            uint8 *data;
85    
86    #ifdef WITH_SCARD
87            scard_lock(SCARD_LOCK_CHANNEL);
88    #endif
89    
90            /* first fragment sent in-place */
91            s_pop_layer(s, channel_hdr);
92            length = s->end - s->p - 8;
93    
94            DEBUG_CHANNEL(("channel_send, length = %d\n", length));
95    
96            thislength = MIN(length, CHANNEL_CHUNK_LENGTH);
97    /* Note: In the original clipboard implementation, this number was
98       1592, not 1600. However, I don't remember the reason and 1600 seems
99       to work so.. This applies only to *this* length, not the length of
100       continuation or ending packets. */
101            remaining = length - thislength;
102            flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST;
103            if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
104                    flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
105    
106            out_uint32_le(s, length);
107            out_uint32_le(s, flags);
108            data = s->end = s->p + thislength;
109            DEBUG_CHANNEL(("Sending %d bytes with FLAG_FIRST\n", thislength));
110            sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
111    
112            /* subsequent segments copied (otherwise would have to generate headers backwards) */
113            while (remaining > 0)
114          {          {
115                  error("Maximum number of RDP5 channels reached. Redefine MAX_RDP5_CHANNELS in constants.h and recompile!\n!");                  thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH);
116                    remaining -= thislength;
117                    flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0;
118                    if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
119                            flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
120    
121                    DEBUG_CHANNEL(("Sending %d bytes with flags %d\n", thislength, flags));
122    
123                    s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8);
124                    out_uint32_le(s, length);
125                    out_uint32_le(s, flags);
126                    out_uint8p(s, data, thislength);
127                    s_mark_end(s);
128                    sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
129    
130                    data += thislength;
131          }          }
132          num_channels++;  
133          channels[num_channels - 1] = xrealloc(channels[num_channels - 1],  #ifdef WITH_SCARD
134                                                sizeof(rdp5_channel) * num_channels);          scard_unlock(SCARD_LOCK_CHANNEL);
135          channels[num_channels - 1]->channelno = MCS_GLOBAL_CHANNEL + num_channels;  #endif
         strcpy(channels[num_channels - 1]->name, name);  
         channels[num_channels - 1]->channelflags = flags;  
         channels[num_channels - 1]->channelcallback = callback;  
136  }  }
137    
138  rdp5_channel *  void
139  find_channel_by_channelno(uint16 channelno)  channel_process(STREAM s, uint16 mcs_channel)
140  {  {
141          if (channelno > MCS_GLOBAL_CHANNEL + num_channels)          uint32 length, flags;
142          {          uint32 thislength;
143                  warning("Channel %d not defined. Highest channel defined is %d\n",          VCHANNEL *channel = NULL;
144                          channelno, MCS_GLOBAL_CHANNEL + num_channels);          unsigned int i;
145                  return NULL;          STREAM in;
146          }  
147          else          for (i = 0; i < g_num_channels; i++)
148          {          {
149                  return channels[channelno - MCS_GLOBAL_CHANNEL - 1];                  channel = &g_channels[i];
150                    if (channel->mcs_id == mcs_channel)
151                            break;
152          }          }
 }  
153    
154  rdp5_channel *          if (i >= g_num_channels)
155  find_channel_by_num(uint16 num)                  return;
156  {  
157          if (num > num_channels)          in_uint32_le(s, length);
158            in_uint32_le(s, flags);
159            if ((flags & CHANNEL_FLAG_FIRST) && (flags & CHANNEL_FLAG_LAST))
160          {          {
161                  error("There are only %d channels defined, channel %d doesn't exist\n",                  /* single fragment - pass straight up */
162                        num_channels, num);                  channel->process(s);
163          }          }
164          else          else
165          {          {
166                  return channels[num];                  /* add fragment to defragmentation buffer */
167                    in = &channel->in;
168                    if (flags & CHANNEL_FLAG_FIRST)
169                    {
170                            if (length > in->size)
171                            {
172                                    in->data = (uint8 *) xrealloc(in->data, length);
173                                    in->size = length;
174                            }
175                            in->p = in->data;
176                    }
177    
178                    thislength = MIN(s->end - s->p, in->data + in->size - in->p);
179                    memcpy(in->p, s->p, thislength);
180                    in->p += thislength;
181    
182                    if (flags & CHANNEL_FLAG_LAST)
183                    {
184                            in->end = in->p;
185                            in->p = in->data;
186                            channel->process(in);
187                    }
188          }          }
         return NULL;            // Shut the compiler up  
 }  
   
   
   
 void  
 dummy_callback(STREAM s, uint16 channelno)  
 {  
         warning("Server is sending information on our dummy channel (%d). Why?\n", channelno);  
 }  
   
 void  
 channels_init(void)  
 {  
         DEBUG_RDP5(("channels_init\n"));  
         register_channel("dummych", 0xc0a0, dummy_callback);  
         register_channel("cliprdr", 0xc0a0, cliprdr_callback);  
189  }  }

Legend:
Removed from v.400  
changed lines
  Added in v.1475

  ViewVC Help
Powered by ViewVC 1.1.26