15 static SOCKET s
= INVALID_SOCKET
;
17 #define iswritable(x) ( (x) != IAC && (x) != CR )
19 static void raw_size(void);
21 static int sb_opt
, sb_len
;
22 static char *sb_buf
= NULL
;
23 static int sb_size
= 0;
26 static void try_write (void) {
27 while (outbuf_head
!= outbuf_reap
) {
28 int end
= (outbuf_reap
< outbuf_head ? outbuf_head
: OUTBUF_SIZE
);
29 int len
= end
- outbuf_reap
;
32 ret
= send (s
, outbuf
+outbuf_reap
, len
, 0);
34 outbuf_reap
= (outbuf_reap
+ ret
) & OUTBUF_MASK
;
40 static void s_write (void *buf
, int len
) {
41 unsigned char *p
= buf
;
43 int new_head
= (outbuf_head
+ 1) & OUTBUF_MASK
;
44 if (new_head
!= outbuf_reap
) {
45 outbuf
[outbuf_head
] = *p
++;
46 outbuf_head
= new_head
;
52 static void c_write (char *buf
, int len
) {
54 int new_head
= (inbuf_head
+ 1) & INBUF_MASK
;
55 int c
= (unsigned char) *buf
;
56 if (new_head
!= inbuf_reap
) {
57 inbuf
[inbuf_head
] = *buf
++;
58 inbuf_head
= new_head
;
61 if( inbuf_head
== inbuf_reap
) len
++; else break;
67 * Called to set up the raw connection. Will arrange for
68 * WM_NETEVENT messages to be passed to the specified window, whose
69 * window procedure should then call raw_msg().
71 * Returns an error message, or NULL on success.
73 * Also places the canonical host name into `realhost'.
75 static char *raw_init (HWND hwnd
, char *host
, int port
, char **realhost
) {
83 if ( (a
= inet_addr(host
)) == (unsigned long) INADDR_NONE
) {
84 if ( (h
= gethostbyname(host
)) == NULL
)
85 switch (WSAGetLastError()) {
86 case WSAENETDOWN
: return "Network is down";
87 case WSAHOST_NOT_FOUND
: case WSANO_DATA
:
88 return "Host does not exist";
89 case WSATRY_AGAIN
: return "Host not found";
90 default: return "gethostbyname: unknown error";
92 memcpy (&a
, h
->h_addr
, sizeof(a
));
93 *realhost
= h
->h_name
;
99 port
= 23; /* default telnet port */
104 s
= socket(AF_INET
, SOCK_STREAM
, 0);
105 if (s
== INVALID_SOCKET
)
106 switch (WSAGetLastError()) {
107 case WSAENETDOWN
: return "Network is down";
108 case WSAEAFNOSUPPORT
: return "TCP/IP support not present";
109 default: return "socket(): unknown error";
113 * Bind to local address.
115 addr
.sin_family
= AF_INET
;
116 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
117 addr
.sin_port
= htons(0);
118 if (bind (s
, (struct sockaddr
*)&addr
, sizeof(addr
)) == SOCKET_ERROR
)
119 switch (WSAGetLastError()) {
120 case WSAENETDOWN
: return "Network is down";
121 default: return "bind(): unknown error";
125 * Connect to remote address.
127 addr
.sin_addr
.s_addr
= htonl(a
);
128 addr
.sin_port
= htons((short)port
);
129 if (connect (s
, (struct sockaddr
*)&addr
, sizeof(addr
)) == SOCKET_ERROR
)
130 switch (WSAGetLastError()) {
131 case WSAENETDOWN
: return "Network is down";
132 case WSAECONNREFUSED
: return "Connection refused";
133 case WSAENETUNREACH
: return "Network is unreachable";
134 case WSAEHOSTUNREACH
: return "No route to host";
135 default: return "connect(): unknown error";
138 if (WSAAsyncSelect (s
, hwnd
, WM_NETEVENT
, FD_READ
|
139 FD_WRITE
| FD_OOB
| FD_CLOSE
) == SOCKET_ERROR
)
140 switch (WSAGetLastError()) {
141 case WSAENETDOWN
: return "Network is down";
142 default: return "WSAAsyncSelect(): unknown error";
149 * Process a WM_NETEVENT message. Will return 0 if the connection
150 * has closed, or <0 for a socket error.
152 static int raw_msg (WPARAM wParam
, LPARAM lParam
) {
157 * Because reading less than the whole of the available pending
158 * data can generate an FD_READ event, we need to allow for the
159 * possibility that FD_READ may arrive with FD_CLOSE already in
160 * the queue; so it's possible that we can get here even with s
161 * invalid. If so, we return 1 and don't worry about it.
163 if (s
== INVALID_SOCKET
)
166 if (WSAGETSELECTERROR(lParam
) != 0)
167 return -WSAGETSELECTERROR(lParam
);
169 switch (WSAGETSELECTEVENT(lParam
)) {
172 ret
= recv(s
, buf
, sizeof(buf
), 0);
173 if (ret
< 0 && WSAGetLastError() == WSAEWOULDBLOCK
)
175 if (ret
< 0) /* any _other_ error */
176 return -10000-WSAGetLastError();
185 ret
= recv(s
, buf
, sizeof(buf
), 0);
189 ret
= recv(s
, buf
, 1, MSG_OOB
);
191 if (ret
< 0 && WSAGetLastError() != WSAEWOULDBLOCK
)
192 return -30000-WSAGetLastError();
195 if (outbuf_head
!= outbuf_reap
)
199 return 1; /* shouldn't happen, but WTF */
203 * Called to send data down the raw connection.
205 static void raw_send (char *buf
, int len
) {
207 if (s
== INVALID_SOCKET
)
214 * Called to set the size of the window
216 static void raw_size(void) {
222 * Send raw special codes.
224 static void raw_special (Telnet_Special code
) {
229 Backend raw_backend
= {