OSDN Git Service

Merge from feature_merge branch. Build TortoiseMerge successfully.
[tortoisegit/TortoiseGitJp.git] / src / TortoisePlink / RAW.C
1 /*\r
2  * "Raw" backend.\r
3  */\r
4 \r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 \r
8 #include "putty.h"\r
9 \r
10 #ifndef FALSE\r
11 #define FALSE 0\r
12 #endif\r
13 #ifndef TRUE\r
14 #define TRUE 1\r
15 #endif\r
16 \r
17 #define RAW_MAX_BACKLOG 4096\r
18 \r
19 typedef struct raw_backend_data {\r
20     const struct plug_function_table *fn;\r
21     /* the above field _must_ be first in the structure */\r
22 \r
23     Socket s;\r
24     int bufsize;\r
25     void *frontend;\r
26 } *Raw;\r
27 \r
28 static void raw_size(void *handle, int width, int height);\r
29 \r
30 static void c_write(Raw raw, char *buf, int len)\r
31 {\r
32     int backlog = from_backend(raw->frontend, 0, buf, len);\r
33     sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);\r
34 }\r
35 \r
36 static void raw_log(Plug plug, int type, SockAddr addr, int port,\r
37                     const char *error_msg, int error_code)\r
38 {\r
39     Raw raw = (Raw) plug;\r
40     char addrbuf[256], *msg;\r
41 \r
42     sk_getaddr(addr, addrbuf, lenof(addrbuf));\r
43 \r
44     if (type == 0)\r
45         msg = dupprintf("Connecting to %s port %d", addrbuf, port);\r
46     else\r
47         msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);\r
48 \r
49     logevent(raw->frontend, msg);\r
50 }\r
51 \r
52 static int raw_closing(Plug plug, const char *error_msg, int error_code,\r
53                        int calling_back)\r
54 {\r
55     Raw raw = (Raw) plug;\r
56 \r
57     if (raw->s) {\r
58         sk_close(raw->s);\r
59         raw->s = NULL;\r
60         notify_remote_exit(raw->frontend);\r
61     }\r
62     if (error_msg) {\r
63         /* A socket error has occurred. */\r
64         logevent(raw->frontend, error_msg);\r
65         connection_fatal(raw->frontend, "%s", error_msg);\r
66     }                                  /* Otherwise, the remote side closed the connection normally. */\r
67     return 0;\r
68 }\r
69 \r
70 static int raw_receive(Plug plug, int urgent, char *data, int len)\r
71 {\r
72     Raw raw = (Raw) plug;\r
73     c_write(raw, data, len);\r
74     return 1;\r
75 }\r
76 \r
77 static void raw_sent(Plug plug, int bufsize)\r
78 {\r
79     Raw raw = (Raw) plug;\r
80     raw->bufsize = bufsize;\r
81 }\r
82 \r
83 /*\r
84  * Called to set up the raw connection.\r
85  * \r
86  * Returns an error message, or NULL on success.\r
87  *\r
88  * Also places the canonical host name into `realhost'. It must be\r
89  * freed by the caller.\r
90  */\r
91 static const char *raw_init(void *frontend_handle, void **backend_handle,\r
92                             Config *cfg,\r
93                             char *host, int port, char **realhost, int nodelay,\r
94                             int keepalive)\r
95 {\r
96     static const struct plug_function_table fn_table = {\r
97         raw_log,\r
98         raw_closing,\r
99         raw_receive,\r
100         raw_sent\r
101     };\r
102     SockAddr addr;\r
103     const char *err;\r
104     Raw raw;\r
105 \r
106     raw = snew(struct raw_backend_data);\r
107     raw->fn = &fn_table;\r
108     raw->s = NULL;\r
109     *backend_handle = raw;\r
110 \r
111     raw->frontend = frontend_handle;\r
112 \r
113     /*\r
114      * Try to find host.\r
115      */\r
116     {\r
117         char *buf;\r
118         buf = dupprintf("Looking up host \"%s\"%s", host,\r
119                         (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :\r
120                          (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :\r
121                           "")));\r
122         logevent(raw->frontend, buf);\r
123         sfree(buf);\r
124     }\r
125     addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);\r
126     if ((err = sk_addr_error(addr)) != NULL) {\r
127         sk_addr_free(addr);\r
128         return err;\r
129     }\r
130 \r
131     if (port < 0)\r
132         port = 23;                     /* default telnet port */\r
133 \r
134     /*\r
135      * Open socket.\r
136      */\r
137     raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,\r
138                             (Plug) raw, cfg);\r
139     if ((err = sk_socket_error(raw->s)) != NULL)\r
140         return err;\r
141 \r
142     return NULL;\r
143 }\r
144 \r
145 static void raw_free(void *handle)\r
146 {\r
147     Raw raw = (Raw) handle;\r
148 \r
149     if (raw->s)\r
150         sk_close(raw->s);\r
151     sfree(raw);\r
152 }\r
153 \r
154 /*\r
155  * Stub routine (we don't have any need to reconfigure this backend).\r
156  */\r
157 static void raw_reconfig(void *handle, Config *cfg)\r
158 {\r
159 }\r
160 \r
161 /*\r
162  * Called to send data down the raw connection.\r
163  */\r
164 static int raw_send(void *handle, char *buf, int len)\r
165 {\r
166     Raw raw = (Raw) handle;\r
167 \r
168     if (raw->s == NULL)\r
169         return 0;\r
170 \r
171     raw->bufsize = sk_write(raw->s, buf, len);\r
172 \r
173     return raw->bufsize;\r
174 }\r
175 \r
176 /*\r
177  * Called to query the current socket sendability status.\r
178  */\r
179 static int raw_sendbuffer(void *handle)\r
180 {\r
181     Raw raw = (Raw) handle;\r
182     return raw->bufsize;\r
183 }\r
184 \r
185 /*\r
186  * Called to set the size of the window\r
187  */\r
188 static void raw_size(void *handle, int width, int height)\r
189 {\r
190     /* Do nothing! */\r
191     return;\r
192 }\r
193 \r
194 /*\r
195  * Send raw special codes.\r
196  */\r
197 static void raw_special(void *handle, Telnet_Special code)\r
198 {\r
199     /* Do nothing! */\r
200     return;\r
201 }\r
202 \r
203 /*\r
204  * Return a list of the special codes that make sense in this\r
205  * protocol.\r
206  */\r
207 static const struct telnet_special *raw_get_specials(void *handle)\r
208 {\r
209     return NULL;\r
210 }\r
211 \r
212 static int raw_connected(void *handle)\r
213 {\r
214     Raw raw = (Raw) handle;\r
215     return raw->s != NULL;\r
216 }\r
217 \r
218 static int raw_sendok(void *handle)\r
219 {\r
220     return 1;\r
221 }\r
222 \r
223 static void raw_unthrottle(void *handle, int backlog)\r
224 {\r
225     Raw raw = (Raw) handle;\r
226     sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);\r
227 }\r
228 \r
229 static int raw_ldisc(void *handle, int option)\r
230 {\r
231     if (option == LD_EDIT || option == LD_ECHO)\r
232         return 1;\r
233     return 0;\r
234 }\r
235 \r
236 static void raw_provide_ldisc(void *handle, void *ldisc)\r
237 {\r
238     /* This is a stub. */\r
239 }\r
240 \r
241 static void raw_provide_logctx(void *handle, void *logctx)\r
242 {\r
243     /* This is a stub. */\r
244 }\r
245 \r
246 static int raw_exitcode(void *handle)\r
247 {\r
248     Raw raw = (Raw) handle;\r
249     if (raw->s != NULL)\r
250         return -1;                     /* still connected */\r
251     else\r
252         /* Exit codes are a meaningless concept in the Raw protocol */\r
253         return 0;\r
254 }\r
255 \r
256 /*\r
257  * cfg_info for Raw does nothing at all.\r
258  */\r
259 static int raw_cfg_info(void *handle)\r
260 {\r
261     return 0;\r
262 }\r
263 \r
264 Backend raw_backend = {\r
265     raw_init,\r
266     raw_free,\r
267     raw_reconfig,\r
268     raw_send,\r
269     raw_sendbuffer,\r
270     raw_size,\r
271     raw_special,\r
272     raw_get_specials,\r
273     raw_connected,\r
274     raw_exitcode,\r
275     raw_sendok,\r
276     raw_ldisc,\r
277     raw_provide_ldisc,\r
278     raw_provide_logctx,\r
279     raw_unthrottle,\r
280     raw_cfg_info,\r
281     1\r
282 };\r