/[rdesktop]/sourceforge.net/trunk/rdesktop/tcp.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/tcp.c

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

revision 33 by matty, Sat Sep 15 12:34:34 2001 UTC revision 1349 by jsorg71, Sat Dec 23 03:23:59 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - TCP layer     Protocol services - TCP layer
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21    #ifndef _WIN32
22  #include <unistd.h>             /* select read write close */  #include <unistd.h>             /* select read write close */
23  #include <sys/socket.h>         /* socket connect setsockopt */  #include <sys/socket.h>         /* socket connect setsockopt */
24  #include <sys/time.h>           /* timeval */  #include <sys/time.h>           /* timeval */
# Line 26  Line 27 
27  #include <netinet/tcp.h>        /* TCP_NODELAY */  #include <netinet/tcp.h>        /* TCP_NODELAY */
28  #include <arpa/inet.h>          /* inet_addr */  #include <arpa/inet.h>          /* inet_addr */
29  #include <errno.h>              /* errno */  #include <errno.h>              /* errno */
30    #endif
31    
32  #include "rdesktop.h"  #include "rdesktop.h"
33    
34  static int sock;  #ifdef _WIN32
35  static struct stream in;  #define socklen_t int
36  static struct stream out;  #define TCP_CLOSE(_sck) closesocket(_sck)
37    #define TCP_STRERROR "tcp error"
38    #define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
39    #else
40    #define TCP_CLOSE(_sck) close(_sck)
41    #define TCP_STRERROR strerror(errno)
42    #define TCP_BLOCKS (errno == EWOULDBLOCK)
43    #endif
44    
45    #ifndef INADDR_NONE
46    #define INADDR_NONE ((unsigned long) -1)
47    #endif
48    
49    static int g_sock;
50    static struct stream g_in;
51    #ifndef WITH_SCARD
52    static struct stream g_out;
53    #endif
54    int g_tcp_port_rdp = TCP_PORT_RDP;
55    
56    /* wait till socket is ready to write or timeout */
57    static BOOL
58    tcp_can_send(int sck, int millis)
59    {
60            fd_set wfds;
61            struct timeval time;
62            int sel_count;
63    
64            time.tv_sec = millis / 1000;
65            time.tv_usec = (millis * 1000) % 1000000;
66            FD_ZERO(&wfds);
67            FD_SET(sck, &wfds);
68            sel_count = select(sck + 1, 0, &wfds, 0, &time);
69            if (sel_count > 0)
70            {
71                    return True;
72            }
73            return False;
74    }
75    
76  /* Initialise TCP transport data packet */  /* Initialise TCP transport data packet */
77  STREAM  STREAM
78  tcp_init(int maxlen)  tcp_init(uint32 maxlen)
79  {  {
80          if (maxlen > out.size)          STREAM result = NULL;
81    
82    #ifdef WITH_SCARD
83            scard_lock(SCARD_LOCK_TCP);
84            result = scard_tcp_init();
85    #else
86            result = &g_out;
87    #endif
88    
89            if (maxlen > result->size)
90          {          {
91                  out.data = xrealloc(out.data, maxlen);                  result->data = (uint8 *) xrealloc(result->data, maxlen);
92                  out.size = maxlen;                  result->size = maxlen;
93          }          }
94    
95          out.p = out.data;          result->p = result->data;
96          out.end = out.data + out.size;          result->end = result->data + result->size;
97          return &out;  #ifdef WITH_SCARD
98            scard_unlock(SCARD_LOCK_TCP);
99    #endif
100            return result;
101  }  }
102    
103  /* Send TCP transport data packet */  /* Send TCP transport data packet */
# Line 54  tcp_send(STREAM s) Line 107  tcp_send(STREAM s)
107          int length = s->end - s->data;          int length = s->end - s->data;
108          int sent, total = 0;          int sent, total = 0;
109    
110    #ifdef WITH_SCARD
111            scard_lock(SCARD_LOCK_TCP);
112    #endif
113          while (total < length)          while (total < length)
114          {          {
115                  sent = send(sock, s->data + total, length - total, 0);                  sent = send(g_sock, s->data + total, length - total, 0);
116                  if (sent <= 0)                  if (sent <= 0)
117                  {                  {
118                          error("send: %s\n", strerror(errno));                          if (sent == -1 && TCP_BLOCKS)
119                          return;                          {
120                                    tcp_can_send(g_sock, 100);
121                                    sent = 0;
122                            }
123                            else
124                            {
125                                    error("send: %s\n", TCP_STRERROR);
126                                    return;
127                            }
128                  }                  }
   
129                  total += sent;                  total += sent;
130          }          }
131    #ifdef WITH_SCARD
132            scard_unlock(SCARD_LOCK_TCP);
133    #endif
134  }  }
135    
136  /* Receive a message on the TCP layer */  /* Receive a message on the TCP layer */
137  STREAM  STREAM
138  tcp_recv(int length)  tcp_recv(STREAM s, uint32 length)
139  {  {
140            uint32 new_length, end_offset, p_offset;
141          int rcvd = 0;          int rcvd = 0;
142    
143          if (length > in.size)          if (s == NULL)
144          {          {
145                  in.data = xrealloc(in.data, length);                  /* read into "new" stream */
146                  in.size = length;                  if (length > g_in.size)
147                    {
148                            g_in.data = (uint8 *) xrealloc(g_in.data, length);
149                            g_in.size = length;
150                    }
151                    g_in.end = g_in.p = g_in.data;
152                    s = &g_in;
153            }
154            else
155            {
156                    /* append to existing stream */
157                    new_length = (s->end - s->data) + length;
158                    if (new_length > s->size)
159                    {
160                            p_offset = s->p - s->data;
161                            end_offset = s->end - s->data;
162                            s->data = (uint8 *) xrealloc(s->data, new_length);
163                            s->size = new_length;
164                            s->p = s->data + p_offset;
165                            s->end = s->data + end_offset;
166                    }
167          }          }
   
         in.end = in.p = in.data;  
168    
169          while (length > 0)          while (length > 0)
170          {          {
171                  ui_select(sock);                  if (!ui_select(g_sock))
172                            /* User quit */
173                            return NULL;
174    
175                  rcvd = recv(sock, in.end, length, 0);                  rcvd = recv(g_sock, s->end, length, 0);
176                  if (rcvd == -1)                  if (rcvd < 0)
177                    {
178                            if (rcvd == -1 && TCP_BLOCKS)
179                            {
180                                    rcvd = 0;
181                            }
182                            else
183                            {
184                                    error("recv: %s\n", TCP_STRERROR);
185                                    return NULL;
186                            }
187                    }
188                    else if (rcvd == 0)
189                  {                  {
190                          error("recv: %s\n", strerror(errno));                          error("Connection closed\n");
191                          return NULL;                          return NULL;
192                  }                  }
193    
194                  in.end += rcvd;                  s->end += rcvd;
195                  length -= rcvd;                  length -= rcvd;
196          }          }
197    
198          return &in;          return s;
199  }  }
200    
201  /* Establish a connection on the TCP layer */  /* Establish a connection on the TCP layer */
202  BOOL  BOOL
203  tcp_connect(char *server)  tcp_connect(char *server)
204  {  {
205            socklen_t option_len;
206            uint32 option_value;
207    
208    #ifdef IPv6
209    
210            int n;
211            struct addrinfo hints, *res, *ressave;
212            char tcp_port_rdp_s[10];
213    
214            snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
215    
216            memset(&hints, 0, sizeof(struct addrinfo));
217            hints.ai_family = AF_UNSPEC;
218            hints.ai_socktype = SOCK_STREAM;
219    
220            if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
221            {
222                    error("getaddrinfo: %s\n", gai_strerror(n));
223                    return False;
224            }
225    
226            ressave = res;
227            g_sock = -1;
228            while (res)
229            {
230                    g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
231                    if (!(g_sock < 0))
232                    {
233                            if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
234                                    break;
235                            TCP_CLOSE(g_sock);
236                            g_sock = -1;
237                    }
238                    res = res->ai_next;
239            }
240            freeaddrinfo(ressave);
241    
242            if (g_sock == -1)
243            {
244                    error("%s: unable to connect\n", server);
245                    return False;
246            }
247    
248    #else /* no IPv6 support */
249    
250          struct hostent *nslookup;          struct hostent *nslookup;
251          struct sockaddr_in servaddr;          struct sockaddr_in servaddr;
         int true = 1;  
252    
253          if ((nslookup = gethostbyname(server)) != NULL)          if ((nslookup = gethostbyname(server)) != NULL)
254          {          {
255                  memcpy(&servaddr.sin_addr, nslookup->h_addr,                  memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr));
                        sizeof(servaddr.sin_addr));  
256          }          }
257          else if (!(servaddr.sin_addr.s_addr = inet_addr(server)))          else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
258          {          {
259                  error("%s: unable to resolve host\n", server);                  error("%s: unable to resolve host\n", server);
260                  return False;                  return False;
261          }          }
262    
263          if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)          if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
264          {          {
265                  error("socket: %s\n", strerror(errno));                  error("socket: %s\n", TCP_STRERROR);
266                  return False;                  return False;
267          }          }
268    
269          servaddr.sin_family = AF_INET;          servaddr.sin_family = AF_INET;
270          servaddr.sin_port = htons(TCP_PORT_RDP);          servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
271    
272          if (connect          if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
             (sock, (struct sockaddr *) &servaddr,  
              sizeof(struct sockaddr)) < 0)  
