/[rdesktop]/jpeg/rdesktop/trunk/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

Annotation of /jpeg/rdesktop/trunk/tcp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1475 - (hide annotations)
Fri Jul 11 03:51:23 2008 UTC (15 years, 10 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/tcp.c
File MIME type: text/plain
File size: 7885 byte(s)
update the copyright year

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

  ViewVC Help
Powered by ViewVC 1.1.26