/[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 724 by stargo, Fri Jun 25 15:46:26 2004 UTC revision 1365 by jsorg71, Thu Jan 4 05:39:39 2007 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-2002     Copyright (C) Matthew Chapman 1999-2007
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
# Line 18  Line 18 
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    #ifdef _WIN32
35    #define socklen_t int
36    #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  #ifndef INADDR_NONE
46  #define INADDR_NONE ((unsigned long) -1)  #define INADDR_NONE ((unsigned long) -1)
47  #endif  #endif
48    
49  static int sock;  static int g_sock;
50  static struct stream in;  static struct stream g_in;
51  static struct stream out;  #ifndef WITH_SCARD
52    static struct stream g_out;
53    #endif
54  int g_tcp_port_rdp = TCP_PORT_RDP;  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(uint32 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 = (uint8 *) 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 59  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(STREAM s, uint32 length)  tcp_recv(STREAM s, uint32 length)
139  {  {
140          unsigned int new_length, end_offset, p_offset;          uint32 new_length, end_offset, p_offset;
141          int rcvd = 0;          int rcvd = 0;
142    
143          if (s == NULL)          if (s == NULL)
144          {          {
145                  /* read into "new" stream */                  /* read into "new" stream */
146                  if (length > in.size)                  if (length > g_in.size)
147                  {                  {
148                          in.data = (uint8 *) xrealloc(in.data, length);                          g_in.data = (uint8 *) xrealloc(g_in.data, length);
149                          in.size = length;                          g_in.size = length;
150                  }                  }
151                  in.end = in.p = in.data;                  g_in.end = g_in.p = g_in.data;
152                  s = &in;                  s = &g_in;
153          }          }
154          else          else
155          {          {
# Line 107  tcp_recv(STREAM s, uint32 length) Line 168  tcp_recv(STREAM s, uint32 length)
168    
169          while (length > 0)          while (length > 0)
170          {          {
171                  if (!ui_select(sock))                  if (!ui_select(g_sock))
172                          /* User quit */                          /* User quit */
173                          return NULL;                          return NULL;
174    
175                  rcvd = recv(sock, s->end, length, 0);                  rcvd = recv(g_sock, s->end, length, 0);
176                  if (rcvd < 0)                  if (rcvd < 0)
177                  {                  {
178                          error("recv: %s\n", strerror(errno));                          if (rcvd == -1 && TCP_BLOCKS)
179                          return NULL;                          {
180                                    rcvd = 0;
181                            }
182                            else
183                            {
184                                    error("recv: %s\n", TCP_STRERROR);
185                                    return NULL;
186                            }
187                  }                  }
188                  else if (rcvd == 0)                  else if (rcvd == 0)
189                  {                  {
# Line 134  tcp_recv(STREAM s, uint32 length) Line 202  tcp_recv(STREAM s, uint32 length)
202  BOOL  BOOL
203  tcp_connect(char *server)  tcp_connect(char *server)
204  {  {
205          int true_value = 1;          socklen_t option_len;
206            uint32 option_value;
207    
208  #ifdef IPv6  #ifdef IPv6
209    
# Line 148  tcp_connect(char *server) Line 217  tcp_connect(char *server)
217          hints.ai_family = AF_UNSPEC;          hints.ai_family = AF_UNSPEC;
218          hints.ai_socktype = SOCK_STREAM;          hints.ai_socktype = SOCK_STREAM;
219    
220          if (getaddrinfo(server, tcp_port_rdp_s, &hints, &res))          if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
221          {          {
222                  error("getaddrinfo: %s\n", gai_strerror(n));                  error("getaddrinfo: %s\n", gai_strerror(n));
223                  return False;                  return False;
224          }          }
225    
226          ressave = res;          ressave = res;
227          sock = -1;          g_sock = -1;
228          while (res)          while (res)
229          {          {
230                  sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);                  g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
231                  if (!(sock < 0))                  if (!(g_sock < 0))
232                  {                  {
233                          if (connect(sock, res->ai_addr, res->ai_addrlen) == 0)                          if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
234                                  break;                                  break;
235                          close(sock);                          TCP_CLOSE(g_sock);
236                          sock = -1;                          g_sock = -1;
237                  }                  }
238                  res = res->ai_next;                  res = res->ai_next;
239          }          }
240          freeaddrinfo(ressave);          freeaddrinfo(ressave);
241    
242          if (sock == -1)          if (g_sock == -1)
243          {          {
244                  error("%s: unable to connect\n", server);                  error("%s: unable to connect\n", server);
245                  return False;                  return False;
# Line 191  tcp_connect(char *server) Line 260  tcp_connect(char *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(g_tcp_port_rdp);          servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
271    
272          if (connect(sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)          if (connect(g_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  #endif /* IPv6 */  #endif /* IPv6 */
280    
281          setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true_value, sizeof(true_value));          option_value = 1;
282            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,
292                                       option_len);
293                    }
294            }
295    
296          in.size = 4096;          g_in.size = 4096;
297          in.data = (uint8 *) xmalloc(in.size);          g_in.data = (uint8 *) xmalloc(g_in.size);
298    
299          out.size = 4096;  #ifdef WITH_SCARD
300          out.data = (uint8 *) xmalloc(out.size);          scard_tcp_connect();
301    #else
302            g_out.size = 4096;
303            g_out.data = (uint8 *) xmalloc(g_out.size);
304    #endif
305    
306          return True;          return True;
307  }  }
# Line 224  tcp_connect(char *server) Line 310  tcp_connect(char *server)
310  void  void
311  tcp_disconnect(void)  tcp_disconnect(void)
312  {  {
313          close(sock);          TCP_CLOSE(g_sock);
314  }  }
315    
316  char *  char *
# Line 232  tcp_get_address() Line 318  tcp_get_address()
318  {  {
319          static char ipaddr[32];          static char ipaddr[32];
320          struct sockaddr_in sockaddr;          struct sockaddr_in sockaddr;
321          size_t len = sizeof(sockaddr);          socklen_t len = sizeof(sockaddr);
322          if (getsockname(sock, (struct sockaddr *) &sockaddr, &len) == 0)          if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
323          {          {
324                  unsigned char *ip = (unsigned char *) &sockaddr.sin_addr;                  uint8 *ip = (uint8 *) & sockaddr.sin_addr;
325                  sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);                  sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
326          }          }
327          else          else
328                  strcpy(ipaddr, "127.0.0.1");                  strcpy(ipaddr, "127.0.0.1");
329          return ipaddr;          return ipaddr;
330  }  }
331    
332    /* reset the state of the tcp layer */
333    /* Support for Session Directory */
334    void
335    tcp_reset_state(void)
336    {
337            g_sock = -1;            /* reset socket */
338    
339            /* Clear the incoming stream */
340            if (g_in.data != NULL)
341                    xfree(g_in.data);
342            g_in.p = NULL;
343            g_in.end = NULL;
344            g_in.data = NULL;
345            g_in.size = 0;
346            g_in.iso_hdr = NULL;
347            g_in.mcs_hdr = NULL;
348            g_in.sec_hdr = NULL;
349            g_in.rdp_hdr = NULL;
350            g_in.channel_hdr = NULL;
351    
352            /* Clear the outgoing stream(s) */
353    #ifdef WITH_SCARD
354            scard_tcp_reset_state();
355    #else
356            if (g_out.data != NULL)
357                    xfree(g_out.data);
358            g_out.p = NULL;
359            g_out.end = NULL;
360            g_out.data = NULL;
361            g_out.size = 0;
362            g_out.iso_hdr = NULL;
363            g_out.mcs_hdr = NULL;
364            g_out.sec_hdr = NULL;
365            g_out.rdp_hdr = NULL;
366            g_out.channel_hdr = NULL;
367    #endif
368    }

Legend:
Removed from v.724  
changed lines
  Added in v.1365

  ViewVC Help
Powered by ViewVC 1.1.26