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