273          {          {
274                  error("connect: %s\n", strerror(errno));                  error("connect: %s\n", TCP_STRERROR);
275                  close(sock);                  TCP_CLOSE(g_sock);
276                  return False;                  return False;
277          }          }
278    
279          setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true,  #endif /* IPv6 */
                    sizeof(true));  
280    
281          in.size = 4096;          option_value = 1;
282          in.data = xmalloc(in.size);          option_len = sizeof(option_value);
283            setsockopt(g_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &option_value, option_len);
284            /* receive buffer must be a least 16 K */
285            if (getsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, &option_len) == 0)
286            {
287                    if (option_value < (1024 * 16))
288                    {
289                            option_value = 1024 * 16;
290                            option_len = sizeof(option_value);
291                            setsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, option_len);
292                    }
293            }
294    
295          out.size = 4096;          g_in.size = 4096;
296          out.data = xmalloc(out.size);          g_in.data = (uint8 *) xmalloc(g_in.size);
297    
298    #ifdef WITH_SCARD
299            scard_tcp_connect();
300    #else
301            g_out.size = 4096;
302            g_out.data = (uint8 *) xmalloc(g_out.size);
303    #endif
304    
305          return True;          return True;
306  }  }
307    
308  /* Disconnect on the TCP layer */  /* Disconnect on the TCP layer */
309  void  void
310  tcp_disconnect()  tcp_disconnect(void)
311  {  {
312          close(sock);          TCP_CLOSE(g_sock);
313    }
314    
315    char *
316    tcp_get_address()
317    {
318            static char ipaddr[32];
319            struct sockaddr_in sockaddr;
320            socklen_t len = sizeof(sockaddr);
321            if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
322            {
323                    uint8 *ip = (uint8 *) &sockaddr.sin_addr;
324                    sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
325            }
326            else
327                    strcpy(ipaddr, "127.0.0.1");
328            return ipaddr;
329    }
330    
331    /* reset the state of the tcp layer */
332    /* Support for Session Directory */
333    void
334    tcp_reset_state(void)
335    {
336            g_sock = -1;            /* reset socket */
337    
338            /* Clear the incoming stream */
339            if (g_in.data != NULL)
340                    xfree(g_in.data);
341            g_in.p = NULL;
342            g_in.end = NULL;
343            g_in.data = NULL;
344            g_in.size = 0;
345            g_in.iso_hdr = NULL;
346            g_in.mcs_hdr = NULL;
347            g_in.sec_hdr = NULL;
348            g_in.rdp_hdr = NULL;
349            g_in.channel_hdr = NULL;
350    
351            /* Clear the outgoing stream(s) */
352    #ifdef WITH_SCARD
353            scard_tcp_reset_state();
354    #else
355            if (g_out.data != NULL)
356                    xfree(g_out.data);
357            g_out.p = NULL;
358            g_out.end = NULL;
359            g_out.data = NULL;
360            g_out.size = 0;
361            g_out.iso_hdr = NULL;
362            g_out.mcs_hdr = NULL;
363            g_out.sec_hdr = NULL;
364            g_out.rdp_hdr = NULL;
365            g_out.channel_hdr = NULL;
366    #endif
367  }  }

Legend:
Removed from v.33  
changed lines
  Added in v.1349

  ViewVC Help
Powered by ViewVC 1.1.26