]> asedeno.scripts.mit.edu Git - PuTTY_svn.git/blob - raw.c
Enable xterm mouse reporting of wheel actions in GTK.
[PuTTY_svn.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                             char *host, int port, char **realhost, int nodelay,
129                             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
150     raw->frontend = frontend_handle;
151
152     addressfamily = conf_get_int(conf, CONF_addressfamily);
153     /*
154      * Try to find host.
155      */
156     {
157         char *buf;
158         buf = dupprintf("Looking up host \"%s\"%s", host,
159                         (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
160                          (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
161                           "")));
162         logevent(raw->frontend, buf);
163         sfree(buf);
164     }
165     addr = name_lookup(host, port, realhost, conf, addressfamily);
166     if ((err = sk_addr_error(addr)) != NULL) {
167         sk_addr_free(addr);
168         return err;
169     }
170
171     if (port < 0)
172         port = 23;                     /* default telnet port */
173
174     /*
175      * Open socket.
176      */
177     raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
178                             (Plug) raw, conf);
179     if ((err = sk_socket_error(raw->s)) != NULL)
180         return err;
181
182     loghost = conf_get_str(conf, CONF_loghost);
183     if (*loghost) {
184         char *colon;
185
186         sfree(*realhost);
187         *realhost = dupstr(loghost);
188
189         colon = host_strrchr(*realhost, ':');
190         if (colon)
191             *colon++ = '\0';
192     }
193
194     return NULL;
195 }
196
197 static 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
206 /*
207  * Stub routine (we don't have any need to reconfigure this backend).
208  */
209 static void raw_reconfig(void *handle, Conf *conf)
210 {
211 }
212
213 /*
214  * Called to send data down the raw connection.
215  */
216 static int raw_send(void *handle, char *buf, int len)
217 {
218     Raw raw = (Raw) handle;
219
220     if (raw->s == NULL)
221         return 0;
222
223     raw->bufsize = sk_write(raw->s, buf, len);
224
225     return raw->bufsize;
226 }
227
228 /*
229  * Called to query the current socket sendability status.
230  */
231 static int raw_sendbuffer(void *handle)
232 {
233     Raw raw = (Raw) handle;
234     return raw->bufsize;
235 }
236
237 /*
238  * Called to set the size of the window
239  */
240 static void raw_size(void *handle, int width, int height)
241 {
242     /* Do nothing! */
243     return;
244 }
245
246 /*
247  * Send raw special codes. We only handle outgoing EOF here.
248  */
249 static void raw_special(void *handle, Telnet_Special code)
250 {
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
258     return;
259 }
260
261 /*
262  * Return a list of the special codes that make sense in this
263  * protocol.
264  */
265 static const struct telnet_special *raw_get_specials(void *handle)
266 {
267     return NULL;
268 }
269
270 static int raw_connected(void *handle)
271 {
272     Raw raw = (Raw) handle;
273     return raw->s != NULL;
274 }
275
276 static int raw_sendok(void *handle)
277 {
278     return 1;
279 }
280
281 static void raw_unthrottle(void *handle, int backlog)
282 {
283     Raw raw = (Raw) handle;
284     sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
285 }
286
287 static int raw_ldisc(void *handle, int option)
288 {
289     if (option == LD_EDIT || option == LD_ECHO)
290         return 1;
291     return 0;
292 }
293
294 static void raw_provide_ldisc(void *handle, void *ldisc)
295 {
296     /* This is a stub. */
297 }
298
299 static void raw_provide_logctx(void *handle, void *logctx)
300 {
301     /* This is a stub. */
302 }
303
304 static int raw_exitcode(void *handle)
305 {
306     Raw raw = (Raw) handle;
307     if (raw->s != NULL)
308         return -1;                     /* still connected */
309     else if (raw->closed_on_socket_error)
310         return INT_MAX;     /* a socket error counts as an unclean exit */
311     else
312         /* Exit codes are a meaningless concept in the Raw protocol */
313         return 0;
314 }
315
316 /*
317  * cfg_info for Raw does nothing at all.
318  */
319 static int raw_cfg_info(void *handle)
320 {
321     return 0;
322 }
323
324 Backend raw_backend = {
325     raw_init,
326     raw_free,
327     raw_reconfig,
328     raw_send,
329     raw_sendbuffer,
330     raw_size,
331     raw_special,
332     raw_get_specials,
333     raw_connected,
334     raw_exitcode,
335     raw_sendok,
336     raw_ldisc,
337     raw_provide_ldisc,
338     raw_provide_logctx,
339     raw_unthrottle,
340     raw_cfg_info,
341     "raw",
342     PROT_RAW,
343     0
344 };