Switch round a bogus if statement I've just noticed. Both the write to
[u/mdw/putty] / raw.c
CommitLineData
eaf1e20a 1/*
2 * "Raw" backend.
3 */
4
5e1a8e27 5#include <stdio.h>
6#include <stdlib.h>
5e1a8e27 7
8#include "putty.h"
9
10#ifndef FALSE
11#define FALSE 0
12#endif
13#ifndef TRUE
14#define TRUE 1
15#endif
16
5471d09a 17#define RAW_MAX_BACKLOG 4096
18
51470298 19typedef struct raw_backend_data {
20 const struct plug_function_table *fn;
21 /* the above field _must_ be first in the structure */
5e1a8e27 22
51470298 23 Socket s;
24 int bufsize;
25 void *frontend;
bc06669b 26 int sent_console_eof, sent_socket_eof;
51470298 27} *Raw;
5e1a8e27 28
51470298 29static void raw_size(void *handle, int width, int height);
30
31static void c_write(Raw raw, char *buf, int len)
32874aea 32{
51470298 33 int backlog = from_backend(raw->frontend, 0, buf, len);
34 sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
5e1a8e27 35}
36
7555d6a5 37static void raw_log(Plug plug, int type, SockAddr addr, int port,
38 const char *error_msg, int error_code)
39{
40 Raw raw = (Raw) plug;
41 char addrbuf[256], *msg;
42
43 sk_getaddr(addr, addrbuf, lenof(addrbuf));
44
45 if (type == 0)
46 msg = dupprintf("Connecting to %s port %d", addrbuf, port);
47 else
48 msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
49
50 logevent(raw->frontend, msg);
51}
52
bc06669b 53static void raw_check_close(Raw raw)
54{
55 /*
56 * Called after we send EOF on either the socket or the console.
57 * Its job is to wind up the session once we have sent EOF on both.
58 */
59 if (raw->sent_console_eof && raw->sent_socket_eof) {
60 if (raw->s) {
61 sk_close(raw->s);
62 raw->s = NULL;
63 notify_remote_exit(raw->frontend);
64 }
65 }
66}
67
cbe2d68f 68static int raw_closing(Plug plug, const char *error_msg, int error_code,
32874aea 69 int calling_back)
70{
51470298 71 Raw raw = (Raw) plug;
72
7e78000d 73 if (error_msg) {
bc06669b 74 /* A socket error has occurred. */
75 if (raw->s) {
76 sk_close(raw->s);
77 raw->s = NULL;
78 notify_remote_exit(raw->frontend);
79 }
80 logevent(raw->frontend, error_msg);
81 connection_fatal(raw->frontend, "%s", error_msg);
82 } else {
83 /* Otherwise, the remote side closed the connection normally. */
84 if (!raw->sent_console_eof && from_backend_eof(raw->frontend)) {
85 /*
86 * The front end wants us to close the outgoing side of the
87 * connection as soon as we see EOF from the far end.
88 */
89 if (!raw->sent_socket_eof) {
90 if (raw->s)
91 sk_write_eof(raw->s);
92 raw->sent_socket_eof= TRUE;
93 }
94 }
95 raw->sent_console_eof = TRUE;
96 raw_check_close(raw);
97 }
7e78000d 98 return 0;
99}
100
32874aea 101static int raw_receive(Plug plug, int urgent, char *data, int len)
102{
51470298 103 Raw raw = (Raw) plug;
104 c_write(raw, data, len);
8df7a775 105 return 1;
5e1a8e27 106}
107
3ad9d396 108static void raw_sent(Plug plug, int bufsize)
109{
51470298 110 Raw raw = (Raw) plug;
111 raw->bufsize = bufsize;
3ad9d396 112}
113
5e1a8e27 114/*
8df7a775 115 * Called to set up the raw connection.
116 *
5e1a8e27 117 * Returns an error message, or NULL on success.
118 *
6e1ebb76 119 * Also places the canonical host name into `realhost'. It must be
120 * freed by the caller.
5e1a8e27 121 */
cbe2d68f 122static const char *raw_init(void *frontend_handle, void **backend_handle,
4a693cfc 123 Conf *conf,
79bf227b 124 char *host, int port, char **realhost, int nodelay,
125 int keepalive)
32874aea 126{
51470298 127 static const struct plug_function_table fn_table = {
7555d6a5 128 raw_log,
7e78000d 129 raw_closing,
3ad9d396 130 raw_receive,
131 raw_sent
51470298 132 };
8df7a775 133 SockAddr addr;
cbe2d68f 134 const char *err;
51470298 135 Raw raw;
4a693cfc 136 int addressfamily;
137 char *loghost;
5e1a8e27 138
3d88e64d 139 raw = snew(struct raw_backend_data);
51470298 140 raw->fn = &fn_table;
141 raw->s = NULL;
142 *backend_handle = raw;
bc06669b 143 raw->sent_console_eof = raw->sent_socket_eof = FALSE;
51470298 144
145 raw->frontend = frontend_handle;
887035a5 146
4a693cfc 147 addressfamily = conf_get_int(conf, CONF_addressfamily);
5e1a8e27 148 /*
149 * Try to find host.
150 */
3ad9d396 151 {
57356d63 152 char *buf;
05581745 153 buf = dupprintf("Looking up host \"%s\"%s", host,
4a693cfc 154 (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
155 (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
05581745 156 "")));
a8327734 157 logevent(raw->frontend, buf);
57356d63 158 sfree(buf);
3ad9d396 159 }
4a693cfc 160 addr = name_lookup(host, port, realhost, conf, addressfamily);
f85e6f6e 161 if ((err = sk_addr_error(addr)) != NULL) {
162 sk_addr_free(addr);
8df7a775 163 return err;
f85e6f6e 164 }
5e1a8e27 165
166 if (port < 0)
167 port = 23; /* default telnet port */
168
169 /*
170 * Open socket.
171 */
79bf227b 172 raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
4a693cfc 173 (Plug) raw, conf);
6f1e7b78 174 if ((err = sk_socket_error(raw->s)) != NULL)
8df7a775 175 return err;
5e1a8e27 176
4a693cfc 177 loghost = conf_get_str(conf, CONF_loghost);
178 if (*loghost) {
881da168 179 char *colon;
180
181 sfree(*realhost);
4a693cfc 182 *realhost = dupstr(loghost);
881da168 183 colon = strrchr(*realhost, ':');
184 if (colon) {
185 /*
186 * FIXME: if we ever update this aspect of ssh.c for
187 * IPv6 literal management, this should change in line
188 * with it.
189 */
190 *colon++ = '\0';
191 }
192 }
193
5e1a8e27 194 return NULL;
195}
196
fabd1805 197static void raw_free(void *handle)
198{
199 Raw raw = (Raw) handle;
200
201 if (raw->s)
202 sk_close(raw->s);
203 sfree(raw);
204}
205
5e1a8e27 206/*
86916870 207 * Stub routine (we don't have any need to reconfigure this backend).
208 */
4a693cfc 209static void raw_reconfig(void *handle, Conf *conf)
86916870 210{
211}
212
213/*
5e1a8e27 214 * Called to send data down the raw connection.
215 */
51470298 216static int raw_send(void *handle, char *buf, int len)
32874aea 217{
51470298 218 Raw raw = (Raw) handle;
219
220 if (raw->s == NULL)
b5a460cd 221 return 0;
5e1a8e27 222
51470298 223 raw->bufsize = sk_write(raw->s, buf, len);
5471d09a 224
51470298 225 return raw->bufsize;
5471d09a 226}
227
228/*
229 * Called to query the current socket sendability status.
230 */
51470298 231static int raw_sendbuffer(void *handle)
5471d09a 232{
51470298 233 Raw raw = (Raw) handle;
234 return raw->bufsize;
5e1a8e27 235}
236
237/*
238 * Called to set the size of the window
239 */
51470298 240static void raw_size(void *handle, int width, int height)
32874aea 241{
5e1a8e27 242 /* Do nothing! */
243 return;
244}
245
246/*
bc06669b 247 * Send raw special codes. We only handle outgoing EOF here.
5e1a8e27 248 */
51470298 249static void raw_special(void *handle, Telnet_Special code)
32874aea 250{
bc06669b 251 Raw raw = (Raw) handle;
252 if (code == TS_EOF && raw->s) {
253 sk_write_eof(raw->s);
254 raw->sent_socket_eof= TRUE;
255 raw_check_close(raw);
256 }
257
5e1a8e27 258 return;
259}
260
125105d1 261/*
262 * Return a list of the special codes that make sense in this
263 * protocol.
264 */
265static const struct telnet_special *raw_get_specials(void *handle)
266{
267 return NULL;
268}
269
6226c939 270static int raw_connected(void *handle)
32874aea 271{
51470298 272 Raw raw = (Raw) handle;
6226c939 273 return raw->s != NULL;
32874aea 274}
8ccc75b0 275
51470298 276static int raw_sendok(void *handle)
32874aea 277{
278 return 1;
279}
4017be6d 280
51470298 281static void raw_unthrottle(void *handle, int backlog)
5471d09a 282{
51470298 283 Raw raw = (Raw) handle;
284 sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
5471d09a 285}
286
51470298 287static int raw_ldisc(void *handle, int option)
32874aea 288{
0965bee0 289 if (option == LD_EDIT || option == LD_ECHO)
32874aea 290 return 1;
0965bee0 291 return 0;
292}
293
b9d7bcad 294static void raw_provide_ldisc(void *handle, void *ldisc)
295{
296 /* This is a stub. */
297}
298
a8327734 299static void raw_provide_logctx(void *handle, void *logctx)
300{
301 /* This is a stub. */
302}
303
51470298 304static int raw_exitcode(void *handle)
d8d6c7e5 305{
0da1a790 306 Raw raw = (Raw) handle;
307 if (raw->s != NULL)
308 return -1; /* still connected */
309 else
310 /* Exit codes are a meaningless concept in the Raw protocol */
311 return 0;
d8d6c7e5 312}
313
f89c3294 314/*
315 * cfg_info for Raw does nothing at all.
316 */
317static int raw_cfg_info(void *handle)
318{
319 return 0;
320}
321
5e1a8e27 322Backend raw_backend = {
323 raw_init,
fabd1805 324 raw_free,
86916870 325 raw_reconfig,
5e1a8e27 326 raw_send,
5471d09a 327 raw_sendbuffer,
5e1a8e27 328 raw_size,
4017be6d 329 raw_special,
125105d1 330 raw_get_specials,
6226c939 331 raw_connected,
d8d6c7e5 332 raw_exitcode,
97db3be4 333 raw_sendok,
0965bee0 334 raw_ldisc,
b9d7bcad 335 raw_provide_ldisc,
a8327734 336 raw_provide_logctx,
5471d09a 337 raw_unthrottle,
f89c3294 338 raw_cfg_info,
9e164d82 339 "raw",
340 PROT_RAW,
a4451dd1 341 0
5e1a8e27 342};