+ static struct socket_function_table fn_table = {
+ mactcp_plug,
+ mactcp_close,
+ mactcp_write,
+ mactcp_write_oob,
+ mactcp_flush,
+ mactcp_set_private_ptr,
+ mactcp_get_private_ptr,
+ mactcp_set_frozen,
+ mactcp_socket_error
+ };
+ TCPiopb pb;
+ UDPiopb upb;
+ Actual_Socket ret;
+ ip_addr dstaddr;
+ size_t buflen;
+
+ /*
+ * Create Socket structure.
+ */
+ ret = smalloc(sizeof(struct Socket_tag));
+ ret->s = 0;
+ ret->fn = &fn_table;
+ ret->err = noErr;
+ ret->plug = plug;
+ bufchain_init(&ret->output_data);
+ ret->connected = 0; /* to start with */
+ ret->writable = 0; /* to start with */
+ ret->sending_oob = 0;
+ ret->frozen = 0;
+ 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;
+
+ dstaddr = addr->hostinfo.addr[0]; /* XXX should try all of them */
+ /*
+ * Create a TCP stream.
+ *
+ * MacTCP requires us to provide it with some buffer memory. Page
+ * 31 of the Programmer's Guide says it should be a minimum of
+ * 4*MTU+1024. Page 36 says a minimum of 4096 bytes. Assume
+ * they're both correct.
+ */
+ assert(addr->resolved);
+ upb.ioCRefNum = mactcp.refnum;
+ upb.csCode = UDPMaxMTUSize;
+ upb.csParam.mtu.remoteHost = dstaddr;
+ upb.csParam.mtu.userDataPtr = NULL;
+ ret->err = PBControlSync((ParmBlkPtr)&upb);
+ if (ret->err != noErr) return (Socket)ret;
+
+ 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.rcvBuffLen = buflen;
+ 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;
+
+ /*
+ * Open the connection.
+ */
+ pb.ioCRefNum = mactcp.refnum;
+ pb.csCode = TCPActiveOpen;
+ pb.tcpStream = ret->s;
+ pb.csParam.open.validityFlags = 0;
+ pb.csParam.open.remoteHost = dstaddr;
+ pb.csParam.open.remotePort = port;
+ pb.csParam.open.localPort = privport ? 1023 : 0;
+ pb.csParam.open.dontFrag = FALSE;
+ pb.csParam.open.timeToLive = 0;
+ pb.csParam.open.security = 0;
+ pb.csParam.open.optionCnt = 0;
+ pb.csParam.open.userDataPtr = (Ptr)ret;
+ while (1) {
+ ret->err = PBControlSync((ParmBlkPtr)&pb);
+ if (!privport || ret->err != duplicateSocket)
+ break;
+ pb.csParam.open.localPort--;
+ if (pb.csParam.open.localPort == 0)
+ break;
+ }
+
+ if (ret->err != noErr) return (Socket)ret;
+
+ ret->connected = TRUE;
+ ret->writable = TRUE;
+
+ /* 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;
+
+ return (Socket)ret;
+}
+
+Socket mactcp_newlistener(char *srcaddr, int port, Plug plug,
+ int local_host_only)
+{