diff --git a/mac/README.mac b/mac/README.mac index a0c57ccc..7a305c67 100644 --- a/mac/README.mac +++ b/mac/README.mac @@ -1,4 +1,4 @@ -$Id: README.mac,v 1.7 2003/01/02 18:09:21 ben Exp $ +$Id: README.mac,v 1.8 2003/01/05 12:53:38 ben Exp $ Information about PuTTY for the Mac OS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -54,6 +54,7 @@ Known bugs: Features we need (and aren't entirely obvious): + * TCP urgent data. * Scroll-conflation -- scroll_display should change the in-memory display and remember the scroll, then do_scroll should be called only when scroll_display gets called for a different rectangle or diff --git a/mac/mac.c b/mac/mac.c index 8aac2ad3..9c1abdf8 100644 --- a/mac/mac.c +++ b/mac/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.18 2003/01/05 10:52:56 ben Exp $ */ +/* $Id: mac.c,v 1.19 2003/01/05 12:53:38 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -213,6 +213,7 @@ static void mac_eventloop(void) { mac_adjustcursor(cursrgn); if (gotevent) mac_event(&event); + mactcp_poll(); } DisposeRgn(cursrgn); } diff --git a/mac/mac.h b/mac/mac.h index a784a284..19e42dd6 100644 --- a/mac/mac.h +++ b/mac/mac.h @@ -88,6 +88,7 @@ extern void init_ucs(void); /* from mtcpnet.c */ extern OSErr mactcp_init(void); extern void mactcp_shutdown(void); +extern void mactcp_poll(void); #endif diff --git a/mac/mtcpnet.c b/mac/mtcpnet.c index cf38417e..d057dc4f 100644 --- a/mac/mtcpnet.c +++ b/mac/mtcpnet.c @@ -37,6 +37,7 @@ #include +#define DEFINE_PLUG_METHOD_MACROS #include "putty.h" #include "network.h" #include "mac.h" @@ -161,6 +162,8 @@ struct Socket_tag { int oobinline; int pending_error; /* in case send() returns error */ int listener; + struct Socket_tag *next; + struct Socket_tag **prev; }; /* @@ -184,6 +187,7 @@ static struct { Handle dnr_handle; int initialised; short refnum; + Actual_Socket socklist; } mactcp; static pascal void mactcp_lookupdone(struct hostInfo *hi, char *cookie); @@ -197,6 +201,8 @@ static void *mactcp_get_private_ptr(Socket); static char *mactcp_socket_error(Socket); static void mactcp_set_frozen(Socket, int); +static void mactcp_recv(Actual_Socket s, size_t len); + /* * Initialise MacTCP. * This should be called once before any TCP connection is opened. @@ -287,11 +293,16 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen) char mybuf[16]; OSErr err; - /* XXX only return first address */ - err = AddrToStr(addr->hostinfo.addr[0], mybuf); - buf[0] = '\0'; - if (err != noErr) - strncat(buf, mybuf, buflen - 1); + if (addr->resolved) { + /* XXX only return first address */ + err = AddrToStr(addr->hostinfo.addr[0], mybuf); + buf[0] = '\0'; + if (err != noErr) + strncat(buf, mybuf, buflen - 1); + } else { + buf[0] = '\0'; + strncat(buf, addr->hostname, buflen - 1); + } } /* I think "local" here really means "loopback" */ @@ -387,6 +398,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, ret->frozen_readable = 0; ret->localhost_only = 0; /* unused, but best init anyway */ ret->pending_error = 0; + ret->oobinline = oobinline; ret->oobpending = FALSE; ret->listener = 0; @@ -451,6 +463,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, ret->connected = TRUE; ret->writable = TRUE; + /* Add this to the list of all sockets */ + ret->next = mactcp.socklist; + ret->prev = &mactcp.socklist; + mactcp.socklist = ret; + fprintf(stderr, "Socket connected\n"); return (Socket)ret; } @@ -488,6 +505,12 @@ static void mactcp_close(Socket sock) s->err = PBControlSync((ParmBlkPtr)&pb); if (s->err == noErr) sfree(pb.csParam.create.rcvBuff); + + /* Unhitch from list of sockets */ + *s->prev = s->next; + if (s->next != NULL) + s->next->prev = s->prev; + sfree(s); } @@ -497,8 +520,6 @@ static int mactcp_write(Socket sock, char *buf, int len) wdsEntry wds[2]; TCPiopb pb; - fprintf(stderr, "Write data, %d bytes\n", len); - wds[0].length = len; wds[0].ptr = buf; wds[1].length = 0; @@ -521,6 +542,56 @@ static int mactcp_write_oob(Socket sock, char *buf, int len) fatalbox("mactcp_write_oob"); } +/* + * Called from our event loop if there's work to do. + */ +void mactcp_poll(void) +{ + Actual_Socket s; + TCPiopb pb; + + for (s = mactcp.socklist; s != NULL; s = s->next) { + /* XXX above can't handle sockets being deleted. */ + pb.ioCRefNum = mactcp.refnum; + pb.csCode = TCPStatus; + pb.tcpStream = s->s; + pb.csParam.status.userDataPtr = (Ptr)s; + s->err = PBControlSync((ParmBlkPtr)&pb); + if (s->err != noErr) + continue; + if (pb.csParam.status.amtUnreadData > 0) + mactcp_recv(s, pb.csParam.status.amtUnreadData); + /* Should check connectionState in case remote has closed */ + } +} + +static void mactcp_recv(Actual_Socket s, size_t len) +{ + rdsEntry rds[2]; + TCPiopb pb; + + if (s->frozen) return; + + while (len > 0) { + pb.ioCRefNum = mactcp.refnum; + pb.csCode = TCPNoCopyRcv; + pb.tcpStream = s->s; + pb.csParam.receive.commandTimeoutValue = 0; + pb.csParam.receive.rdsPtr = (Ptr)rds; + pb.csParam.receive.rdsLength = lenof(rds) - 1; + pb.csParam.receive.userDataPtr = (Ptr)s; + s->err = PBControlSync((ParmBlkPtr)&pb); + if (s->err != noErr) + return; + plug_receive(s->plug, 0, rds[0].ptr, rds[0].length); + len -= rds[0].length; + pb.csCode = TCPRcvBfrReturn; + s->err = PBControlSync((ParmBlkPtr)&pb); + if (s->err != noErr) + return; + } +} + /* * Each socket abstraction contains a `void *' private field in * which the client can keep state. @@ -589,8 +660,11 @@ static char *mactcp_socket_error(Socket sock) static void mactcp_set_frozen(Socket sock, int is_frozen) { + Actual_Socket s = (Actual_Socket) sock; - fatalbox("mactcp_set_frozen"); + if (s->frozen == is_frozen) + return; + s->frozen = is_frozen; } /*