- Fix the LARGE_SIZE constant so it uses the lookaside list for mbuf ext buffers...
[reactos.git] / base / applications / tsclient / rdesktop / iso.c
1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - ISO layer
4 Copyright (C) Matthew Chapman 1999-2005
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 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.
19 */
20
21 #include "rdesktop.h"
22
23 /* Send a self-contained ISO PDU */
24 static BOOL
25 iso_send_msg(RDPCLIENT * This, uint8 code)
26 {
27 STREAM s;
28
29 s = tcp_init(This, 11);
30
31 if(s == NULL)
32 return False;
33
34 out_uint8(s, 3); /* version */
35 out_uint8(s, 0); /* reserved */
36 out_uint16_be(s, 11); /* length */
37
38 out_uint8(s, 6); /* hdrlen */
39 out_uint8(s, code);
40 out_uint16(s, 0); /* dst_ref */
41 out_uint16(s, 0); /* src_ref */
42 out_uint8(s, 0); /* class */
43
44 s_mark_end(s);
45 return tcp_send(This, s);
46 }
47
48 static BOOL
49 iso_send_connection_request(RDPCLIENT * This, char *cookie)
50 {
51 STREAM s;
52 int cookielen = (int)strlen(cookie);
53 int length = 11 + cookielen;
54
55 s = tcp_init(This, length);
56
57 if(s == NULL)
58 return False;
59
60 out_uint8(s, 3); /* version */
61 out_uint8(s, 0); /* reserved */
62 out_uint16_be(s, length); /* length */
63
64 out_uint8(s, length - 5); /* hdrlen */
65 out_uint8(s, ISO_PDU_CR);
66 out_uint16(s, 0); /* dst_ref */
67 out_uint16(s, 0); /* src_ref */
68 out_uint8(s, 0); /* class */
69
70 out_uint8p(s, cookie, cookielen);
71
72 s_mark_end(s);
73 return tcp_send(This, s);
74 }
75
76 /* Receive a message on the ISO layer, return code */
77 static STREAM
78 iso_recv_msg(RDPCLIENT * This, uint8 * code, uint8 * rdpver)
79 {
80 STREAM s;
81 uint16 length;
82 uint8 version;
83
84 s = tcp_recv(This, NULL, 4);
85 if (s == NULL)
86 return NULL;
87 in_uint8(s, version);
88 if (rdpver != NULL)
89 *rdpver = version;
90 if (version == 3)
91 {
92 in_uint8s(s, 1); /* pad */
93 in_uint16_be(s, length);
94 }
95 else
96 {
97 in_uint8(s, length);
98 if (length & 0x80)
99 {
100 length &= ~0x80;
101 next_be(s, length);
102 }
103 }
104 s = tcp_recv(This, s, length - 4);
105 if (s == NULL)
106 return NULL;
107 if (version != 3)
108 return s;
109 in_uint8s(s, 1); /* hdrlen */
110 in_uint8(s, *code);
111 if (*code == ISO_PDU_DT)
112 {
113 in_uint8s(s, 1); /* eot */
114 return s;
115 }
116 in_uint8s(s, 5); /* dst_ref, src_ref, class */
117 return s;
118 }
119
120 /* Initialise ISO transport data packet */
121 STREAM
122 iso_init(RDPCLIENT * This, int length)
123 {
124 STREAM s;
125
126 s = tcp_init(This, length + 7);
127
128 if(s == NULL)
129 return NULL;
130
131 s_push_layer(s, iso_hdr, 7);
132
133 return s;
134 }
135
136 /* Send an ISO data PDU */
137 BOOL
138 iso_send(RDPCLIENT * This, STREAM s)
139 {
140 uint16 length;
141
142 s_pop_layer(s, iso_hdr);
143 length = (uint16)(s->end - s->p);
144
145 out_uint8(s, 3); /* version */
146 out_uint8(s, 0); /* reserved */
147 out_uint16_be(s, length);
148
149 out_uint8(s, 2); /* hdrlen */
150 out_uint8(s, ISO_PDU_DT); /* code */
151 out_uint8(s, 0x80); /* eot */
152
153 return tcp_send(This, s);
154 }
155
156 /* Receive ISO transport data packet */
157 STREAM
158 iso_recv(RDPCLIENT * This, uint8 * rdpver)
159 {
160 STREAM s;
161 uint8 code = 0;
162
163 s = iso_recv_msg(This, &code, rdpver);
164 if (s == NULL)
165 return NULL;
166 if (rdpver != NULL)
167 if (*rdpver != 3)
168 return s;
169 if (code != ISO_PDU_DT)
170 {
171 error("expected DT, got 0x%x\n", code);
172 return NULL;
173 }
174 return s;
175 }
176
177 /* Establish a connection up to the ISO layer */
178 BOOL
179 iso_connect(RDPCLIENT * This, char *server, char *cookie)
180 {
181 uint8 code = 0;
182
183 if (!tcp_connect(This, server))
184 return False;
185
186 if (!iso_send_connection_request(This, cookie))
187 return False;
188
189 if (iso_recv_msg(This, &code, NULL) == NULL)
190 return False;
191
192 if (code != ISO_PDU_CC)
193 {
194 error("expected CC, got 0x%x\n", code);
195 tcp_disconnect(This);
196 return False;
197 }
198
199 return True;
200 }
201
202 /* Establish a reconnection up to the ISO layer */
203 BOOL
204 iso_reconnect(RDPCLIENT * This, char *server, char *cookie)
205 {
206 uint8 code = 0;
207
208 if (!tcp_connect(This, server))
209 return False;
210
211 if (!iso_send_connection_request(This, cookie)) // BUGBUG should we really pass the cookie here?
212 return False;
213
214 if (iso_recv_msg(This, &code, NULL) == NULL)
215 return False;
216
217 if (code != ISO_PDU_CC)
218 {
219 error("expected CC, got 0x%x\n", code);
220 tcp_disconnect(This);
221 return False;
222 }
223
224 return True;
225 }
226
227 /* Disconnect from the ISO layer */
228 BOOL
229 iso_disconnect(RDPCLIENT * This)
230 {
231 iso_send_msg(This, ISO_PDU_DR);
232 return tcp_disconnect(This);
233 }
234
235 /* reset the state to support reconnecting */
236 void
237 iso_reset_state(RDPCLIENT * This)
238 {
239 tcp_reset_state(This);
240 }