Import X server from vnc-3.3.7.
[rdpsrv] / tcp.c
1 /*
2    rdesktop: A Remote Desktop Protocol client.
3    Protocol services - TCP layer
4    Copyright (C) Matthew Chapman 1999-2002
5    
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.
10    
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.
15
16    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 #include <unistd.h>             /* select read write close */
22 #include <sys/socket.h>         /* socket connect setsockopt */
23 #include <sys/time.h>           /* timeval */
24 #include <netdb.h>              /* gethostbyname */
25 #include <netinet/in.h>         /* sockaddr_in */
26 #include <netinet/tcp.h>        /* TCP_NODELAY */
27 #include <arpa/inet.h>          /* inet_addr */
28 #include <errno.h>              /* errno */
29 #include "rdesktop.h"
30
31 #ifndef INADDR_NONE
32 #define INADDR_NONE ((unsigned long) -1)
33 #endif
34
35 static int sock;
36 static struct stream in;
37 static struct stream out;
38 extern int tcp_port_rdp;
39
40 /* Initialise TCP transport data packet */
41 STREAM
42 tcp_init(uint32 maxlen)
43 {
44         if (maxlen > out.size)
45         {
46                 out.data = (uint8 *) xrealloc(out.data, maxlen);
47                 out.size = maxlen;
48         }
49
50         out.p = out.data;
51         out.end = out.data + out.size;
52         return &out;
53 }
54
55 /* Send TCP transport data packet */
56 void
57 tcp_send(STREAM s)
58 {
59         int length = s->end - s->data;
60         int sent, total = 0;
61
62         while (total < length)
63         {
64                 sent = send(sock, s->data + total, length - total, 0);
65                 if (sent <= 0)
66                 {
67                         error("send: %s\n", strerror(errno));
68                         return;
69                 }
70
71                 total += sent;
72         }
73 }
74
75 /* Receive a message on the TCP layer */
76 STREAM
77 tcp_recv(STREAM s, uint32 length)
78 {
79         unsigned int new_length, end_offset, p_offset;
80         int rcvd = 0;
81
82         if (s == NULL)
83         {
84                 /* read into "new" stream */
85                 if (length > in.size)
86                 {
87                         in.data = (uint8 *) xrealloc(in.data, length);
88                         in.size = length;
89                 }
90                 in.end = in.p = in.data;
91                 s = &in;
92         }
93         else
94         {
95                 /* append to existing stream */
96                 new_length = (s->end - s->data) + length;
97                 if (new_length > s->size)
98                 {
99                         p_offset = s->p - s->data;
100                         end_offset = s->end - s->data;
101                         s->data = (uint8 *) xrealloc(s->data, new_length);
102                         s->size = new_length;
103                         s->p = s->data + p_offset;
104                         s->end = s->data + end_offset;
105                 }
106         }
107
108         while (length > 0)
109         {
110 #if 0
111                 if (!ui_select(sock))
112                         /* User quit */
113                         return NULL;
114 #endif
115
116                 rcvd = recv(sock, s->end, length, 0);
117                 if (rcvd < 0)
118                 {
119                         error("recv: %s\n", strerror(errno));
120                         return NULL;
121                 }
122                 else if (rcvd == 0)
123                 {
124                         error("Connection closed\n");
125                         return NULL;
126                 }
127
128                 s->end += rcvd;
129                 length -= rcvd;
130         }
131
132         return s;
133 }
134
135 /* Establish a connection on the TCP layer */
136 BOOL
137 tcp_recv_connect(int server_sock)
138 {
139         struct sockaddr_in sin;
140         unsigned true_value = 1;
141         socklen_t len = sizeof(sin);
142         sock = accept(server_sock, (struct sockaddr *)&sin, &len);
143
144         if (sock == -1) {
145                 perror("accept()");
146                 exit(1);
147         }
148
149         setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true_value, sizeof(true_value));
150
151         in.size = 4096;
152         in.data = (uint8 *) xmalloc(in.size);
153
154         out.size = 4096;
155         out.data = (uint8 *) xmalloc(out.size);
156
157         return True;
158 }
159
160 /* Disconnect on the TCP layer */
161 void
162 tcp_disconnect(void)
163 {
164         close(sock);
165 }