* mtcpnet.c - MacTCP interface
*/
+#if !TARGET_API_MAC_CARBON
+
#include <MacTypes.h>
#include <Devices.h>
#include <Endian.h>
typedef STACK_UPP_TYPE(AddrToStrProcPtr) AddrToStrUPP;
enum { uppAddrToStrProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned long)))
- | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
+ | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32)))
+ | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
+ | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
};
#define InvokeAddrToStrUPP(selector, addr, addrStr, userUPP) \
CALL_THREE_PARAMETER_UPP((userUPP), uppAddrToStrProcInfo, (selector),\
/* End of AddressXlation.h bits */
+/* TCP connection states, mysteriously missing from <MacTCP.h> */
+#define TCPS_CLOSED 0
+#define TCPS_LISTEN 2
+#define TCPS_SYN_RECEIVED 4
+#define TCPS_SYN_SENT 6
+#define TCPS_ESTABLISHED 8
+#define TCPS_FIN_WAIT_1 10
+#define TCPS_FIN_WAIT_2 12
+#define TCPS_CLOSE_WAIT 14
+#define TCPS_CLOSING 16
+#define TCPS_LAST_ACK 18
+#define TCPS_TIME_WAIT 20
+
struct Socket_tag {
struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
Handle dnr_handle;
int initialised;
short refnum;
+ ProcessSerialNumber self;
Actual_Socket socklist;
} mactcp;
static pascal void mactcp_lookupdone(struct hostInfo *hi, char *cookie);
+static pascal void mactcp_asr(StreamPtr, unsigned short, Ptr, unsigned short,
+ struct ICMPReport *);
static Plug mactcp_plug(Socket, Plug);
static void mactcp_flush(Socket);
static void mactcp_close(Socket);
-static int mactcp_write(Socket, char *, int);
-static int mactcp_write_oob(Socket, char *, int);
+static int mactcp_write(Socket, char const *, int);
+static int mactcp_write_oob(Socket, char const*, int);
static void mactcp_set_private_ptr(Socket, void *);
static void *mactcp_get_private_ptr(Socket);
-static char *mactcp_socket_error(Socket);
+static const char *mactcp_socket_error(Socket);
static void mactcp_set_frozen(Socket, int);
static void mactcp_recv(Actual_Socket s, size_t len);
return noErr;
}
-void mactcp_shutdown(void)
+void mactcp_cleanup(void)
{
+ Actual_Socket s, next;
+
+ /*
+ * Eventually, PuTTY should close down each session as it exits,
+ * so there should be no sockets left when we get here. Still,
+ * better safe than sorry.
+ *
+ * XXX What about in-flight aync I/O (when we support that)?
+ */
+ for (s = mactcp.socklist; s != NULL; s = next) {
+ next = s->next; /* s is about to vanish */
+ mactcp_close(&s->fn);
+ }
+ /*
+ * When we get async DNS, we have to wait for any outstanding
+ * requests to complete here before exiting.
+ */
CloseResolver();
mactcp.initialised = FALSE;
}
static ResultUPP mactcp_lookupdone_upp;
-SockAddr sk_namelookup(char *host, char **canonicalname)
+SockAddr mactcp_namelookup(char const *host, char **canonicalname)
{
- SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
+ SockAddr ret = snew(struct SockAddr_tag);
OSErr err;
volatile int done = FALSE;
char *realhost;
+ int realhostlen;
- fprintf(stderr, "Resolving %s...\n", host);
/* Clear the structure. */
memset(ret, 0, sizeof(struct SockAddr_tag));
if (mactcp_lookupdone_upp == NULL)
mactcp_lookupdone_upp = NewResultUPP(&mactcp_lookupdone);
- err = StrToAddr(host, &ret->hostinfo, mactcp_lookupdone_upp,
+ /* Casting away const -- hope StrToAddr is sensible */
+ err = StrToAddr((char *)host, &ret->hostinfo, mactcp_lookupdone_upp,
(char *)&done);
/*
* PuTTY expects DNS lookups to be synchronous (see bug
continue;
ret->resolved = TRUE;
- if (ret->hostinfo.rtnCode == noErr)
+ if (ret->hostinfo.rtnCode == noErr) {
realhost = ret->hostinfo.cname;
- else
+ /* MacTCP puts trailing dots on canonical names. */
+ realhostlen = strlen(realhost);
+ if (realhost[realhostlen - 1] == '.')
+ realhost[realhostlen - 1] = '\0';
+ } else
realhost = "";
- *canonicalname = smalloc(1+strlen(realhost));
+ *canonicalname = snewn(1 + strlen(realhost), char);
strcpy(*canonicalname, realhost);
- fprintf(stderr, "canonical name = %s\n", realhost);
return ret;
}
*donep = TRUE;
}
-SockAddr sk_nonamelookup(char *host)
+SockAddr mactcp_nonamelookup(char const *host)
{
- SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
+ SockAddr ret = snew(struct SockAddr_tag);
ret->resolved = FALSE;
ret->hostinfo.rtnCode = noErr;
return ret;
}
-void sk_getaddr(SockAddr addr, char *buf, int buflen)
+void mactcp_getaddr(SockAddr addr, char *buf, int buflen)
{
char mybuf[16];
OSErr err;
/* I think "local" here really means "loopback" */
-int sk_hostname_is_local(char *name)
+int mactcp_hostname_is_local(char *name)
{
return !strcmp(name, "localhost");
}
-int sk_address_is_local(SockAddr addr)
+int mactcp_address_is_local(SockAddr addr)
{
int i;
return FALSE;
}
-int sk_addrtype(SockAddr addr)
+int mactcp_addrtype(SockAddr addr)
{
if (addr->resolved)
return ADDRTYPE_NAME;
}
-void sk_addrcopy(SockAddr addr, char *buf)
+void mactcp_addrcopy(SockAddr addr, char *buf)
{
/* XXX only return first address */
memcpy(buf, &addr->hostinfo.addr[0], 4);
}
-void sk_addr_free(SockAddr addr)
+void mactcp_addr_free(SockAddr addr)
{
sfree(addr);
static void mactcp_flush(Socket s)
{
- fatalbox("sk_tcp_flush");
+ fatalbox("mactcp_flush");
+}
+
+Socket mactcp_register(void *sock, Plug plug)
+{
+
+ fatalbox("mactcp_register");
}
-Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
- int nodelay, Plug plug)
+static TCPNotifyUPP mactcp_asr_upp;
+
+Socket mactcp_new(SockAddr addr, int port, int privport, int oobinline,
+ int nodelay, int keepalive, Plug plug)
{
static struct socket_function_table fn_table = {
mactcp_plug,
ip_addr dstaddr;
size_t buflen;
- fprintf(stderr, "Opening socket, port = %d\n", port);
/*
* Create Socket structure.
*/
- ret = smalloc(sizeof(struct Socket_tag));
+ ret = snew(struct Socket_tag);
ret->s = 0;
ret->fn = &fn_table;
ret->err = noErr;
upb.csParam.mtu.remoteHost = dstaddr;
upb.csParam.mtu.userDataPtr = NULL;
ret->err = PBControlSync((ParmBlkPtr)&upb);
- fprintf(stderr, "getting mtu, err = %d\n", ret->err);
if (ret->err != noErr) return (Socket)ret;
- fprintf(stderr, "Got MTU = %d\n", upb.csParam.mtu.mtuSize);
buflen = upb.csParam.mtu.mtuSize * 4 + 1024;
if (buflen < 4096) buflen = 4096;
+ if (mactcp_asr_upp == NULL)
+ mactcp_asr_upp = NewTCPNotifyUPP(&mactcp_asr);
+ GetCurrentProcess(&mactcp.self);
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPCreate;
- pb.csParam.create.rcvBuff = smalloc(buflen);
+ pb.csParam.create.rcvBuff = snewn(buflen, char);
pb.csParam.create.rcvBuffLen = buflen;
- pb.csParam.create.notifyProc = NULL;
+ pb.csParam.create.notifyProc = mactcp_asr_upp;
pb.csParam.create.userDataPtr = (Ptr)ret;
ret->err = PBControlSync((ParmBlkPtr)&pb);
if (ret->err != noErr) return (Socket)ret;
ret->s = pb.tcpStream;
- fprintf(stderr, "stream opened\n");
/*
* Open the connection.
/* Add this to the list of all sockets */
ret->next = mactcp.socklist;
ret->prev = &mactcp.socklist;
+ if (ret->next != NULL)
+ ret->next->prev = &ret->next;
mactcp.socklist = ret;
- fprintf(stderr, "Socket connected\n");
+ sk_addr_free(addr); /* don't need this anymore */
+
return (Socket)ret;
}
+Socket mactcp_newlistener(char *srcaddr, int port, Plug plug,
+ int local_host_only, int address_family)
+{
+
+ fatalbox("mactcp_newlistener");
+}
+
static void mactcp_close(Socket sock)
{
Actual_Socket s = (Actual_Socket)sock;
sfree(s);
}
-static int mactcp_write(Socket sock, char *buf, int len)
+static int mactcp_write(Socket sock, char const *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
wdsEntry wds[2];
TCPiopb pb;
+ /*
+ * Casting away const from buf should be safe -- MacTCP won't
+ * write to it.
+ */
wds[0].length = len;
- wds[0].ptr = buf;
+ wds[0].ptr = (char *)buf;
wds[1].length = 0;
pb.ioCRefNum = mactcp.refnum;
return 0;
}
-static int mactcp_write_oob(Socket sock, char *buf, int len)
+static int mactcp_write_oob(Socket sock, char const *buf, int len)
{
fatalbox("mactcp_write_oob");
}
+static pascal void mactcp_asr(StreamPtr str, unsigned short event, Ptr cookie,
+ unsigned short termin_reason,
+ struct ICMPReport *icmp)
+{
+
+ WakeUpProcess(&mactcp.self);
+}
+
/*
* Called from our event loop if there's work to do.
*/
void mactcp_poll(void)
{
- Actual_Socket s;
+ Actual_Socket s, next;
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)
+ for (s = mactcp.socklist; s != NULL; s = next) {
+ next = s->next;
+ do {
+ 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)
+ goto next_socket;
+ if (pb.csParam.status.amtUnreadData == 0)
+ break;
mactcp_recv(s, pb.csParam.status.amtUnreadData);
- /* Should check connectionState in case remote has closed */
+ } while (TRUE);
+ switch (pb.csParam.status.connectionState) {
+ case TCPS_CLOSE_WAIT:
+ /* Remote end has sent us a FIN */
+ plug_closing(s->plug, NULL, 0, 0);
+ }
+ next_socket:
+ ;
}
}
}
/*
- * Special error values are returned from sk_namelookup and sk_new
- * if there's a problem. These functions extract an error message,
- * or return NULL if there's no problem.
+ * Special error values are returned from mactcp_namelookup and
+ * mactcp_new if there's a problem. These functions extract an error
+ * message, or return NULL if there's no problem.
*/
-char *sk_addr_error(SockAddr addr)
+char *mactcp_addr_error(SockAddr addr)
{
static char buf[64];
}
}
-static char *mactcp_socket_error(Socket sock)
+static const char *mactcp_socket_error(Socket sock)
{
static char buf[64];
Actual_Socket s = (Actual_Socket) sock;
return noErr;
}
+#endif
+
/*
* Local Variables:
* c-file-style: "simon"