1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - TCP layer
4 Copyright (C) Matthew Chapman 1999-2005
6 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.
11 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.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #define TCP_CLOSE(_sck) closesocket(_sck)
27 #define TCP_STRERROR "tcp error"
28 #define TCP_SLEEP(_n) Sleep(_n)
29 #define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
31 #define TCP_CLOSE(_sck) close(_sck)
32 #define TCP_STRERROR strerror(errno)
33 #define TCP_SLEEP(_n) sleep(_n)
34 #define TCP_BLOCKS (errno == EWOULDBLOCK)
38 #define INADDR_NONE ((unsigned long) -1)
42 static struct stream in
;
43 static struct stream out
;
44 int g_tcp_port_rdp
= TCP_PORT_RDP
;
46 /* Initialise TCP transport data packet */
48 tcp_init(uint32 maxlen
)
50 if (maxlen
> out
.size
)
52 out
.data
= (uint8
*) xrealloc(out
.data
, maxlen
);
57 out
.end
= out
.data
+ out
.size
;
61 /* Send TCP transport data packet */
65 int length
= s
->end
- s
->data
;
68 while (total
< length
)
70 sent
= send(sock
, (char *)s
->data
+ total
, length
- total
, 0);
73 if (sent
== -1 && TCP_BLOCKS
)
80 error("send: %s\n", TCP_STRERROR
);
88 /* Receive a message on the TCP layer */
90 tcp_recv(STREAM s
, uint32 length
)
92 unsigned int new_length
, end_offset
, p_offset
;
97 /* read into "new" stream */
100 in
.data
= (uint8
*) xrealloc(in
.data
, length
);
103 in
.end
= in
.p
= in
.data
;
108 /* append to existing stream */
109 new_length
= (s
->end
- s
->data
) + length
;
110 if (new_length
> s
->size
)
112 p_offset
= s
->p
- s
->data
;
113 end_offset
= s
->end
- s
->data
;
114 s
->data
= (uint8
*) xrealloc(s
->data
, new_length
);
115 s
->size
= new_length
;
116 s
->p
= s
->data
+ p_offset
;
117 s
->end
= s
->data
+ end_offset
;
123 if (!ui_select(sock
))
127 rcvd
= recv(sock
, (char *)s
->end
, length
, 0);
130 if (rcvd
== -1 && TCP_BLOCKS
)
137 error("recv: %s\n", TCP_STRERROR
);
143 error("Connection closed\n");
154 /* Establish a connection on the TCP layer */
156 tcp_connect(char *server
)
163 struct addrinfo hints
, *res
, *ressave
;
164 char tcp_port_rdp_s
[10];
166 snprintf(tcp_port_rdp_s
, 10, "%d", g_tcp_port_rdp
);
168 memset(&hints
, 0, sizeof(struct addrinfo
));
169 hints
.ai_family
= AF_UNSPEC
;
170 hints
.ai_socktype
= SOCK_STREAM
;
172 if ((n
= getaddrinfo(server
, tcp_port_rdp_s
, &hints
, &res
)))
174 error("getaddrinfo: %s\n", gai_strerror(n
));
182 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
185 if (connect(sock
, res
->ai_addr
, res
->ai_addrlen
) == 0)
192 freeaddrinfo(ressave
);
196 error("%s: unable to connect\n", server
);
200 #else /* no IPv6 support */
202 struct hostent
*nslookup
;
203 struct sockaddr_in servaddr
;
205 if ((nslookup
= gethostbyname(server
)) != NULL
)
207 memcpy(&servaddr
.sin_addr
, nslookup
->h_addr
, sizeof(servaddr
.sin_addr
));
209 else if ((servaddr
.sin_addr
.s_addr
= inet_addr(server
)) == INADDR_NONE
)
211 error("%s: unable to resolve host\n", server
);
215 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
217 error("socket: %s\n", TCP_STRERROR
);
221 servaddr
.sin_family
= AF_INET
;
222 servaddr
.sin_port
= htons((uint16
) g_tcp_port_rdp
);
224 if (connect(sock
, (struct sockaddr
*) &servaddr
, sizeof(struct sockaddr
)) < 0)
226 error("connect: %s\n", TCP_STRERROR
);
233 setsockopt(sock
, IPPROTO_TCP
, TCP_NODELAY
, (void *) &true_value
, sizeof(true_value
));
236 in
.data
= (uint8
*) xmalloc(in
.size
);
239 out
.data
= (uint8
*) xmalloc(out
.size
);
244 /* Disconnect on the TCP layer */
254 static char ipaddr
[32];
255 struct sockaddr_in sockaddr
;
256 socklen_t len
= sizeof(sockaddr
);
257 if (getsockname(sock
, (struct sockaddr
*) &sockaddr
, &len
) == 0)
259 unsigned char *ip
= (unsigned char *) &sockaddr
.sin_addr
;
260 sprintf(ipaddr
, "%d.%d.%d.%d", ip
[0], ip
[1], ip
[2], ip
[3]);
263 strcpy(ipaddr
, "127.0.0.1");
267 /* reset the state of the tcp layer */
268 /* Support for Session Directory */
270 tcp_reset_state(void)
272 sock
= -1; /* reset socket */
274 /* Clear the incoming stream */
285 in
.channel_hdr
= NULL
;
287 /* Clear the outgoing stream */
288 if (out
.data
!= NULL
)
298 out
.channel_hdr
= NULL
;