⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclmacsock.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
    err = PBControlSync((ParmBlkPtr) &statusPB);    if ((err == connectionDoesntExist) ||	((err == noErr) && (statusPB.csParam.status.connectionState == 14))) {	/*	 * The socket was probably closed on the other side of the connection.	 */	if (interp) {	    Tcl_AppendResult(interp, "can't access socket info: ",			     "connection reset by peer", NULL);	}	return TCL_ERROR;    } else if (err != noErr) {	if (interp) { 	    Tcl_AppendResult(interp, "unknown socket error", NULL);	}	Debugger();	return TCL_ERROR;    }    /*     * Get the sockname for the socket.     */    Tcl_DStringInit(&dString);    if (doAll || doSockName) {	if (doAll) {	    Tcl_DStringAppendElement(dsPtr, "-sockname");	    Tcl_DStringStartSublist(dsPtr);	}	tcpAddress = statusPB.csParam.status.localHost;	sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,		tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,		tcpAddress & 0xff);	Tcl_DStringAppendElement(dsPtr, buffer);	if (ResolveAddress(tcpAddress, &dString) == noErr) {	    Tcl_DStringAppendElement(dsPtr, dString.string);	} else {	    Tcl_DStringAppendElement(dsPtr, "<unknown>");	}	sprintf(buffer, "%d", statusPB.csParam.status.localPort);	Tcl_DStringAppendElement(dsPtr, buffer);	if (doAll) {	    Tcl_DStringEndSublist(dsPtr);	}    }    /*     * Get the peername for the socket.     */    if ((doAll || doPeerName) && (statePtr->flags & TCP_CONNECTED)) {	if (doAll) {	    Tcl_DStringAppendElement(dsPtr, "-peername");	    Tcl_DStringStartSublist(dsPtr);	}	tcpAddress = statusPB.csParam.status.remoteHost;	sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,		tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,		tcpAddress & 0xff);	Tcl_DStringAppendElement(dsPtr, buffer);	Tcl_DStringSetLength(&dString, 0);	if (ResolveAddress(tcpAddress, &dString) == noErr) {	    Tcl_DStringAppendElement(dsPtr, dString.string);	} else {	    Tcl_DStringAppendElement(dsPtr, "<unknown>");	}	sprintf(buffer, "%d", statusPB.csParam.status.remotePort);	Tcl_DStringAppendElement(dsPtr, buffer);	if (doAll) {	    Tcl_DStringEndSublist(dsPtr);	}    }    Tcl_DStringFree(&dString);    return TCL_OK;}/* *---------------------------------------------------------------------- * * TcpWatch -- * *	Initialize the notifier to watch this channel. * * Results: *	None. * * Side effects: *	Sets the watchMask for the channel. * *---------------------------------------------------------------------- */static voidTcpWatch(instanceData, mask)    ClientData instanceData;		/* The file state. */    int mask;				/* Events of interest; an OR-ed                                         * combination of TCL_READABLE,                                         * TCL_WRITABLE and TCL_EXCEPTION. */{    TcpState *statePtr = (TcpState *) instanceData;    statePtr->watchMask = mask;}/* *---------------------------------------------------------------------- * * NewSocketInfo -- * *	This function allocates and initializes a new SocketInfo *	structure. * * Results: *	Returns a newly allocated SocketInfo. * * Side effects: *	Adds the socket to the global socket list, allocates memory. * *---------------------------------------------------------------------- */static TcpState *NewSocketInfo(    StreamPtr tcpStream){    TcpState *statePtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));    statePtr->tcpStream = tcpStream;    statePtr->psn = applicationPSN;    statePtr->flags = 0;    statePtr->checkMask = 0;    statePtr->watchMask = 0;    statePtr->acceptProc = (Tcl_TcpAcceptProc *) NULL;    statePtr->acceptProcData = (ClientData) NULL;    statePtr->writeBuffer = (void *) NULL;    statePtr->writeBufferSize = 0;    statePtr->nextPtr = tsdPtr->socketList;    tsdPtr->socketList = statePtr;    return statePtr;}/* *---------------------------------------------------------------------- * * FreeSocketInfo -- * *	This function deallocates a SocketInfo structure that is no *	longer needed. * * Results: *	None. * * Side effects: *	Removes the socket from the global socket list, frees memory. * *---------------------------------------------------------------------- */static voidFreeSocketInfo(    TcpState *statePtr)		/* The state pointer to free. */{    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (statePtr == tsdPtr->socketList) {	tsdPtr->socketList = statePtr->nextPtr;    } else {	TcpState *p;	for (p = tsdPtr->socketList; p != NULL; p = p->nextPtr) {	    if (p->nextPtr == statePtr) {		p->nextPtr = statePtr->nextPtr;		break;	    }	}    }        if (statePtr->writeBuffer != (void *) NULL) {        ckfree(statePtr->writeBuffer);    }        ckfree((char *) statePtr);}/* *---------------------------------------------------------------------- * * Tcl_MakeTcpClientChannel -- * *	Creates a Tcl_Channel from an existing client TCP socket. * * Results: *	The Tcl_Channel wrapped around the preexisting TCP socket. * * Side effects: *	None. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_MakeTcpClientChannel(    ClientData sock)	/* The socket to wrap up into a channel. */{    TcpState *statePtr;    char channelName[20];    if (TclpHasSockets(NULL) != TCL_OK) {	return NULL;    }	    statePtr = NewSocketInfo((StreamPtr) sock);    /* TODO: do we need to set the port??? */        sprintf(channelName, "sock%d", socketNumber++);        statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,            (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));    Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);    Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");    return statePtr->channel;}/* *---------------------------------------------------------------------- * * CreateSocket -- * *	This function opens a new socket and initializes the *	SocketInfo structure. * * Results: *	Returns a new SocketInfo, or NULL with an error in interp. * * Side effects: *	Adds a new socket to the socketList. * *---------------------------------------------------------------------- */static TcpState *CreateSocket(    Tcl_Interp *interp,		/* For error reporting; can be NULL. */    int port,			/* Port number to open. */    CONST char *host,		/* Name of host on which to open port. */    CONST char *myaddr,		/* Optional client-side address */    int myport,			/* Optional client-side port */    int server,			/* 1 if socket should be a server socket,				 * else 0 for a client socket. */    int async)			/* 1 create async, 0 do sync. */{    ip_addr macAddr;    OSErr err;    TCPiopb pb;    StreamPtr tcpStream;    TcpState *statePtr;    char * buffer;        /*     * Figure out the ip address from the host string.     */    if (host == NULL) {	err = GetLocalAddress(&macAddr);    } else {	err = GetHostFromString(host, &macAddr);    }    if (err != noErr) {	Tcl_SetErrno(EHOSTUNREACH);	if (interp != (Tcl_Interp *) NULL) {	    Tcl_AppendResult(interp, "couldn't open socket: ",                        Tcl_PosixError(interp), (char *) NULL);	}	return (TcpState *) NULL;    }        /*     * Create a MacTCP stream and create the state used for socket     * transactions from here on out.     */    ClearZombieSockets();    buffer = ckalloc(socketBufferSize);    InitMacTCPParamBlock(&pb, TCPCreate);    pb.csParam.create.rcvBuff = buffer;    pb.csParam.create.rcvBuffLen = socketBufferSize;    pb.csParam.create.notifyProc = nil /* notifyUPP */;    err = PBControlSync((ParmBlkPtr) &pb);    if (err != noErr) {        Tcl_SetErrno(0); /* TODO: set to ENOSR - maybe?*/        if (interp != (Tcl_Interp *) NULL) {	    Tcl_AppendResult(interp, "couldn't open socket: ",		Tcl_PosixError(interp), (char *) NULL);        }	return (TcpState *) NULL;    }    tcpStream = pb.tcpStream;    statePtr = NewSocketInfo(tcpStream);    statePtr->port = port;        if (server) {        /*          * Set up server connection.         */	InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);	statePtr->pb.tcpStream = tcpStream;	statePtr->pb.csParam.open.localPort = statePtr->port;	statePtr->pb.ioCompletion = completeUPP; 	statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;	statePtr->pb.csParam.open.ulpTimeoutValue = 100;	statePtr->pb.csParam.open.ulpTimeoutAction 	= 1 /* 1:abort 0:report */;	statePtr->pb.csParam.open.commandTimeoutValue	= 0 /* infinity */;	statePtr->flags |= TCP_LISTENING;	err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));	/*	 * If this is a server on port 0 then we need to wait until	 * the dynamic port allocation is made by the MacTcp driver.	 */	if (statePtr->port == 0) {	    EventRecord dummy;	    while (statePtr->pb.csParam.open.localPort == 0) {		WaitNextEvent(0, &dummy, 1, NULL);		if (statePtr->pb.ioResult != 0) {		    break;		}	    }	    statePtr->port = statePtr->pb.csParam.open.localPort;	}	Tcl_SetErrno(EINPROGRESS);    } else {	/*	 * Attempt to connect. The connect may fail at present with an	 * EINPROGRESS but at a later time it will complete. The caller	 * will set up a file handler on the socket if she is interested in	 * being informed when the connect completes.	 */	InitMacTCPParamBlock(&statePtr->pb, TCPActiveOpen);		statePtr->pb.tcpStream = tcpStream;	statePtr->pb.csParam.open.remoteHost = macAddr;	statePtr->pb.csParam.open.remotePort = port;	statePtr->pb.csParam.open.localHost = 0;	statePtr->pb.csParam.open.localPort = myport;	statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;		statePtr->pb.csParam.open.validityFlags 	= timeoutValue | timeoutAction;	statePtr->pb.csParam.open.ulpTimeoutValue 	= 60 /* seconds */;	statePtr->pb.csParam.open.ulpTimeoutAction 	= 1 /* 1:abort 0:report */;	statePtr->pb.csParam.open.commandTimeoutValue   = 0;	statePtr->pb.ioCompletion = completeUPP;	if (async) {	    statePtr->flags |= TCP_ASYNC_CONNECT;	    err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));	    Tcl_SetErrno(EINPROGRESS);	} else {	    err = PBControlSync((ParmBlkPtr) &(statePtr->pb));	}    }        switch (err) {	case noErr:	    if (!async) {		statePtr->flags |= TCP_CONNECTED;	    }	    return statePtr;	case duplicateSocket:	    Tcl_SetErrno(EADDRINUSE);	    break;	case openFailed:	case connectionTerminated:	    Tcl_SetErrno(ECONNREFUSED);	    break;	case invalidStreamPtr:	case connectionExists:	default:	    /*	     * These cases should never occur.  However, we will fail	     * gracefully and hope Tcl can resume.  The alternative is to panic	     * which is probably a bit drastic.	     */	    Debugger();	    Tcl_SetErrno(err);    }    /*     * We had error during the connection.  Release the stream     * and file handle.  Also report to the interp.     */    pb.ioCRefNum = driverRefNum;    pb.csCode = TCPRelease;    pb.tcpStream = tcpStream;    pb.ioCompletion = NULL;     err = PBControlSync((ParmBlkPtr) &pb);    if (interp != (Tcl_Interp *) NULL) {	Tcl_AppendResult(interp, "couldn't open socket: ",	    Tcl_PosixError(interp), (char *) NULL);    }    ckfree(buffer);    FreeSocketInfo(statePtr);    return (TcpState *) NULL;}/* *---------------------------------------------------------------------- * * Tcl_OpenTcpClient -- * *	Opens a TCP client socket and creates a channel around it. * * Results: *	The channel or NULL if failed. On failure, the routine also *	sets the output argument errorCodePtr to the error code. * * Side effects: *	Opens a client socket and creates a new channel. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_OpenTcpClient(    Tcl_Interp *interp, 		/* For error reporting; can be NULL. */    int port, 				/* Port number to open. */    CONST char *host, 			/* Host on which to open port. */    CONST char *myaddr,			/* Client-side address */    int myport, 			/* Client-side port */    int async)				/* If nonzero, attempt to do an                                         * asynchronous connect. Otherwise                                         * we do a blocking connect.                                          * - currently ignored */{    TcpState *statePtr;    char channelName[20];    if (TclpHasSockets(interp) != TCL_OK) {	return NULL;    }	    /*     * Create a new client socket and wrap it in a channel.     */    statePtr = CreateSocket(interp, port, host, myaddr, myport, 0, async);    if (statePtr == NULL) {	return NULL;    }        sprintf(channelName, "sock%d", socketNumber++);    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,            (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));    Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);    Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");    return statePtr->channel;}/* *---------------------------------------------------------------------- * * Tcl_OpenTcpServer -- * *	Opens a TCP server socket and creates a channel around it. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -