GOBJS1 = window.$(OBJ) windlg.$(OBJ) winctrls.$(OBJ) terminal.$(OBJ)
GOBJS2 = xlat.$(OBJ) sizetip.$(OBJ)
##-- objects putty puttytel plink
-LOBJS1 = telnet.$(OBJ) raw.$(OBJ) ldisc.$(OBJ)
+LOBJS1 = telnet.$(OBJ) raw.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ)
##-- objects putty plink
POBJS = be_all.$(OBJ)
##-- objects puttytel
##-- objects plink
PLOBJS = plink.$(OBJ)
##-- objects pscp
-SOBJS = scp.$(OBJ) be_none.$(OBJ)
+SOBJS = scp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ)
##-- objects putty puttytel pscp plink
MOBJS = misc.$(OBJ) version.$(OBJ) winstore.$(OBJ) settings.$(OBJ)
+MOBJ2 = tree234.$(OBJ)
##-- objects putty pscp plink
OBJS1 = sshcrc.$(OBJ) sshdes.$(OBJ) sshmd5.$(OBJ) sshrsa.$(OBJ) sshrand.$(OBJ)
OBJS2 = sshsha.$(OBJ) sshblowf.$(OBJ) noise.$(OBJ) sshdh.$(OBJ) sshdss.$(OBJ)
-OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ) tree234.$(OBJ)
+OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ)
##-- objects pageant
PAGE1 = pageant.$(OBJ) sshrsa.$(OBJ) sshpubk.$(OBJ) sshdes.$(OBJ) sshbn.$(OBJ)
PAGE2 = sshmd5.$(OBJ) version.$(OBJ) tree234.$(OBJ)
all: putty.exe puttytel.exe pscp.exe plink.exe pageant.exe puttygen.exe
-putty.exe: $(GOBJS1) $(GOBJS2) $(LOBJS1) $(POBJS) $(MOBJS) $(OBJS1) $(OBJS2) $(OBJS3) $(PRESRC) putty.rsp
+putty.exe: $(GOBJS1) $(GOBJS2) $(LOBJS1) $(POBJS) $(MOBJS) $(MOBJ2) $(OBJS1) $(OBJS2) $(OBJS3) $(PRESRC) putty.rsp
link $(LFLAGS) -out:putty.exe @putty.rsp
-puttytel.exe: $(GOBJS1) $(GOBJS2) $(LOBJS1) $(TOBJS) $(MOBJS) $(PRESRC) puttytel.rsp
+puttytel.exe: $(GOBJS1) $(GOBJS2) $(LOBJS1) $(TOBJS) $(MOBJS) $(MOBJ2) $(PRESRC) puttytel.rsp
link $(LFLAGS) -out:puttytel.exe @puttytel.rsp
pageant.exe: $(PAGE1) $(PAGE2) $(PAGERC) pageant.rsp
puttygen.exe: $(GEN1) $(GEN2) $(GEN3) $(GEN4) $(GENRC) puttygen.rsp
link $(LFLAGS) -out:puttygen.exe @puttygen.rsp
-pscp.exe: $(SOBJS) $(MOBJS) $(OBJS1) $(OBJS2) $(OBJS3) $(SRESRC) pscp.rsp
+pscp.exe: $(SOBJS) $(MOBJS) $(MOBJ2) $(OBJS1) $(OBJS2) $(OBJS3) $(SRESRC) pscp.rsp
link $(LFLAGS) -out:pscp.exe @pscp.rsp
-plink.exe: $(LOBJS1) $(POBJS) $(PLOBJS) $(MOBJS) $(OBJS1) $(OBJS2) $(OBJS3) $(LRESRC) plink.rsp
+plink.exe: $(LOBJS1) $(POBJS) $(PLOBJS) $(MOBJS) $(MOBJ2) $(OBJS1) $(OBJS2) $(OBJS3) $(LRESRC) plink.rsp
link $(LFLAGS) -out:plink.exe @plink.rsp
putty.rsp: makefile
echo $(LOBJS1) >> putty.rsp
echo $(POBJS) >> putty.rsp
echo $(MOBJS) >> putty.rsp
+ echo $(MOBJ2) >> putty.rsp
echo $(OBJS1) >> putty.rsp
echo $(OBJS2) >> putty.rsp
echo $(OBJS3) >> putty.rsp
echo $(LOBJS1) >> puttytel.rsp
echo $(TOBJS) >> puttytel.rsp
echo $(MOBJS) >> puttytel.rsp
+ echo $(MOBJ2) >> puttytel.rsp
echo $(PRESRC) >> puttytel.rsp
echo $(LIBS1) >> puttytel.rsp
echo $(LIBS2) >> puttytel.rsp
echo /nologo /subsystem:console > pscp.rsp
echo $(SOBJS) >> pscp.rsp
echo $(MOBJS) >> pscp.rsp
+ echo $(MOBJ2) >> pscp.rsp
echo $(OBJS1) >> pscp.rsp
echo $(OBJS2) >> pscp.rsp
echo $(OBJS3) >> pscp.rsp
echo $(POBJS) >> plink.rsp
echo $(PLOBJS) >> plink.rsp
echo $(MOBJS) >> plink.rsp
+ echo $(MOBJ2) >> plink.rsp
echo $(OBJS1) >> plink.rsp
echo $(OBJS2) >> plink.rsp
echo $(OBJS3) >> plink.rsp
echo $(SOCK2) >> plink.rsp
##-- dependencies
-window.$(OBJ): window.c putty.h win_res.h storage.h winstuff.h
-windlg.$(OBJ): windlg.c putty.h ssh.h win_res.h winstuff.h
+window.$(OBJ): window.c putty.h network.h win_res.h storage.h winstuff.h
+windlg.$(OBJ): windlg.c putty.h network.h ssh.h win_res.h winstuff.h
winctrls.$(OBJ): winctrls.c winstuff.h winstuff.h
-settings.$(OBJ): settings.c putty.h storage.h
-winstore.$(OBJ): winstore.c putty.h storage.h
-terminal.$(OBJ): terminal.c putty.h
-sizetip.$(OBJ): sizetip.c putty.h winstuff.h
-telnet.$(OBJ): telnet.c putty.h
-raw.$(OBJ): raw.c putty.h
-xlat.$(OBJ): xlat.c putty.h
-ldisc.$(OBJ): ldisc.c putty.h
-misc.$(OBJ): misc.c putty.h
-noise.$(OBJ): noise.c putty.h ssh.h storage.h
-ssh.$(OBJ): ssh.c ssh.h putty.h tree234.h
+settings.$(OBJ): settings.c putty.h network.h storage.h
+winstore.$(OBJ): winstore.c putty.h network.h storage.h
+terminal.$(OBJ): terminal.c putty.h network.h
+sizetip.$(OBJ): sizetip.c putty.h network.h winstuff.h
+telnet.$(OBJ): telnet.c putty.h network.h
+raw.$(OBJ): raw.c putty.h network.h
+xlat.$(OBJ): xlat.c putty.h network.h
+ldisc.$(OBJ): ldisc.c putty.h network.h
+misc.$(OBJ): misc.c putty.h network.h
+noise.$(OBJ): noise.c putty.h network.h ssh.h storage.h
+ssh.$(OBJ): ssh.c ssh.h putty.h network.h tree234.h
sshcrc.$(OBJ): sshcrc.c ssh.h
sshdes.$(OBJ): sshdes.c ssh.h
sshmd5.$(OBJ): sshmd5.c ssh.h
sshdss.$(OBJ): sshdss.c ssh.h
sshbn.$(OBJ): sshbn.c ssh.h
sshpubk.$(OBJ): sshpubk.c ssh.h
-scp.$(OBJ): scp.c putty.h winstuff.h
+scp.$(OBJ): scp.c putty.h network.h winstuff.h
version.$(OBJ): version.c
be_all.$(OBJ): be_all.c
be_nossh.$(OBJ): be_nossh.c
be_none.$(OBJ): be_none.c
-plink.$(OBJ): plink.c putty.h winstuff.h
+plink.$(OBJ): plink.c putty.h network.h winstuff.h
pageant.$(OBJ): pageant.c ssh.h tree234.h
tree234.$(OBJ): tree234.c tree234.h
##--
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include <ctype.h>
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include <stdlib.h>
#include "putty.h"
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
#include "putty.h"
-#include "winstuff.h"
#include "storage.h"
+#include "tree234.h"
void fatalbox (char *p, ...) {
va_list ap;
HANDLE outhandle, errhandle;
DWORD orig_console_mode;
+WSAEVENT netevent;
+
void begin_session(void) {
if (!cfg.ldisc_term)
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
struct input_data {
DWORD len;
char buffer[4096];
- HANDLE event;
+ HANDLE event, eventback;
};
static int get_password(const char *prompt, char *str, int maxlen)
inhandle = GetStdHandle(STD_INPUT_HANDLE);
while (ReadFile(inhandle, idata->buffer, sizeof(idata->buffer),
- &idata->len, NULL)) {
+ &idata->len, NULL) && idata->len > 0) {
SetEvent(idata->event);
+ WaitForSingleObject(idata->eventback, INFINITE);
}
idata->len = 0;
exit(1);
}
+char *do_select(SOCKET skt, int startup) {
+ int events;
+ if (startup) {
+ events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE;
+ } else {
+ events = 0;
+ }
+ if (WSAEventSelect (skt, netevent, events) == SOCKET_ERROR) {
+ switch (WSAGetLastError()) {
+ case WSAENETDOWN: return "Network is down";
+ default: return "WSAAsyncSelect(): unknown error";
+ }
+ }
+ return NULL;
+}
+
int main(int argc, char **argv) {
WSADATA wsadata;
WORD winsock_ver;
- WSAEVENT netevent, stdinevent;
+ WSAEVENT stdinevent;
HANDLE handles[2];
- SOCKET socket;
DWORD threadid;
struct input_data idata;
int sending;
int portnumber = -1;
+ SOCKET *sklist;
+ int skcount, sksize;
+ int connopen;
ssh_get_password = get_password;
+ sklist = NULL; skcount = sksize = 0;
+
flags = FLAG_STDERR;
/*
* Process the command line.
WSACleanup();
return 1;
}
+ sk_init();
/*
* Start up the connection.
*/
+ netevent = CreateEvent(NULL, FALSE, FALSE, NULL);
{
char *error;
char *realhost;
- error = back->init (NULL, cfg.host, cfg.port, &realhost);
+ error = back->init (cfg.host, cfg.port, &realhost);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
return 1;
}
}
+ connopen = 1;
- netevent = CreateEvent(NULL, FALSE, FALSE, NULL);
stdinevent = CreateEvent(NULL, FALSE, FALSE, NULL);
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &orig_console_mode);
errhandle = GetStdHandle(STD_ERROR_HANDLE);
/*
- * Now we must send the back end oodles of stuff.
- */
- socket = back->socket();
- /*
* Turn off ECHO and LINE input modes. We don't care if this
* call fails, because we know we aren't necessarily running in
* a console.
*/
- WSAEventSelect(socket, netevent, FD_READ | FD_CLOSE);
handles[0] = netevent;
handles[1] = stdinevent;
sending = FALSE;
* - so we're back to ReadFile blocking.
*/
idata.event = stdinevent;
+ idata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!CreateThread(NULL, 0, stdin_read_thread,
&idata, 0, &threadid)) {
fprintf(stderr, "Unable to create second thread\n");
n = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (n == 0) {
WSANETWORKEVENTS things;
- if (!WSAEnumNetworkEvents(socket, netevent, &things)) {
- if (things.lNetworkEvents & FD_READ)
- back->msg(0, FD_READ);
- if (things.lNetworkEvents & FD_CLOSE) {
- back->msg(0, FD_CLOSE);
- break;
- }
+ enum234 e;
+ SOCKET socket;
+ extern SOCKET first_socket(enum234 *), next_socket(enum234 *);
+ extern int select_result(WPARAM, LPARAM);
+ int i;
+
+ /*
+ * We must not call select_result() for any socket
+ * until we have finished enumerating within the tree.
+ * This is because select_result() may close the socket
+ * and modify the tree.
+ */
+ /* Count the active sockets. */
+ i = 0;
+ for (socket = first_socket(&e); socket != INVALID_SOCKET;
+ socket = next_socket(&e))
+ i++;
+
+ /* Expand the buffer if necessary. */
+ if (i > sksize) {
+ sksize = i+16;
+ sklist = srealloc(sklist, sksize * sizeof(*sklist));
+ }
+
+ /* Retrieve the sockets into sklist. */
+ skcount = 0;
+ for (socket = first_socket(&e); socket != INVALID_SOCKET;
+ socket = next_socket(&e)) {
+ sklist[skcount++] = socket;
}
+
+ /* Now we're done enumerating; go through the list. */
+ for (i = 0; i < skcount; i++) {
+ WPARAM wp;
+ socket = sklist[i];
+ wp = (WPARAM)socket;
+ if (!WSAEnumNetworkEvents(socket, netevent, &things)) {
+ if (things.lNetworkEvents & FD_READ)
+ connopen &= select_result(wp, (LPARAM)FD_READ);
+ if (things.lNetworkEvents & FD_CLOSE)
+ connopen &= select_result(wp, (LPARAM)FD_CLOSE);
+ if (things.lNetworkEvents & FD_OOB)
+ connopen &= select_result(wp, (LPARAM)FD_OOB);
+ if (things.lNetworkEvents & FD_WRITE)
+ connopen &= select_result(wp, (LPARAM)FD_WRITE);
+ }
+ }
} else if (n == 1) {
if (idata.len > 0) {
back->send(idata.buffer, idata.len);
} else {
back->special(TS_EOF);
}
+ SetEvent(idata.eventback);
}
- if (back->socket() == INVALID_SOCKET)
+ if (!connopen || back->socket() == NULL)
break; /* we closed the connection */
}
WSACleanup();
#ifndef PUTTY_PUTTY_H
#define PUTTY_PUTTY_H
+#include "network.h"
+
#define PUTTY_REG_POS "Software\\SimonTatham\\PuTTY"
#define PUTTY_REG_PARENT "Software\\SimonTatham"
#define PUTTY_REG_PARENT_CHILD "PuTTY"
} VT_Mode;
typedef struct {
- char *(*init) (HWND hwnd, char *host, int port, char **realhost);
- int (*msg) (WPARAM wParam, LPARAM lParam);
+ char *(*init) (char *host, int port, char **realhost);
void (*send) (char *buf, int len);
void (*size) (void);
void (*special) (Telnet_Special code);
- SOCKET (*socket) (void);
+ Socket (*socket) (void);
int (*sendok) (void);
int default_port;
} Backend;
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include "putty.h"
#define TRUE 1
#endif
-static SOCKET s = INVALID_SOCKET;
+static Socket s = NULL;
static void raw_size(void);
static int sb_size = 0;
#define SB_DELTA 1024
-static void try_write (void) {
- while (outbuf_head != outbuf_reap) {
- int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
- int len = end - outbuf_reap;
- int ret;
-
- ret = send (s, outbuf+outbuf_reap, len, 0);
- if (ret > 0)
- outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
- if (ret < len)
- return;
- }
+static void c_write (char *buf, int len) {
+ from_backend(0, buf, len);
}
-static void s_write (void *buf, int len) {
- unsigned char *p = buf;
- while (len--) {
- int new_head = (outbuf_head + 1) & OUTBUF_MASK;
- if (new_head != outbuf_reap) {
- outbuf[outbuf_head] = *p++;
- outbuf_head = new_head;
- }
+static int raw_receive (Socket s, int urgent, char *data, int len) {
+ if (!len) {
+ /* Connection has closed. */
+ sk_close(s);
+ s = NULL;
+ return 0;
}
- try_write();
-}
-
-static void c_write (char *buf, int len) {
- from_backend(0, buf, len);
+ c_write(data, len);
+ return 1;
}
/*
- * Called to set up the raw connection. Will arrange for
- * WM_NETEVENT messages to be passed to the specified window, whose
- * window procedure should then call raw_msg().
- *
+ * Called to set up the raw connection.
+ *
* Returns an error message, or NULL on success.
*
* Also places the canonical host name into `realhost'.
*/
-static char *raw_init (HWND hwnd, char *host, int port, char **realhost) {
- SOCKADDR_IN addr;
- struct hostent *h;
- unsigned long a;
+static char *raw_init (char *host, int port, char **realhost) {
+ SockAddr addr;
+ char *err;
/*
* Try to find host.
*/
- if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
- if ( (h = gethostbyname(host)) == NULL)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAHOST_NOT_FOUND: case WSANO_DATA:
- return "Host does not exist";
- case WSATRY_AGAIN: return "Host not found";
- default: return "gethostbyname: unknown error";
- }
- memcpy (&a, h->h_addr, sizeof(a));
- *realhost = h->h_name;
- } else
- *realhost = host;
- a = ntohl(a);
+ addr = sk_namelookup(host, realhost);
+ if ( (err = sk_addr_error(addr)) )
+ return err;
if (port < 0)
port = 23; /* default telnet port */
/*
* Open socket.
*/
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAEAFNOSUPPORT: return "TCP/IP support not present";
- default: return "socket(): unknown error";
- }
+ s = sk_new(addr, port, raw_receive);
+ if ( (err = sk_socket_error(s)) )
+ return err;
- /*
- * Bind to local address.
- */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(0);
- if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "bind(): unknown error";
- }
-
- /*
- * Connect to remote address.
- */
- addr.sin_addr.s_addr = htonl(a);
- addr.sin_port = htons((short)port);
- if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAECONNREFUSED: return "Connection refused";
- case WSAENETUNREACH: return "Network is unreachable";
- case WSAEHOSTUNREACH: return "No route to host";
- default: return "connect(): unknown error";
- }
-
- if (hwnd && WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
- FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "WSAAsyncSelect(): unknown error";
- }
+ sk_addr_free(addr);
/*
* We have no pre-session phase.
}
/*
- * Process a WM_NETEVENT message. Will return 0 if the connection
- * has closed, or <0 for a socket error.
- */
-static int raw_msg (WPARAM wParam, LPARAM lParam) {
- int ret;
- char buf[256];
-
- /*
- * Because reading less than the whole of the available pending
- * data can generate an FD_READ event, we need to allow for the
- * possibility that FD_READ may arrive with FD_CLOSE already in
- * the queue; so it's possible that we can get here even with s
- * invalid. If so, we return 1 and don't worry about it.
- */
- if (s == INVALID_SOCKET) {
- closesocket(s);
- s = INVALID_SOCKET;
- return 1;
- }
-
- if (WSAGETSELECTERROR(lParam) != 0)
- return -WSAGETSELECTERROR(lParam);
-
- switch (WSAGETSELECTEVENT(lParam)) {
- case FD_READ:
- case FD_CLOSE:
- ret = recv(s, buf, sizeof(buf), 0);
- if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
- return 1;
- if (ret < 0) { /* any _other_ error */
- closesocket(s);
- s = INVALID_SOCKET;
- return -10000-WSAGetLastError();
- }
- if (ret == 0) {
- s = INVALID_SOCKET;
- return 0;
- }
- c_write( buf, ret );
- return 1;
- case FD_OOB:
- do {
- ret = recv(s, buf, sizeof(buf), 0);
- c_write( buf, ret );
- } while (ret > 0);
- do {
- ret = recv(s, buf, 1, MSG_OOB);
- } while (ret > 0);
- if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
- return -30000-WSAGetLastError();
- return 1;
- case FD_WRITE:
- if (outbuf_head != outbuf_reap)
- try_write();
- return 1;
- }
- return 1; /* shouldn't happen, but WTF */
-}
-
-/*
* Called to send data down the raw connection.
*/
static void raw_send (char *buf, int len) {
- if (s == INVALID_SOCKET)
+ if (s == NULL)
return;
- s_write( buf, len );
+ sk_write(s, buf, len);
}
/*
return;
}
-static SOCKET raw_socket(void) { return s; }
+static Socket raw_socket(void) { return s; }
static int raw_sendok(void) { return 1; }
Backend raw_backend = {
raw_init,
- raw_msg,
raw_send,
raw_size,
raw_special,
}
/*
+ * Be told what socket we're supposed to be using.
+ */
+static SOCKET scp_ssh_socket;
+char *do_select(SOCKET skt, int startup) {
+ if (startup)
+ scp_ssh_socket = skt;
+ else
+ scp_ssh_socket = INVALID_SOCKET;
+ return NULL;
+}
+extern int select_result(WPARAM, LPARAM);
+
+/*
* Receive a block of data from the SSH link. Block until all data
* is available.
*
* own trap in from_backend() to catch the data that comes back. We
* do this until we have enough data.
*/
+
static unsigned char *outptr; /* where to put the data */
static unsigned outlen; /* how much data required */
static unsigned char *pending = NULL; /* any spare data */
}
}
static int ssh_scp_recv(unsigned char *buf, int len) {
- SOCKET s;
-
outptr = buf;
outlen = len;
while (outlen > 0) {
fd_set readfds;
- s = back->socket();
- if (s == INVALID_SOCKET) {
- connection_open = FALSE;
- return 0;
- }
+
FD_ZERO(&readfds);
- FD_SET(s, &readfds);
+ FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0)
return 0; /* doom */
- back->msg(0, FD_READ);
+ select_result((WPARAM)scp_ssh_socket, (LPARAM)FD_READ);
}
return len;
* Loop through the ssh connection and authentication process.
*/
static void ssh_scp_init(void) {
- SOCKET s;
-
- s = back->socket();
- if (s == INVALID_SOCKET)
+ if (scp_ssh_socket == INVALID_SOCKET)
return;
while (!back->sendok()) {
fd_set readfds;
FD_ZERO(&readfds);
- FD_SET(s, &readfds);
+ FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0)
return; /* doom */
- back->msg(0, FD_READ);
+ select_result((WPARAM)scp_ssh_socket, (LPARAM)FD_READ);
}
}
back = &ssh_backend;
- err = back->init(NULL, cfg.host, cfg.port, &realhost);
+ err = back->init(cfg.host, cfg.port, &realhost);
if (err != NULL)
bump("ssh_init: %s", err);
ssh_scp_init();
flags = FLAG_STDERR;
ssh_get_password = &get_password;
init_winsock();
+ sk_init();
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-')
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
#include "storage.h"
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <winreg.h>
#include <tchar.h>
#include <stdio.h>
+#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include "putty.h"
#include "tree234.h"
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
fprintf(stderr, "%s\n", s); }
-#define bombout(msg) ( ssh_state = SSH_STATE_CLOSED, closesocket(s), \
- s = INVALID_SOCKET, connection_fatal msg )
+#define bombout(msg) ( ssh_state = SSH_STATE_CLOSED, sk_close(s), \
+ s = NULL, connection_fatal msg )
#define SSH1_MSG_DISCONNECT 1 /* 0x1 */
#define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */
static SHA_State exhash;
-static SOCKET s = INVALID_SOCKET;
+static Socket s = NULL;
static unsigned char session_key[32];
static const struct ssh_cipher *cipher = NULL;
return 0;
}
-static void s_write (char *buf, int len) {
- while (len > 0) {
- int i = send (s, buf, len, 0);
- noise_ultralight(i);
- if (i <= 0) {
- bombout(("Lost connection while sending"));
- return;
- }
- if (i > 0)
- len -= i, buf += i;
- }
-}
-
-static int s_read (char *buf, int len) {
- int ret = 0;
- while (len > 0) {
- int i = recv (s, buf, len, 0);
- noise_ultralight(i);
- if (i > 0)
- len -= i, buf += i, ret += i;
- else
- return i;
- }
- return ret;
-}
-
static void c_write (char *buf, int len) {
if ((flags & FLAG_STDERR)) {
int i;
crFinish(0);
}
-static void ssh_gotdata(unsigned char *data, int datalen)
-{
- while (datalen > 0) {
- if ( s_rdpkt(&data, &datalen) == 0 ) {
- ssh_protocol(NULL, 0, 1);
- if (ssh_state == SSH_STATE_CLOSED) {
- return;
- }
- }
- }
-}
-
-
static void s_wrpkt_start(int type, int len) {
int pad, biglen;
if (cipher)
cipher->encrypt(pktout.data+4, biglen);
- s_write(pktout.data, biglen+4);
+ sk_write(s, pktout.data, biglen+4);
}
/*
s_wrpkt();
}
-
-/*
- * Connect to specified host and port.
- * Returns an error message, or NULL on success.
- * Also places the canonical host name into `realhost'.
- */
-static char *connect_to_host(char *host, int port, char **realhost)
-{
- SOCKADDR_IN addr;
- struct hostent *h;
- unsigned long a;
-#ifdef FWHACK
- char *FWhost;
- int FWport;
-#endif
-
- savedhost = malloc(1+strlen(host));
- if (!savedhost)
- fatalbox("Out of memory");
- strcpy(savedhost, host);
-
- if (port < 0)
- port = 22; /* default ssh port */
- savedport = port;
-
-#ifdef FWHACK
- FWhost = host;
- FWport = port;
- host = FWSTR;
- port = 23;
-#endif
-
- /*
- * Try to find host.
- */
- if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
- if ( (h = gethostbyname(host)) == NULL)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAHOST_NOT_FOUND: case WSANO_DATA:
- return "Host does not exist";
- case WSATRY_AGAIN: return "Host not found";
- default: return "gethostbyname: unknown error";
- }
- memcpy (&a, h->h_addr, sizeof(a));
- *realhost = h->h_name;
- } else
- *realhost = host;
-#ifdef FWHACK
- *realhost = FWhost;
-#endif
- a = ntohl(a);
-
- /*
- * Open socket.
- */
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAEAFNOSUPPORT: return "TCP/IP support not present";
- default: return "socket(): unknown error";
- }
-
- /*
- * Bind to local address.
- */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(0);
- if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "bind(): unknown error";
- }
-
- /*
- * Connect to remote address.
- */
- addr.sin_addr.s_addr = htonl(a);
- addr.sin_port = htons((short)port);
- if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAECONNREFUSED: return "Connection refused";
- case WSAENETUNREACH: return "Network is unreachable";
- case WSAEHOSTUNREACH: return "No route to host";
- default: return "connect(): unknown error";
- }
-
-#ifdef FWHACK
- send(s, "connect ", 8, 0);
- send(s, FWhost, strlen(FWhost), 0);
- {
- char buf[20];
- sprintf(buf, " %d\n", FWport);
- send (s, buf, strlen(buf), 0);
- }
-#endif
-
- return NULL;
-}
-
static int ssh_versioncmp(char *a, char *b) {
char *ae, *be;
unsigned long av, bv;
cscipher->encrypt(pktout.data, pktout.length + padding);
maclen = csmac ? csmac->len : 0;
- s_write(pktout.data, pktout.length + padding + maclen);
+ sk_write(s, pktout.data, pktout.length + padding + maclen);
}
#if 0
return b;
}
-static int do_ssh_init(void) {
- char c, *vsp;
- char version[10];
- char vstring[80];
- char vlog[sizeof(vstring)+20];
- int i;
+static int do_ssh_init(unsigned char c) {
+ static char *vsp;
+ static char version[10];
+ static char vstring[80];
+ static char vlog[sizeof(vstring)+20];
+ static int i;
-#ifdef FWHACK
+ crBegin;
+
+ /* Search for the string "SSH-" in the input. */
i = 0;
- while (s_read(&c, 1) == 1) {
- if (c == 'S' && i < 2) i++;
- else if (c == 'S' && i == 2) i = 2;
- else if (c == 'H' && i == 2) break;
+ while (1) {
+ static const int transS[] = { 1, 2, 2, 1 };
+ static const int transH[] = { 0, 0, 3, 0 };
+ static const int transminus[] = { 0, 0, 0, -1 };
+ if (c == 'S') i = transS[i];
+ else if (c == 'H') i = transH[i];
+ else if (c == '-') i = transminus[i];
else i = 0;
+ if (i < 0)
+ break;
+ crReturn(1); /* get another character */
}
-#else
- if (s_read(&c,1) != 1 || c != 'S') return 0;
- if (s_read(&c,1) != 1 || c != 'S') return 0;
- if (s_read(&c,1) != 1 || c != 'H') return 0;
-#endif
+
strcpy(vstring, "SSH-");
vsp = vstring+4;
- if (s_read(&c,1) != 1 || c != '-') return 0;
i = 0;
while (1) {
- if (s_read(&c,1) != 1)
- return 0;
+ crReturn(1); /* get another char */
if (vsp < vstring+sizeof(vstring)-1)
*vsp++ = c;
if (i >= 0) {
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
logevent("Using SSH protocol version 2");
- s_write(vstring, strlen(vstring));
+ sk_write(s, vstring, strlen(vstring));
ssh_protocol = ssh2_protocol;
ssh_version = 2;
s_rdpkt = ssh2_rdpkt;
vlog[strcspn(vlog, "\r\n")] = '\0';
logevent(vlog);
logevent("Using SSH protocol version 1");
- s_write(vstring, strlen(vstring));
+ sk_write(s, vstring, strlen(vstring));
ssh_protocol = ssh1_protocol;
ssh_version = 1;
s_rdpkt = ssh1_rdpkt;
}
- ssh_send_ok = 0;
+
+ crFinish(0);
+}
+
+static void ssh_gotdata(unsigned char *data, int datalen)
+{
+ crBegin;
+
+ /*
+ * To begin with, feed the characters one by one to the
+ * protocol initialisation / selection function do_ssh_init().
+ * When that returns 0, we're done with the initial greeting
+ * exchange and can move on to packet discipline.
+ */
+ while (1) {
+ int ret;
+ if (datalen == 0)
+ crReturnV; /* more data please */
+ ret = do_ssh_init(*data);
+ data++; datalen--;
+ if (ret == 0)
+ break;
+ }
+
+ /*
+ * We emerge from that loop when the initial negotiation is
+ * over and we have selected an s_rdpkt function. Now pass
+ * everything to s_rdpkt, and then pass the resulting packets
+ * to the proper protocol handler.
+ */
+ if (datalen == 0)
+ crReturnV;
+ while (1) {
+ while (datalen > 0) {
+ if ( s_rdpkt(&data, &datalen) == 0 ) {
+ ssh_protocol(NULL, 0, 1);
+ if (ssh_state == SSH_STATE_CLOSED) {
+ return;
+ }
+ }
+ }
+ crReturnV;
+ }
+ crFinishV;
+}
+
+static int ssh_receive(Socket s, int urgent, char *data, int len) {
+ if (!len) {
+ /* Connection has closed. */
+ sk_close(s);
+ s = NULL;
+ return 0;
+ }
+ ssh_gotdata (data, len);
return 1;
}
/*
+ * Connect to specified host and port.
+ * Returns an error message, or NULL on success.
+ * Also places the canonical host name into `realhost'.
+ */
+static char *connect_to_host(char *host, int port, char **realhost)
+{
+ SockAddr addr;
+ char *err;
+#ifdef FWHACK
+ char *FWhost;
+ int FWport;
+#endif
+
+ savedhost = malloc(1+strlen(host));
+ if (!savedhost)
+ fatalbox("Out of memory");
+ strcpy(savedhost, host);
+
+ if (port < 0)
+ port = 22; /* default ssh port */
+ savedport = port;
+
+#ifdef FWHACK
+ FWhost = host;
+ FWport = port;
+ host = FWSTR;
+ port = 23;
+#endif
+
+ /*
+ * Try to find host.
+ */
+ addr = sk_namelookup(host, realhost);
+ if ( (err = sk_addr_error(addr)) )
+ return err;
+
+#ifdef FWHACK
+ *realhost = FWhost;
+#endif
+
+ /*
+ * Open socket.
+ */
+ s = sk_new(addr, port, ssh_receive);
+ if ( (err = sk_socket_error(s)) )
+ return err;
+
+#ifdef FWHACK
+ sk_write(s, "connect ", 8);
+ sk_write(s, FWhost, strlen(FWhost));
+ {
+ char buf[20];
+ sprintf(buf, " %d\n", FWport);
+ sk_write(s, buf, strlen(buf));
+ }
+#endif
+
+ return NULL;
+}
+
+/*
* Handle the key exchange and user authentication phases.
*/
static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
crReturnV;
}
} else {
- send_packet(SSH1_CMSG_STDIN_DATA,
- PKT_INT, inlen, PKT_DATA, in, inlen, PKT_END);
+ while (inlen > 0) {
+ int len = min(inlen, 512);
+ send_packet(SSH1_CMSG_STDIN_DATA,
+ PKT_INT, len, PKT_DATA, in, len, PKT_END);
+ in += len;
+ inlen -= len;
+ }
}
}
ssh2_pkt_init(SSH2_MSG_DISCONNECT);
ssh2_pkt_send();
ssh_state = SSH_STATE_CLOSED;
- closesocket(s);
- s = INVALID_SOCKET;
+ sk_close(s);
+ s = NULL;
}
continue; /* remote sends close; ignore (FIXME) */
} else if (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
}
/*
- * Called to set up the connection. Will arrange for WM_NETEVENT
- * messages to be passed to the specified window, whose window
- * procedure should then call telnet_msg().
+ * Called to set up the connection.
*
* Returns an error message, or NULL on success.
*/
-static char *ssh_init (HWND hwnd, char *host, int port, char **realhost) {
+static char *ssh_init (char *host, int port, char **realhost) {
char *p;
#ifdef MSCRYPTOAPI
return "Microsoft high encryption pack not installed!";
#endif
+ ssh_send_ok = 0;
+
p = connect_to_host(host, port, realhost);
if (p != NULL)
return p;
- if (!do_ssh_init())
- return "Protocol initialisation error";
-
- if (hwnd && WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ | FD_CLOSE) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "WSAAsyncSelect(): unknown error";
- }
-
return NULL;
}
/*
- * Process a WM_NETEVENT message. Will return 0 if the connection
- * has closed, or <0 for a socket error.
- */
-static int ssh_msg (WPARAM wParam, LPARAM lParam) {
- int ret;
- char buf[256];
-
- /*
- * Because reading less than the whole of the available pending
- * data can generate an FD_READ event, we need to allow for the
- * possibility that FD_READ may arrive with FD_CLOSE already in
- * the queue; so it's possible that we can get here even with s
- * invalid. If so, we return 1 and don't worry about it.
- */
- if (s == INVALID_SOCKET)
- return 1;
-
- if (WSAGETSELECTERROR(lParam) != 0) {
- closesocket(s);
- s = INVALID_SOCKET;
- return -WSAGETSELECTERROR(lParam);
- }
-
- switch (WSAGETSELECTEVENT(lParam)) {
- case FD_READ:
- case FD_CLOSE:
- ret = recv(s, buf, sizeof(buf), 0);
- if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
- return 1;
- if (ret < 0) { /* any _other_ error */
- closesocket(s);
- s = INVALID_SOCKET;
- return -10000-WSAGetLastError();
- }
- if (ret == 0) {
- s = INVALID_SOCKET;
- return 0;
- }
- ssh_gotdata (buf, ret);
- if (ssh_state == SSH_STATE_CLOSED) {
- closesocket(s);
- s = INVALID_SOCKET;
- return 0;
- }
- return 1;
- }
- return 1; /* shouldn't happen, but WTF */
-}
-
-/*
* Called to send data down the Telnet connection.
*/
static void ssh_send (char *buf, int len) {
- if (s == INVALID_SOCKET)
+ if (s == NULL)
return;
ssh_protocol(buf, len, 0);
}
}
-static SOCKET ssh_socket(void) { return s; }
+static Socket ssh_socket(void) { return s; }
static int ssh_sendok(void) { return ssh_send_ok; }
Backend ssh_backend = {
ssh_init,
- ssh_msg,
ssh_send,
ssh_size,
ssh_special,
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include "putty.h"
#define TRUE 1
#endif
-static SOCKET s = INVALID_SOCKET;
+static Socket s = NULL;
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
static int sb_size = 0;
#define SB_DELTA 1024
-static void try_write (void) {
- while (outbuf_head != outbuf_reap) {
- int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
- int len = end - outbuf_reap;
- int ret;
-
- ret = send (s, outbuf+outbuf_reap, len, 0);
- if (ret > 0)
- outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
- if (ret < len)
- return;
- }
-}
-
-static void s_write (void *buf, int len) {
- unsigned char *p = buf;
- while (len--) {
- int new_head = (outbuf_head + 1) & OUTBUF_MASK;
- if (new_head != outbuf_reap) {
- outbuf[outbuf_head] = *p++;
- outbuf_head = new_head;
- }
- }
- try_write();
-}
-
static void c_write1(int c) {
char cc = (char)c;
from_backend(0, &cc, 1);
unsigned char b[3];
b[0] = IAC; b[1] = cmd; b[2] = option;
- s_write (b, 3);
+ sk_write(s, b, 3);
log_option("client", cmd, option);
}
strcpy(b+4, cfg.termspeed);
n = 4 + strlen(cfg.termspeed);
b[n] = IAC; b[n+1] = SE;
- s_write (b, n+2);
+ sk_write(s, b, n+2);
logevent("server:\tSB TSPEED SEND");
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
logevent (logbuf);
b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ?
cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]);
b[n+4] = IAC; b[n+5] = SE;
- s_write (b, n+6);
+ sk_write(s, b, n+6);
b[n+4] = 0;
logevent("server:\tSB TTYPE SEND");
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
while (*e) b[n++] = *e++;
}
b[n++] = IAC; b[n++] = SE;
- s_write (b, n);
+ sk_write(s, b, n);
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
n==6 ? "<nothing>" : "<stuff>");
logevent (logbuf);
}
}
+static int telnet_receive(Socket s, int urgent, char *data, int len) {
+ if (!len) {
+ /* Connection has closed. */
+ sk_close(s);
+ s = NULL;
+ return 0;
+ }
+ do_telnet_read (data, len);
+ return 1;
+}
+
/*
- * Called to set up the Telnet connection. Will arrange for
- * WM_NETEVENT messages to be passed to the specified window, whose
- * window procedure should then call telnet_msg().
+ * Called to set up the Telnet connection.
*
* Returns an error message, or NULL on success.
*
* Also places the canonical host name into `realhost'.
*/
-static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
- SOCKADDR_IN addr;
- struct hostent *h;
- unsigned long a;
+static char *telnet_init (char *host, int port, char **realhost) {
+ SockAddr addr;
+ char *err;
/*
* Try to find host.
*/
- if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
- if ( (h = gethostbyname(host)) == NULL)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAHOST_NOT_FOUND: case WSANO_DATA:
- return "Host does not exist";
- case WSATRY_AGAIN: return "Host not found";
- default: return "gethostbyname: unknown error";
- }
- memcpy (&a, h->h_addr, sizeof(a));
- *realhost = h->h_name;
- } else
- *realhost = host;
- a = ntohl(a);
+ addr = sk_namelookup(host, realhost);
+ if ( (err = sk_addr_error(addr)) )
+ return err;
if (port < 0)
port = 23; /* default telnet port */
/*
* Open socket.
*/
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAEAFNOSUPPORT: return "TCP/IP support not present";
- default: return "socket(): unknown error";
- }
+ s = sk_new(addr, port, telnet_receive);
+ if ( (err = sk_socket_error(s)) )
+ return err;
- {
- BOOL b = TRUE;
- setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
- }
-
- /*
- * Bind to local address.
- */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(0);
- if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "bind(): unknown error";
- }
-
- /*
- * Connect to remote address.
- */
- addr.sin_addr.s_addr = htonl(a);
- addr.sin_port = htons((short)port);
- if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- case WSAECONNREFUSED: return "Connection refused";
- case WSAENETUNREACH: return "Network is unreachable";
- case WSAEHOSTUNREACH: return "No route to host";
- default: return "connect(): unknown error";
- }
-
- if (hwnd && WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
- FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
- switch (WSAGetLastError()) {
- case WSAENETDOWN: return "Network is down";
- default: return "WSAAsyncSelect(): unknown error";
- }
+ sk_addr_free(addr);
/*
* Initialise option states.
}
/*
- * Process a WM_NETEVENT message. Will return 0 if the connection
- * has closed, or <0 for a socket error.
- */
-static int telnet_msg (WPARAM wParam, LPARAM lParam) {
- int ret;
- /* This needs to be larger than the packet size now that inbuf
- * cannot overflow, in fact the fewer calls we make to windows
- * the faster we will run!
- */
- char buf[16384];
-
- /*
- * Because reading less than the whole of the available pending
- * data can generate an FD_READ event, we need to allow for the
- * possibility that FD_READ may arrive with FD_CLOSE already in
- * the queue; so it's possible that we can get here even with s
- * invalid. If so, we return 1 and don't worry about it.
- */
- if (s == INVALID_SOCKET)
- return 1;
-
- if (WSAGETSELECTERROR(lParam) != 0) {
- closesocket(s);
- s = INVALID_SOCKET;
- return -WSAGETSELECTERROR(lParam);
- }
-
- switch (WSAGETSELECTEVENT(lParam)) {
- case FD_READ:
- case FD_CLOSE:
- {
- int clear_of_oob = 1;
-
- /* Don't check for error return; some shims don't support
- * this ioctl.
- */
- ioctlsocket (s, SIOCATMARK, &clear_of_oob);
-
- in_synch = !clear_of_oob;
-
- do {
- ret = recv(s, buf, sizeof(buf), 0);
- if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
- return 1;
- if (ret < 0) { /* any _other_ error */
- closesocket(s);
- s = INVALID_SOCKET;
- return -10000-WSAGetLastError();
- }
- if (ret == 0) {
- s = INVALID_SOCKET;
- return 0;
- }
- do_telnet_read (buf, ret);
- } while (in_synch);
- }
- return 1;
- case FD_WRITE:
- if (outbuf_head != outbuf_reap)
- try_write();
- return 1;
- }
- return 1; /* shouldn't happen, but WTF */
-}
-
-/*
* Called to send data down the Telnet connection.
*/
static void telnet_send (char *buf, int len) {
static unsigned char cr[2] = { CR, NUL };
static unsigned char nl[2] = { CR, LF };
- if (s == INVALID_SOCKET)
+ if (s == NULL)
return;
p = buf;
char *q = p;
while (iswritable((unsigned char)*p) && p < buf+len) p++;
- s_write (q, p-q);
+ sk_write(s, q, p-q);
while (p < buf+len && !iswritable((unsigned char)*p)) {
- s_write ((unsigned char)*p == IAC ? iac : nl, 2);
+ sk_write(s, (unsigned char)*p == IAC ? iac : nl, 2);
p++;
}
}
unsigned char b[16];
char logbuf[50];
- if (s == INVALID_SOCKET || o_naws.state != ACTIVE)
+ if (s == NULL || o_naws.state != ACTIVE)
return;
b[0] = IAC; b[1] = SB; b[2] = TELOPT_NAWS;
b[3] = cols >> 8; b[4] = cols & 0xFF;
b[5] = rows >> 8; b[6] = rows & 0xFF;
b[7] = IAC; b[8] = SE;
- s_write (b, 9);
+ sk_write(s, b, 9);
sprintf(logbuf, "client:\tSB NAWS %d,%d",
((unsigned char)b[3] << 8) + (unsigned char)b[4],
((unsigned char)b[5] << 8) + (unsigned char)b[6]);
static void telnet_special (Telnet_Special code) {
unsigned char b[2];
- if (s == INVALID_SOCKET)
+ if (s == NULL)
return;
b[0] = IAC;
switch (code) {
- case TS_AYT: b[1] = AYT; s_write (b, 2); break;
- case TS_BRK: b[1] = BREAK; s_write (b, 2); break;
- case TS_EC: b[1] = EC; s_write (b, 2); break;
- case TS_EL: b[1] = EL; s_write (b, 2); break;
- case TS_GA: b[1] = GA; s_write (b, 2); break;
- case TS_NOP: b[1] = NOP; s_write (b, 2); break;
- case TS_ABORT: b[1] = ABORT; s_write (b, 2); break;
- case TS_AO: b[1] = AO; s_write (b, 2); break;
- case TS_IP: b[1] = IP; s_write (b, 2); break;
- case TS_SUSP: b[1] = SUSP; s_write (b, 2); break;
- case TS_EOR: b[1] = EOR; s_write (b, 2); break;
- case TS_EOF: b[1] = xEOF; s_write (b, 2); break;
+ case TS_AYT: b[1] = AYT; sk_write(s, b, 2); break;
+ case TS_BRK: b[1] = BREAK; sk_write(s, b, 2); break;
+ case TS_EC: b[1] = EC; sk_write(s, b, 2); break;
+ case TS_EL: b[1] = EL; sk_write(s, b, 2); break;
+ case TS_GA: b[1] = GA; sk_write(s, b, 2); break;
+ case TS_NOP: b[1] = NOP; sk_write(s, b, 2); break;
+ case TS_ABORT: b[1] = ABORT; sk_write(s, b, 2); break;
+ case TS_AO: b[1] = AO; sk_write(s, b, 2); break;
+ case TS_IP: b[1] = IP; sk_write(s, b, 2); break;
+ case TS_SUSP: b[1] = SUSP; sk_write(s, b, 2); break;
+ case TS_EOR: b[1] = EOR; sk_write(s, b, 2); break;
+ case TS_EOF: b[1] = xEOF; sk_write(s, b, 2); break;
case TS_SYNCH:
- outbuf_head = outbuf_reap = 0;
- b[1] = DM;
- send (s, b, 2, MSG_OOB);
- break;
+ b[1] = DM;
+ sk_write (s, b, 1);
+ sk_write_oob (s, b+1, 1);
+ break;
case TS_RECHO:
if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) {
o_echo.state = REQUESTED;
case TS_PING:
if (o_they_sga.state == ACTIVE) {
b[1] = NOP;
- s_write (b, 2);
+ sk_write(s, b, 2);
}
break;
}
}
-static SOCKET telnet_socket(void) { return s; }
+static Socket telnet_socket(void) { return s; }
static int telnet_sendok(void) { return 1; }
Backend telnet_backend = {
telnet_init,
- telnet_msg,
telnet_send,
telnet_size,
telnet_special,
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include <stdlib.h>
}
void term_paste() {
-static long last_paste = 0;
+ static long last_paste = 0;
long now, paste_diff;
if(paste_len == 0) return;
while(paste_pos<paste_len)
{
- char c = paste_buffer[paste_pos++];
- ldisc->send (&c, 1);
+ int n = 0;
+ while (n + paste_pos < paste_len) {
+ if (paste_buffer[paste_pos + n++] == '\r')
+ break;
+ }
+ ldisc->send (paste_buffer+paste_pos, n);
+ paste_pos += n;
- if (c =='\r') {
+ if (paste_pos < paste_len) {
paste_hold = 1;
return;
}
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include <stdlib.h>
return 1;
}
/* WISHLIST: maybe allow config tweaking even if winsock not present? */
+ sk_init();
InitCommonControls();
char msg[1024], *title;
char *realhost;
- error = back->init (hwnd, cfg.host, cfg.port, &realhost);
+ error = back->init (cfg.host, cfg.port, &realhost);
if (error) {
sprintf(msg, "Unable to open connection:\n%s", error);
MessageBox(NULL, msg, "PuTTY Error", MB_ICONERROR | MB_OK);
}
/*
+ * Set up, or shut down, an AsyncSelect. Called from winnet.c.
+ */
+char *do_select(SOCKET skt, int startup) {
+ int msg, events;
+ if (startup) {
+ msg = WM_NETEVENT;
+ events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE;
+ } else {
+ msg = events = 0;
+ }
+ if (!hwnd)
+ return "do_select(): internal error (hwnd==NULL)";
+ if (WSAAsyncSelect (skt, hwnd, msg, events) == SOCKET_ERROR) {
+ switch (WSAGetLastError()) {
+ case WSAENETDOWN: return "Network is down";
+ default: return "WSAAsyncSelect(): unknown error";
+ }
+ }
+ return NULL;
+}
+
+/*
* Print a message box and close the connection.
*/
void connection_fatal(char *fmt, ...) {
* Actually do the job requested by a WM_NETEVENT
*/
static void enact_pending_netevent(void) {
- int i;
static int reentering = 0;
+ extern int select_result(WPARAM, LPARAM);
+ int ret;
if (reentering)
return; /* don't unpend the pending */
pending_netevent = FALSE;
reentering = 1;
- i = back->msg (pend_netevent_wParam, pend_netevent_lParam);
+ ret = select_result (pend_netevent_wParam, pend_netevent_lParam);
reentering = 0;
- if (i < 0) {
- char buf[1024];
- switch (WSABASEERR + (-i) % 10000) {
- case WSAECONNRESET:
- sprintf(buf, "Connection reset by peer");
- break;
- case WSAECONNABORTED:
- sprintf(buf, "Connection aborted");
- break;
- default:
- sprintf(buf, "Unexpected network error %d", -i);
- break;
- }
- connection_fatal(buf);
- }
- if (i <= 0) {
+ if (ret == 0) {
if (cfg.close_on_exit)
PostQuitMessage(0);
else {
*/
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"
#include "storage.h"
#include <windows.h>
-#ifndef AUTO_WINSOCK
-#ifdef WINSOCK_TWO
-#include <winsock2.h>
-#else
-#include <winsock.h>
-#endif
-#endif
#include <stdio.h>
#include "putty.h"