From: Ben Harris Date: Sun, 4 Apr 1999 18:23:35 +0000 (+0000) Subject: Lots of MacTCP networking stuff. I think all the code's written, but it X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=0256bceeced72bcd64904584ab50149f6976ee1f;p=PuTTY.git Lots of MacTCP networking stuff. I think all the code's written, but it doesn't actually work yet. Also the telnet backend is still single-session, and I haven't even touched the ssh one. Oh, and the "Main" segment just overflowed 32k, so we have extra linker incantations. I'm off to the pub now. [originally from svn r156] --- diff --git a/Makefile.mpw b/Makefile.mpw index 61d1c7c5..b08c1789 100644 --- a/Makefile.mpw +++ b/Makefile.mpw @@ -1,4 +1,4 @@ -# $Id: Makefile.mpw,v 1.1.2.11 1999/04/03 21:53:29 ben Exp $ +# $Id: Makefile.mpw,v 1.1.2.12 1999/04/04 18:23:33 ben Exp $ # This is the Makefile for building PuTTY for the Mac OS. # Users of non-Mac systems will see some pretty strange characters around. @@ -13,8 +13,10 @@ COptions = {Includes} {Sym PPCCOptions = {Includes} {Sym¥PPC} -w 35 Objects¥68K = ¶ + dnr.c.o ¶ mac.c.o ¶ maccfg.c.o ¶ + macnet.c.o ¶ macterm.c.o ¶ misc.c.o ¶ # ssh.c.o ¶ @@ -24,13 +26,15 @@ Objects # sshrand.c.o ¶ # sshrsa.c.o ¶ # sshsha.c.o ¶ -# telnet.c.o ¶ + telnet.c.o ¶ terminal.c.o ¶ testback.c.o Objects¥PPC = ¶ + dnr.c.x ¶ mac.c.x ¶ maccfg.c.x ¶ + macnet.c.x ¶ macterm.c.x ¶ misc.c.x ¶ # ssh.c.x ¶ @@ -40,7 +44,7 @@ Objects # sshrand.c.x ¶ # sshrsa.c.x ¶ # sshsha.c.x ¶ -# telnet.c.x ¶ + telnet.c.x ¶ terminal.c.x ¶ testback.c.x @@ -89,11 +93,13 @@ PuTTY.68k ILink ¶ -o {Targ} {Sym¥68K} ¶ -t 'APPL' -c 'pTTY' ¶ + -br 68k -model far ¶ -newerdeps {NewerDeps} ELSE ILink ¶ -o {Targ} {Sym¥68K} ¶ -t 'APPL' -c 'pTTY' ¶ + -br 68k -model far¶ {Objects¥68K} ¶ {Libs¥68K} END @@ -118,6 +124,7 @@ PuTTY setfile -t XCOF {Targ} {PPCC} {default}.c -o {Targ} {PPCCOptions} +dnr.c.o dnr.c.x Ä mac.c.o mac.c.x Ä putty.h mac.h macresid.h maccfg.c.o maccfg.c.x Ä putty.h mac.h macresid.h macnet.c.o macnet.c.x Ä putty.h diff --git a/mac.c b/mac.c index d90fc375..2d43626e 100644 --- a/mac.c +++ b/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.1.2.23 1999/04/02 12:58:02 ben Exp $ */ +/* $Id: mac.c,v 1.1.2.24 1999/04/04 18:23:33 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -159,6 +159,7 @@ static void mac_eventloop(void) { mac_adjustcursor(cursrgn); if (gotevent) mac_event(&event); + macnet_eventcheck(); } DisposeRgn(cursrgn); } diff --git a/mac.h b/mac.h index 335f3f86..f6a3c9f6 100644 --- a/mac.h +++ b/mac.h @@ -30,6 +30,8 @@ extern void mac_keyterm(WindowPtr, EventRecord *); extern void mac_menuterm(WindowPtr, short, short); /* from maccfg.c */ extern void mac_loadconfig(Config *); +/* from macnet.c */ +extern void macnet_eventcheck(void); #endif diff --git a/macnet.c b/macnet.c index 059bb9e2..7f21ba68 100644 --- a/macnet.c +++ b/macnet.c @@ -1,4 +1,4 @@ -/* $Id: macnet.c,v 1.1.2.2 1999/04/03 21:53:29 ben Exp $ */ +/* $Id: macnet.c,v 1.1.2.3 1999/04/04 18:23:34 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -73,21 +73,17 @@ typedef struct Socket { TCPiopb spareiopb; /* for closing etc */ hostInfo hostinfo; int port; -// unsigned char *inbuf; -// int inbuf_head, inbuf_reap, inbuf_size; -// unsigned char *outbuf; -// int outbuf_head, outbuf_reap, outbuf_size; ProcessSerialNumber psn; Session *s; - UInt32 a5; - qHdr sendq; /* Blocks waiting to be sent */ - qHdr freeq; /* Blocks sent, waiting to be freed */ + long a5; + QHdr sendq; /* Blocks waiting to be sent */ } Socket; typedef struct { QElem qelem; int flags; - int len; + wdsEntry wds; + short wdsterm; } Send_Buffer; /* @@ -112,9 +108,11 @@ static int mtcp_initted = FALSE; static OSErr macnet_init(void); static pascal void macnet_resolved(hostInfo *, char *); -static void macnet_opened(TCPiopb*); -static void macnet_sent(TCPiopb*); -static void macnet_closed(TCPiopb*); +static void macnet_completed_open(TCPiopb*); +static void macnet_completed_send(TCPiopb*); +static void macnet_sent(Socket *); +static void macnet_startsend(Socket *); +static void macnet_completed_close(TCPiopb*); static pascal void macnet_asr(StreamPtr, unsigned short, Ptr, unsigned short, ICMPReport *); static void macnet_sendevent(Socket *, Net_Event_Type); @@ -122,21 +120,22 @@ static void macnet_sendevent(Socket *, Net_Event_Type); #if TARGET_RT_MAC_CFM static RoutineDescriptor macnet_resolved_upp = BUILD_ROUTINE_DESCRIPTOR(uppResultProcInfo, (ProcPtr)macnet_resolved); -static RoutineDescriptor macnet_opened_upp = +static RoutineDescriptor macnet_completed_open_upp = BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo, - (ProcPtr)macnet_opened); -static RoutineDescriptor macnet_sent_upp = - BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo, (ProcPtr)macnet_sent); -static RoutineDescriptor macnet_closed_upp = + (ProcPtr)macnet_completed_open); +static RoutineDescriptor macnet_complete_send_upp = BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo, - (ProcPtr)macnet_closed); + (ProcPtr)macnet_completed_send); +static RoutineDescriptor macnet_completed_close_upp = + BUILD_ROUTINE_DESCRIPTOR(uppTCPIOCompletionProcInfo, + (ProcPtr)macnet_completed_close); static RoutineDescriptor macnet_asr_upp = BUILD_ROUTINE_DESCRIPTOR(uppTCPNotifyProcInfo, (ProcPtr)macnet_asr); #else #define macnet_resolved_upp macnet_resolved -#define macnet_opened_upp macnet_opened -#define macnet_sent_upp macnet_sent -#define macnet_closed_upp macnet_closed +#define macnet_completed_open_upp macnet_completed_open +#define macnet_completed_send_upp macnet_completed_send +#define macnet_completed_close_upp macnet_completed_close #define macnet_asr_upp macnet_asr #endif @@ -153,13 +152,18 @@ static OSErr macnet_init(void) { NetEvent *eventblock; int i; + /* + * FIXME: This is hideously broken, in that we're meant to faff + * with unit numbers and stuff, and we blatantly don't. + */ err = opendriver(".IPP", &mtcp_refnum); if (err != noErr) return err; err = OpenResolver(NULL); if (err != noErr) return err; - /* Set up the event queues, and fill the free queue with events */ + /* Set up the event queues, and fill the free queue with events + */ macnet_eventq.qFlags = 0; macnet_eventq.qHead = macnet_eventq.qTail = NULL; macnet_freeq.qFlags = 0; @@ -168,6 +172,7 @@ static OSErr macnet_init(void) { for (i = 0; i < NUM_EVENTS; i++) Enqueue(&eventblock[i].qelem, &macnet_freeq); mtcp_initted = TRUE; + return 0; } Socket *net_open(Session *s, char *host, int port) { @@ -217,9 +222,11 @@ Socket *net_open(Session *s, char *host, int port) { static pascal void macnet_resolved(hostInfo *hi, char *cookie) { Socket *sock = (Socket *)cookie; OSErr err; - UInt32 olda5; +#if !TARGET_RT_CFM + long olda5; olda5 = SetA5(sock->a5); +#endif /* * We've resolved a name, so now we'd like to connect to it (or * report an error). @@ -227,7 +234,7 @@ static pascal void macnet_resolved(hostInfo *hi, char *cookie) { switch (sock->hostinfo.rtnCode) { case noErr: /* Open a connection */ - sock->iopb.ioCompletion = macnet_opened_upp; + sock->iopb.ioCompletion = macnet_completed_open_upp; sock->iopb.csCode = TCPActiveOpen; sock->iopb.csParam.open.validityFlags = typeOfService; sock->iopb.csParam.open.commandTimeoutValue = 0; /* unused */ @@ -249,14 +256,18 @@ static pascal void macnet_resolved(hostInfo *hi, char *cookie) { macnet_sendevent(sock, NE_NOHOST); break; } +#if !TARGET_RT_CFM SetA5(olda5); +#endif } -static void macnet_opened(TCPiopb *iopb) { +static void macnet_completed_open(TCPiopb *iopb) { Socket *sock = (Socket *)iopb->csParam.open.userDataPtr; - UInt32 olda5; +#if !TARGET_RT_CFM + long olda5; olda5 = SetA5(sock->a5); +#endif switch (iopb->ioResult) { case noErr: macnet_sendevent(sock, NE_OPEN); @@ -265,16 +276,20 @@ static void macnet_opened(TCPiopb *iopb) { macnet_sendevent(sock, NE_NOOPEN); break; } +#if !TARGET_RT_CFM SetA5(olda5); +#endif } static pascal void macnet_asr(StreamPtr tcpstream, unsigned short eventcode, Ptr cookie, unsigned short terminreason, ICMPReport *icmpmsg) { Socket *sock = (Socket *)cookie; - UInt32 olda5; +#if !TARGET_RT_CFM + long olda5; olda5 = SetA5(sock->a5); +#endif switch (eventcode) { case TCPClosing: macnet_sendevent(sock, NE_CLOSING); @@ -306,23 +321,87 @@ static pascal void macnet_asr(StreamPtr tcpstream, unsigned short eventcode, } break; } +#if !TARGET_RT_CFM SetA5(olda5); +#endif } /* * Send a block of data. */ -int net_send(Socket *sock, void *buf, int buflen, int flags) {{ +int net_send(Socket *sock, void *buf, int buflen, int flags) { OSErr err; Send_Buffer *buff; buff = smalloc(sizeof(Send_Buffer) + buflen); buff->flags = flags; - buff->len = buflen; - memcpy(buff + 1, buf, buflen); + buff->wds.length = buflen; + buff->wds.ptr = (Ptr)&buff[1]; /* after the end of the struct */ + buff->wdsterm = 0; + memcpy(&buff[1], buf, buflen); Enqueue(&buff->qelem, &sock->sendq); - macnet_start(sock); + /* Kick off the transmit if the queue was empty */ + if (sock->sendq.qHead == &buff->qelem) + macnet_startsend(sock); +} + +/* + * This is called once every time round the event loop to check for + * network events and handle them. + */ +void macnet_eventcheck() { + NetEvent *ne; + + if (!mtcp_initted) + return; + ne = (NetEvent *)macnet_eventq.qHead; + if (ne == NULL) + return; + Dequeue(&ne->qelem, &macnet_eventq); + switch (ne->type) { + case NE_SENT: + macnet_sent(ne->sock); + break; + default: + (ne->sock->s->back->msg)(ne->sock->s, ne->sock, ne->type); + break; + } + Enqueue(&ne->qelem, &macnet_freeq); +} + +/* + * The block at the head of the send queue has finished sending, so we + * can free it. Kick off the next transmission if there is one. + */ +static void macnet_sent(Socket *sock) { + Send_Buffer *buff; + + assert(sock->sendq.qHead != NULL); + buff = (Send_Buffer *)sock->sendq.qHead; + Dequeue(&buff->qelem, &sock->sendq); + sfree(buff); + if (sock->sendq.qHead != NULL) + macnet_startsend(sock); +} + +/* + * There's a block on the head of the send queue which needs to be + * sent. + */ + +static void macnet_startsend(Socket *sock) { + Send_Buffer *buff; + OSErr err; + + buff = (Send_Buffer *)sock->sendq.qHead; + sock->iopb.csCode = TCPSend; + sock->iopb.csParam.send.validityFlags = 0; + sock->iopb.csParam.send.pushFlag = buff->flags & SEND_PUSH ? true : false; + sock->iopb.csParam.send.urgentFlag = buff->flags & SEND_URG ? true : false; + sock->iopb.csParam.send.wdsPtr = (Ptr)&buff->wds; + sock->iopb.csParam.send.userDataPtr = (char *)sock; + err = PBControlAsync((ParmBlkPtr)&sock->iopb); } int net_recv(Socket *sock, void *buf, int buflen, int flags) { @@ -331,7 +410,8 @@ int net_recv(Socket *sock, void *buf, int buflen, int flags) { int avail, want, got; memcpy(&iopb, &sock->iopb, sizeof(TCPiopb)); - /* Work out if there's anything to recieve (we don't want to block) */ + /* Work out if there's anything to recieve (we don't want to block) + */ iopb.csCode = TCPStatus; err = PBControlSync((ParmBlkPtr)&iopb); if (err != noErr) @@ -341,12 +421,12 @@ int net_recv(Socket *sock, void *buf, int buflen, int flags) { return 0; want = avail < buflen ? avail : buflen; iopb.csCode = TCPRcv; - iopb.csParam.receive.buffPtr = buf; - iopb.csParam.receive.buffLen = want; + iopb.csParam.receive.rcvBuff = buf; + iopb.csParam.receive.rcvBuffLen = want; err = PBControlSync((ParmBlkPtr)&iopb); if (err != noErr) return 0; - return iopb.csParam.receive.buffLen; + return iopb.csParam.receive.rcvBuffLen; } @@ -360,7 +440,7 @@ void net_close(Socket *sock) { * free it, which we can't do at interrupt time). */ memcpy(&sock->spareiopb, &sock->iopb, sizeof(TCPiopb)); - sock->spareiopb.ioCompletion = macnet_closed_upp; + sock->spareiopb.ioCompletion = macnet_completed_close_upp; sock->spareiopb.csCode = TCPClose; sock->spareiopb.csParam.close.validityFlags = 0; sock->spareiopb.csParam.close.userDataPtr = (char *)sock; @@ -376,11 +456,13 @@ void net_close(Socket *sock) { } } -static void macnet_closed(TCPiopb* iopb) { +static void macnet_completed_close(TCPiopb* iopb) { Socket *sock = (Socket *)iopb->csParam.close.userDataPtr; - UInt32 olda5; +#if !TARGET_RT_CFM + long olda5; olda5 = SetA5(sock->a5); +#endif switch (iopb->ioResult) { case noErr: macnet_sendevent(sock, NE_CLOSED); @@ -392,7 +474,9 @@ static void macnet_closed(TCPiopb* iopb) { macnet_sendevent(sock, NE_DIED); break; } +#if !TARGET_RT_CFM SetA5(olda5); +#endif } /* diff --git a/macterm.c b/macterm.c index 84d88969..39a0d9b7 100644 --- a/macterm.c +++ b/macterm.c @@ -1,4 +1,4 @@ -/* $Id: macterm.c,v 1.1.2.33 1999/03/30 19:44:51 ben Exp $ */ +/* $Id: macterm.c,v 1.1.2.34 1999/04/04 18:23:34 ben Exp $ */ /* * Copyright (c) 1999 Simon Tatham * Copyright (c) 1999 Ben Harris @@ -140,7 +140,7 @@ void mac_newsession(void) { s = smalloc(sizeof(*s)); memset(s, 0, sizeof(*s)); mac_loadconfig(&s->cfg); - s->back = &hexdump_backend; + s->back = &telnet_backend; /* XXX: Own storage management? */ if (mac_gestalts.qdvers == gestaltOriginalQD) @@ -158,11 +158,12 @@ void mac_newsession(void) { SetPalette(s->window, s->palette, TRUE); ActivatePalette(s->window); ShowWindow(s->window); - starttime = TickCount(); - display_resource(s, 'pTST', 128); - sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime); - inbuf_putstr(s, msg); - term_out(s); + s->back->init(s); +/* starttime = TickCount(); */ +/* display_resource(s, 'pTST', 128); */ +/* sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime); */ +/* inbuf_putstr(s, msg); */ +/* term_out(s); */ } static void mac_initfont(Session *s) { @@ -1011,6 +1012,11 @@ void do_scroll(Session *s, int topline, int botline, int lines) { DisposeRgn(update); } +void lognegot(/*Session *s,*/ const char *str) { + + /* XXX Do something */ +} + /* * Emacs magic: * Local Variables: diff --git a/putty.h b/putty.h index 3681de53..5b5aa17f 100644 --- a/putty.h +++ b/putty.h @@ -102,6 +102,7 @@ typedef enum { NE_NOOPEN, /* Connection failed to open for some other reason */ NE_DATA, /* Incoming normal data */ NE_URGENT, /* Incoming urgent data */ + NE_SENT, /* Used internally by Mac network stack */ NE_CLOSING, /* Connection closed by remote host */ NE_CLOSED, /* Connection close completed */ NE_TIMEOUT, /* Remote host vanished */ @@ -109,10 +110,14 @@ typedef enum { NE_DIED, /* Connection has failed for some other reason */ } Net_Event_Type; +#ifdef macintosh +typedef Socket *SOCKET; +#define INVALID_SOCKET NULL +#endif typedef struct { - char *(*init) (Session *, char *host, int port); - int (*msg)(Session *, Socket *, Net_Event_Type); + char *(*init) (Session *); + int (*msg)(Session *, SOCKET, Net_Event_Type); void (*send) (Session *, char *buf, int len); void (*size) (Session *); void (*special) (Session *, Telnet_Special code); @@ -281,14 +286,15 @@ extern void pre_paint(Session *); extern void post_paint(Session *); extern void palette_set(Session *, int, int, int, int); extern void palette_reset(Session *); -void write_clip (void *, int); -void get_clip (void **, int *); +extern void write_clip (void *, int); +extern void get_clip (void **, int *); extern void do_scroll(Session *, int, int, int); -void fatalbox (const char *, ...); +extern void fatalbox(const char *, ...); #ifdef macintosh #pragma noreturn (fatalbox) #endif -extern void beep (Session *s); +extern void beep(Session *s); +extern void lognegot(const char *); /* * Exports from the network system @@ -298,6 +304,8 @@ extern Socket *net_open(Session *, char *host, int port); extern char *net_realname(Socket *); extern int net_recv(Socket *, void *, int, int); extern int net_send(Socket *, void *, int, int); +#define SEND_PUSH 0x01 +#define SEND_URG 0x02 extern void net_close(Socket *); /* ask the remote end to close */ extern void net_destroy(Socket *); /* Tidy up */ diff --git a/telnet.c b/telnet.c index 26cb9180..5b40eda3 100644 --- a/telnet.c +++ b/telnet.c @@ -1,15 +1,17 @@ #ifdef macintosh -#include #else /* not macintosh */ #include #include #endif /* not macintosh */ #include #include +#include #include "putty.h" static SOCKET s = INVALID_SOCKET; +/* kludge till we decide where to put telnet state */ +static Session *sess; #define IAC 255 /* interpret as command: */ #define DONT 254 /* you are not to use option */ @@ -102,7 +104,7 @@ static char *telopt(int opt) { return ""; } -static void telnet_size(void); +static void telnet_size(Session *ignored); struct Opt { int send; /* what we initially send */ @@ -135,19 +137,19 @@ static int in_synch; #endif static int sb_opt, sb_len; -static char *sb_buf = NULL; +static unsigned char *sb_buf = NULL; 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; + while (sess->outbuf_head != sess->outbuf_reap) { + int end = (sess->outbuf_reap < sess->outbuf_head ? sess->outbuf_head : OUTBUF_SIZE); + int len = end - sess->outbuf_reap; int ret; - ret = send (s, outbuf+outbuf_reap, len, 0); + ret = net_send (s, sess->outbuf+sess->outbuf_reap, len, 0); if (ret > 0) - outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK; + sess->outbuf_reap = (sess->outbuf_reap + ret) & OUTBUF_MASK; if (ret < len) return; } @@ -156,10 +158,10 @@ static void try_write (void) { 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; + int new_head = (sess->outbuf_head + 1) & OUTBUF_MASK; + if (new_head != sess->outbuf_reap) { + sess->outbuf[sess->outbuf_head] = *p++; + sess->outbuf_head = new_head; } } try_write(); @@ -167,11 +169,11 @@ static void s_write (void *buf, int len) { static void c_write (char *buf, int len) { while (len--) { - int new_head = (inbuf_head + 1) & INBUF_MASK; + int new_head = (sess->inbuf_head + 1) & INBUF_MASK; int c = (unsigned char) *buf; - if (new_head != inbuf_reap) { - inbuf[inbuf_head] = *buf++; - inbuf_head = new_head; + if (new_head != sess->inbuf_reap) { + sess->inbuf[sess->inbuf_head] = *buf++; + sess->inbuf_head = new_head; } } } @@ -201,7 +203,7 @@ static void deactivate_option (struct Opt *o) { static void activate_option (struct Opt *o) { if (o->send == WILL && o->option == TELOPT_NAWS) - telnet_size(); + telnet_size(sess); if (o->send == WILL && (o->option == TELOPT_NEW_ENVIRON || o->option == TELOPT_OLD_ENVIRON)) { @@ -276,27 +278,27 @@ static void process_subneg (void) { switch (sb_opt) { case TELOPT_TSPEED: if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) { - char logbuf[sizeof(cfg.termspeed)+80]; + char logbuf[sizeof(sess->cfg.termspeed)+80]; b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED; b[3] = TELQUAL_IS; - strcpy(b+4, cfg.termspeed); - n = 4 + strlen(cfg.termspeed); + strcpy((char *)b+4, sess->cfg.termspeed); + n = 4 + strlen(sess->cfg.termspeed); b[n] = IAC; b[n+1] = SE; s_write (b, n+2); lognegot("server:\tSB TSPEED SEND"); - sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed); + sprintf(logbuf, "client:\tSB TSPEED IS %s", sess->cfg.termspeed); lognegot (logbuf); } else lognegot ("server:\tSB TSPEED "); break; case TELOPT_TTYPE: if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) { - char logbuf[sizeof(cfg.termtype)+80]; + char logbuf[sizeof(sess->cfg.termtype)+80]; b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE; b[3] = TELQUAL_IS; - for (n = 0; cfg.termtype[n]; n++) - b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ? - cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]); + for (n = 0; sess->cfg.termtype[n]; n++) + b[n+4] = (sess->cfg.termtype[n] >= 'a' && sess->cfg.termtype[n] <= 'z' ? + sess->cfg.termtype[n] + 'A'-'a' : sess->cfg.termtype[n]); b[n+4] = IAC; b[n+5] = SE; s_write (b, n+6); b[n+4] = 0; @@ -316,7 +318,7 @@ static void process_subneg (void) { sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt)); lognegot (logbuf); if (sb_opt == TELOPT_OLD_ENVIRON) { - if (cfg.rfc_environ) { + if (sess->cfg.rfc_environ) { value = RFC_VALUE; var = RFC_VAR; } else { @@ -347,7 +349,7 @@ static void process_subneg (void) { b[0] = IAC; b[1] = SB; b[2] = sb_opt; b[3] = TELQUAL_IS; n = 4; - e = cfg.environmt; + e = sess->cfg.environmt; while (*e) { b[n++] = var; while (*e && *e != '\t') b[n++] = *e++; @@ -356,10 +358,10 @@ static void process_subneg (void) { while (*e) b[n++] = *e++; e++; } - if (*cfg.username) { + if (*sess->cfg.username) { b[n++] = var; b[n++] = 'U'; b[n++] = 'S'; b[n++] = 'E'; b[n++] = 'R'; b[n++] = value; - e = cfg.username; + e = sess->cfg.username; while (*e) b[n++] = *e++; } b[n++] = IAC; b[n++] = SE; @@ -373,9 +375,9 @@ static void process_subneg (void) { } static enum { - TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT, + TELNET_TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT, SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR -} telnet_state = TOPLEVEL; +} telnet_state = TELNET_TOPLEVEL; static void do_telnet_read (char *buf, int len) { unsigned char b[10]; @@ -384,10 +386,10 @@ static void do_telnet_read (char *buf, int len) { int c = (unsigned char) *buf++; switch (telnet_state) { - case TOPLEVEL: + case TELNET_TOPLEVEL: case SEENCR: if (c == NUL && telnet_state == SEENCR) - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; else if (c == IAC) telnet_state = SEENIAC; else { @@ -395,11 +397,11 @@ static void do_telnet_read (char *buf, int len) { #if 0 if (!in_synch) #endif - c_write (b, 1); + c_write ((char *)b, 1); if (c == CR) telnet_state = SEENCR; else - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; } break; case SEENIAC: @@ -408,23 +410,23 @@ static void do_telnet_read (char *buf, int len) { else if (c == WILL) telnet_state = SEENWILL; else if (c == WONT) telnet_state = SEENWONT; else if (c == SB) telnet_state = SEENSB; - else telnet_state = TOPLEVEL;/* ignore _everything_ else! */ + else telnet_state = TELNET_TOPLEVEL;/* ignore _everything_ else! */ break; case SEENWILL: proc_rec_opt (WILL, c); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; break; case SEENWONT: proc_rec_opt (WONT, c); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; break; case SEENDO: proc_rec_opt (DO, c); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; break; case SEENDONT: proc_rec_opt (DONT, c); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; break; case SEENSB: sb_opt = c; @@ -437,7 +439,7 @@ static void do_telnet_read (char *buf, int len) { else { subneg_addchar: if (sb_len >= sb_size) { - char *newbuf; + unsigned char *newbuf; sb_size += SB_DELTA; newbuf = (sb_buf ? realloc(sb_buf, sb_size) : @@ -457,7 +459,7 @@ static void do_telnet_read (char *buf, int len) { goto subneg_addchar; /* yes, it's a hack, I know, but... */ else { process_subneg(); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; } break; } @@ -471,84 +473,11 @@ static void do_telnet_read (char *buf, int len) { * * 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 (Session *this_sess) { - /* - * 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); - - 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"; - } - -#if 0 - { - BOOL b = TRUE; - setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b)); - } -#endif - - /* - * 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 (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"; - } + sess = this_sess; + s = net_open(sess, sess->cfg.host, sess->cfg.port); /* * Initialise option states. @@ -575,23 +504,18 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) { * 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) { +static int telnet_msg (Session *sess, SOCKET sock, Net_Event_Type ne) { int ret; char buf[256]; if (s == INVALID_SOCKET) /* how the hell did we get here?! */ return -5000; - if (WSAGETSELECTERROR(lParam) != 0) - return -WSAGETSELECTERROR(lParam); - - switch (WSAGETSELECTEVENT(lParam)) { - case FD_READ: - ret = recv(s, buf, sizeof(buf), 0); - if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) - return 1; + switch (ne) { + case NE_DATA: + ret = net_recv(s, buf, sizeof(buf), 0); if (ret < 0) /* any _other_ error */ - return -10000-WSAGetLastError(); + return -1; if (ret == 0) { s = INVALID_SOCKET; return 0; /* can't happen, in theory */ @@ -608,24 +532,20 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) { #endif do_telnet_read (buf, ret); return 1; - case FD_OOB: + case NE_URGENT: do { - ret = recv(s, buf, sizeof(buf), 0); + ret = net_recv(s, buf, sizeof(buf), 0); } while (ret > 0); - telnet_state = TOPLEVEL; + telnet_state = TELNET_TOPLEVEL; do { - ret = recv(s, buf, 1, MSG_OOB); + ret = net_recv(s, buf, 1, /*MSG_OOB*/ 0); if (ret > 0) do_telnet_read (buf, ret); } while (ret > 0); - if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) - return -30000-WSAGetLastError(); - return 1; - case FD_WRITE: - if (outbuf_head != outbuf_reap) - try_write(); + if (ret < 0) + return -3; return 1; - case FD_CLOSE: + case NE_CLOSING: s = INVALID_SOCKET; return 0; } @@ -635,7 +555,7 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) { /* * Called to send data down the Telnet connection. */ -static void telnet_send (char *buf, int len) { +static void telnet_send (Session *this_sess, char *buf, int len) { char *p; static unsigned char iac[2] = { IAC, IAC }; static unsigned char cr[2] = { CR, NUL }; @@ -660,15 +580,15 @@ static void telnet_send (char *buf, int len) { /* * Called to set the size of the window from Telnet's POV. */ -static void telnet_size(void) { +static void telnet_size(Session *sess) { unsigned char b[16]; char logbuf[50]; if (s == INVALID_SOCKET || 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[3] = sess->cols >> 8; b[4] = sess->cols & 0xFF; + b[5] = sess->rows >> 8; b[6] = sess->rows & 0xFF; b[7] = IAC; b[8] = SE; s_write (b, 9); sprintf(logbuf, "client:\tSB NAWS %d,%d", @@ -680,7 +600,7 @@ static void telnet_size(void) { /* * Send Telnet special codes. */ -static void telnet_special (Telnet_Special code) { +static void telnet_special (Session *sess, Telnet_Special code) { unsigned char b[2]; if (s == INVALID_SOCKET) @@ -701,9 +621,9 @@ static void telnet_special (Telnet_Special code) { case TS_EOR: b[1] = EOR; s_write (b, 2); break; case TS_EOF: b[1] = xEOF; s_write (b, 2); break; case TS_SYNCH: - outbuf_head = outbuf_reap = 0; + sess->outbuf_head = sess->outbuf_reap = 0; b[0] = DM; - send (s, b, 1, MSG_OOB); + net_send (s, b, 1, SEND_URG); break; } } diff --git a/testback.c b/testback.c index fcfcd000..a0fcbf5a 100644 --- a/testback.c +++ b/testback.c @@ -1,4 +1,4 @@ -/* $Id: testback.c,v 1.1.2.5 1999/03/29 19:50:24 ben Exp $ */ +/* $Id: testback.c,v 1.1.2.6 1999/04/04 18:23:35 ben Exp $ */ /* * Copyright (c) 1999 Simon Tatham * Copyright (c) 1999 Ben Harris @@ -33,8 +33,8 @@ #include "putty.h" -static char *null_init(Session *, char *, int, char **); -static int null_msg(Session *); +static char *null_init(Session *); +static int null_msg(Session *, Socket *, Net_Event_Type); static void null_send(Session *, char *, int); static void loop_send(Session *, char *, int); static void hexdump_send(Session *, char *, int); @@ -53,12 +53,12 @@ Backend hexdump_backend = { null_init, null_msg, hexdump_send, null_size, null_special }; -static char *null_init(Session *s, char *host, int port, char **realhost) { +static char *null_init(Session *s) { return NULL; } -static int null_msg(Session *s) { +static int null_msg(Session *s, Socket *sock, Net_Event_Type ne) { return 1; }