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.
25 #define TCP_CLOSE(_sck) closesocket(_sck)
26 #define TCP_STRERROR "tcp error"
27 #define TCP_SLEEP(_n) Sleep(_n)
28 #define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
30 #define TCP_CLOSE(_sck) close(_sck)
31 #define TCP_STRERROR strerror(errno)
32 #define TCP_SLEEP(_n) sleep(_n)
33 #define TCP_BLOCKS (errno == EWOULDBLOCK)
37 #define INADDR_NONE ((unsigned long) -1)
41 static struct stream in
;
42 static struct stream out
;
43 int g_tcp_port_rdp
= TCP_PORT_RDP
;
45 /* Initialise TCP transport data packet */
47 tcp_init(uint32 maxlen
)
49 if (maxlen
> out
.size
)
51 out
.data
= (uint8
*) xrealloc(out
.data
, maxlen
);
56 out
.end
= out
.data
+ out
.size
;
60 /* Send TCP transport data packet */
64 int length
= s
->end
- s
->data
;
67 while (total
< length
)
69 sent
= send(sock
, (char *)s
->data
+ total
, length
- total
, 0);
72 if (sent
== -1 && TCP_BLOCKS
)
79 error("send: %s\n", TCP_STRERROR
);
87 /* Receive a message on the TCP layer */
89 tcp_recv(STREAM s
, uint32 length
)
91 unsigned int new_length
, end_offset
, p_offset
;
96 /* read into "new" stream */
99 in
.data
= (uint8
*) xrealloc(in
.data
, length
);
102 in
.end
= in
.p
= in
.data
;
107 /* append to existing stream */
108 new_length
= (s
->end
- s
->data
) + length
;
109 if (new_length
> s
->size
)
111 p_offset
= s
->p
- s
->data
;
112 end_offset
= s
->end
- s
->data
;
113 s
->data
= (uint8
*) xrealloc(s
->data
, new_length
);
114 s
->size
= new_length
;
115 s
->p
= s
->data
+ p_offset
;
116 s
->end
= s
->data
+ end_offset
;
122 if (!ui_select(sock
))
126 rcvd
= recv(sock
, (char *)s
->end
, length
, 0);
129 if (rcvd
== -1 && TCP_BLOCKS
)
136 error("recv: %s\n", TCP_STRERROR
);
142 error("Connection closed\n");
153 /* Establish a connection on the TCP layer */
155 tcp_connect(char *server
)
162 struct addrinfo hints
, *res
, *ressave
;
163 char tcp_port_rdp_s
[10];
165 snprintf(tcp_port_rdp_s
, 10, "%d", g_tcp_port_rdp
);
167 memset(&hints
, 0, sizeof(struct addrinfo
));
168 hints
.ai_family
= AF_UNSPEC
;
169 hints
.ai_socktype
= SOCK_STREAM
;
171 if ((n
= getaddrinfo(server
, tcp_port_rdp_s
, &hints
, &res
)))
173 error("getaddrinfo: %s\n", gai_strerror(n
));
181 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
184 if (connect(sock
, res
->ai_addr
, res
->ai_addrlen
) == 0)
191 freeaddrinfo(ressave
);
195 error("%s: unable to connect\n", server
);
199 #else /* no IPv6 support */
201 struct hostent
*nslookup
;
202 struct sockaddr_in servaddr
;
204 if ((nslookup
= gethostbyname(server
)) != NULL
)
206 memcpy(&servaddr
.sin_addr
, nslookup
->h_addr
, sizeof(servaddr
.sin_addr
));
208 else if ((servaddr
.sin_addr
.s_addr
= inet_addr(server
)) == INADDR_NONE
)
210 error("%s: unable to resolve host\n", server
);
214 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
216 error("socket: %s\n", TCP_STRERROR
);
220 servaddr
.sin_family
= AF_INET
;
221 servaddr
.sin_port
= htons((uint16
) g_tcp_port_rdp
);
223 if (connect(sock
, (struct sockaddr
*) &servaddr
, sizeof(struct sockaddr
)) < 0)
225 error("connect: %s\n", TCP_STRERROR
);
232 setsockopt(sock
, IPPROTO_TCP
, TCP_NODELAY
, (void *) &true_value
, sizeof(true_value
));
235 in
.data
= (uint8
*) xmalloc(in
.size
);
238 out
.data
= (uint8
*) xmalloc(out
.size
);
243 /* Disconnect on the TCP layer */
253 static char ipaddr
[32];
254 struct sockaddr_in sockaddr
;
255 socklen_t len
= sizeof(sockaddr
);
256 if (getsockname(sock
, (struct sockaddr
*) &sockaddr
, &len
) == 0)
258 unsigned char *ip
= (unsigned char *) &sockaddr
.sin_addr
;
259 sprintf(ipaddr
, "%d.%d.%d.%d", ip
[0], ip
[1], ip
[2], ip
[3]);
262 strcpy(ipaddr
, "127.0.0.1");
266 /* reset the state of the tcp layer */
267 /* Support for Session Directory */
269 tcp_reset_state(void)
271 sock
= -1; /* reset socket */
273 /* Clear the incoming stream */
284 in
.channel_hdr
= NULL
;
286 /* Clear the outgoing stream */
287 if (out
.data
!= NULL
)
297 out
.channel_hdr
= NULL
;