/engine/putty/raw.c

https://gitlab.com/OpenSourceMirror/s2putty · C · 282 lines · 193 code · 43 blank · 46 comment · 21 complexity · 42a7152157dd2bdaeb7b6296e8d6c09c MD5 · raw file

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