raw.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <winsock.h>
  5. #include "putty.h"
  6. #ifndef FALSE
  7. #define FALSE 0
  8. #endif
  9. #ifndef TRUE
  10. #define TRUE 1
  11. #endif
  12. static SOCKET s = INVALID_SOCKET;
  13. #define iswritable(x) ( (x) != IAC && (x) != CR )
  14. static void raw_size(void);
  15. static int sb_opt, sb_len;
  16. static char *sb_buf = NULL;
  17. static int sb_size = 0;
  18. #define SB_DELTA 1024
  19. static void try_write (void) {
  20. while (outbuf_head != outbuf_reap) {
  21. int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
  22. int len = end - outbuf_reap;
  23. int ret;
  24. ret = send (s, outbuf+outbuf_reap, len, 0);
  25. if (ret > 0)
  26. outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
  27. if (ret < len)
  28. return;
  29. }
  30. }
  31. static void s_write (void *buf, int len) {
  32. unsigned char *p = buf;
  33. while (len--) {
  34. int new_head = (outbuf_head + 1) & OUTBUF_MASK;
  35. if (new_head != outbuf_reap) {
  36. outbuf[outbuf_head] = *p++;
  37. outbuf_head = new_head;
  38. }
  39. }
  40. try_write();
  41. }
  42. static void c_write (char *buf, int len) {
  43. while (len--) {
  44. int new_head = (inbuf_head + 1) & INBUF_MASK;
  45. if (new_head != inbuf_reap) {
  46. inbuf[inbuf_head] = *buf++;
  47. inbuf_head = new_head;
  48. } else {
  49. term_out();
  50. if( inbuf_head == inbuf_reap ) len++; else break;
  51. }
  52. }
  53. }
  54. /*
  55. * Called to set up the raw connection. Will arrange for
  56. * WM_NETEVENT messages to be passed to the specified window, whose
  57. * window procedure should then call raw_msg().
  58. *
  59. * Returns an error message, or NULL on success.
  60. *
  61. * Also places the canonical host name into `realhost'.
  62. */
  63. static char *raw_init (HWND hwnd, char *host, int port, char **realhost) {
  64. SOCKADDR_IN addr;
  65. struct hostent *h;
  66. unsigned long a;
  67. /*
  68. * Try to find host.
  69. */
  70. if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
  71. if ( (h = gethostbyname(host)) == NULL)
  72. switch (WSAGetLastError()) {
  73. case WSAENETDOWN: return "Network is down";
  74. case WSAHOST_NOT_FOUND: case WSANO_DATA:
  75. return "Host does not exist";
  76. case WSATRY_AGAIN: return "Host not found";
  77. default: return "gethostbyname: unknown error";
  78. }
  79. memcpy (&a, h->h_addr, sizeof(a));
  80. *realhost = h->h_name;
  81. } else
  82. *realhost = host;
  83. a = ntohl(a);
  84. if (port < 0)
  85. port = 23; /* default telnet port */
  86. /*
  87. * Open socket.
  88. */
  89. s = socket(AF_INET, SOCK_STREAM, 0);
  90. if (s == INVALID_SOCKET)
  91. switch (WSAGetLastError()) {
  92. case WSAENETDOWN: return "Network is down";
  93. case WSAEAFNOSUPPORT: return "TCP/IP support not present";
  94. default: return "socket(): unknown error";
  95. }
  96. /*
  97. * Bind to local address.
  98. */
  99. addr.sin_family = AF_INET;
  100. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  101. addr.sin_port = htons(0);
  102. if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
  103. switch (WSAGetLastError()) {
  104. case WSAENETDOWN: return "Network is down";
  105. default: return "bind(): unknown error";
  106. }
  107. /*
  108. * Connect to remote address.
  109. */
  110. addr.sin_addr.s_addr = htonl(a);
  111. addr.sin_port = htons((short)port);
  112. if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
  113. switch (WSAGetLastError()) {
  114. case WSAENETDOWN: return "Network is down";
  115. case WSAECONNREFUSED: return "Connection refused";
  116. case WSAENETUNREACH: return "Network is unreachable";
  117. case WSAEHOSTUNREACH: return "No route to host";
  118. default: return "connect(): unknown error";
  119. }
  120. if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
  121. FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
  122. switch (WSAGetLastError()) {
  123. case WSAENETDOWN: return "Network is down";
  124. default: return "WSAAsyncSelect(): unknown error";
  125. }
  126. return NULL;
  127. }
  128. /*
  129. * Process a WM_NETEVENT message. Will return 0 if the connection
  130. * has closed, or <0 for a socket error.
  131. */
  132. static int raw_msg (WPARAM wParam, LPARAM lParam) {
  133. int ret;
  134. char buf[256];
  135. /*
  136. * Because reading less than the whole of the available pending
  137. * data can generate an FD_READ event, we need to allow for the
  138. * possibility that FD_READ may arrive with FD_CLOSE already in
  139. * the queue; so it's possible that we can get here even with s
  140. * invalid. If so, we return 1 and don't worry about it.
  141. */
  142. if (s == INVALID_SOCKET)
  143. return 1;
  144. if (WSAGETSELECTERROR(lParam) != 0)
  145. return -WSAGETSELECTERROR(lParam);
  146. switch (WSAGETSELECTEVENT(lParam)) {
  147. case FD_READ:
  148. case FD_CLOSE:
  149. ret = recv(s, buf, sizeof(buf), 0);
  150. if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
  151. return 1;
  152. if (ret < 0) /* any _other_ error */
  153. return -10000-WSAGetLastError();
  154. if (ret == 0) {
  155. s = INVALID_SOCKET;
  156. return 0;
  157. }
  158. c_write( buf, ret );
  159. return 1;
  160. case FD_OOB:
  161. do {
  162. ret = recv(s, buf, sizeof(buf), 0);
  163. c_write( buf, ret );
  164. } while (ret > 0);
  165. do {
  166. ret = recv(s, buf, 1, MSG_OOB);
  167. } while (ret > 0);
  168. if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
  169. return -30000-WSAGetLastError();
  170. return 1;
  171. case FD_WRITE:
  172. if (outbuf_head != outbuf_reap)
  173. try_write();
  174. return 1;
  175. }
  176. return 1; /* shouldn't happen, but WTF */
  177. }
  178. /*
  179. * Called to send data down the raw connection.
  180. */
  181. static void raw_send (char *buf, int len) {
  182. if (s == INVALID_SOCKET)
  183. return;
  184. s_write( buf, len );
  185. }
  186. /*
  187. * Called to set the size of the window
  188. */
  189. static void raw_size(void) {
  190. /* Do nothing! */
  191. return;
  192. }
  193. /*
  194. * Send raw special codes.
  195. */
  196. static void raw_special (Telnet_Special code) {
  197. /* Do nothing! */
  198. return;
  199. }
  200. Backend raw_backend = {
  201. raw_init,
  202. raw_msg,
  203. raw_send,
  204. raw_size,
  205. raw_special
  206. };