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

📄 tclmacsock.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * Queue events for any ready sockets that don't already have events     * queued (caused by persistent states that won't generate WinSock     * events).     */    for (statePtr = socketList; statePtr != NULL;	    statePtr = statePtr->nextPtr) {	/*	 * Check to see if this socket is dead and needs to be cleaned	 * up.  We use a dummy statePtr whose only valid field is the	 * nextPtr to allow the loop to continue even if the element	 * is deleted.	 */	if (statePtr->flags & TCP_RELEASE) {	    if (!(statePtr->flags & TCP_PENDING)) {		dummyState.nextPtr = statePtr->nextPtr;		SocketFreeProc(statePtr);		statePtr = &dummyState;	    }	    continue;	}	if (!(statePtr->flags & TCP_PENDING) && SocketReady(statePtr)) {	    statePtr->flags |= TCP_PENDING;	    evPtr = (SocketEvent *) ckalloc(sizeof(SocketEvent));	    evPtr->header.proc = SocketEventProc;	    evPtr->statePtr = statePtr;	    evPtr->tcpStream = statePtr->tcpStream;	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);	}    }}/* *---------------------------------------------------------------------- * * SocketReady -- * *	This function checks the current state of a socket to see *	if any interesting conditions are present. * * Results: *	Returns 1 if an event that someone is watching is present, else *	returns 0. * * Side effects: *	Updates the checkMask for the socket to reflect any newly *	detected events. * *---------------------------------------------------------------------- */static intSocketReady(    TcpState *statePtr){    TCPiopb statusPB;    int foundSomething = 0;    int didStatus = 0;    int amount;    OSErr err;    if (statePtr->flags & TCP_LISTEN_CONNECT) {	foundSomething = 1;	statePtr->checkMask |= TCL_READABLE;    }    if (statePtr->watchMask & TCL_READABLE) {	if (statePtr->checkMask & TCL_READABLE) {	    foundSomething = 1;	} else if (statePtr->flags & TCP_CONNECTED) {	    statusPB.ioCRefNum = driverRefNum;	    statusPB.tcpStream = statePtr->tcpStream;	    statusPB.csCode = TCPStatus;	    err = PBControlSync((ParmBlkPtr) &statusPB);	    didStatus = 1;	    /*	     * We make the fchannel readable if 1) we get an error,	     * 2) there is more data available, or 3) we detect	     * that a close from the remote connection has arrived.	     */	    if ((err != noErr) ||		    (statusPB.csParam.status.amtUnreadData > 0) ||		    (statusPB.csParam.status.connectionState == 14)) {		statePtr->checkMask |= TCL_READABLE;		foundSomething = 1;	    }	}    }    if (statePtr->watchMask & TCL_WRITABLE) {	if (statePtr->checkMask & TCL_WRITABLE) {	    foundSomething = 1;	} else if (statePtr->flags & TCP_CONNECTED) {	    if (!didStatus) {		statusPB.ioCRefNum = driverRefNum;		statusPB.tcpStream = statePtr->tcpStream;		statusPB.csCode = TCPStatus;		err = PBControlSync((ParmBlkPtr) &statusPB);	    }	    /*	     * If there is an error or there if there is room to	     * send more data we make the channel writeable.	     */	    amount = statusPB.csParam.status.sendWindow - 		statusPB.csParam.status.amtUnackedData;	    if ((err != noErr) || (amount > 0)) {		statePtr->checkMask |= TCL_WRITABLE;		foundSomething = 1;	    }	}    }    return foundSomething;}/* *---------------------------------------------------------------------- * * InitMacTCPParamBlock-- * *	Initialize a MacTCP parameter block. * * Results: *	None. * * Side effects: *	Initializes the parameter block. * *---------------------------------------------------------------------- */static voidInitMacTCPParamBlock(    TCPiopb *pBlock,		/* Tcp parmeter block. */    int csCode)			/* Tcp operation code. */{    memset(pBlock, 0, sizeof(TCPiopb));    pBlock->ioResult = 1;    pBlock->ioCRefNum = driverRefNum;    pBlock->csCode = (short) csCode;}/* *---------------------------------------------------------------------- * * TcpBlockMode -- * *	Set blocking or non-blocking mode on channel. * * Results: *	0 if successful, errno when failed. * * Side effects: *	Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */static intTcpBlockMode(    ClientData instanceData, 		/* Channel state. */    int mode)				/* The mode to set. */{    TcpState *statePtr = (TcpState *) instanceData;        if (mode == TCL_MODE_BLOCKING) {	statePtr->flags &= ~TCP_ASYNC_SOCKET;    } else {	statePtr->flags |= TCP_ASYNC_SOCKET;    }    return 0;}/* *---------------------------------------------------------------------- * * TcpClose -- * *	Close the socket. * * Results: *	0 if successful, the value of errno if failed. * * Side effects: *	Closes the socket. * *---------------------------------------------------------------------- */static intTcpClose(    ClientData instanceData,		/* The socket to close. */    Tcl_Interp *interp)			/* Interp for error messages. */{    TcpState *statePtr = (TcpState *) instanceData;    StreamPtr tcpStream;    TCPiopb closePB;    OSErr err;    tcpStream = statePtr->tcpStream;    statePtr->flags &= ~TCP_CONNECTED;        /*     * If this is a server socket we can't use the statePtr     * param block because it is in use.  However, we can      * close syncronously.     */    if ((statePtr->flags & TCP_LISTENING) ||	    (statePtr->flags & TCP_LISTEN_CONNECT)) {	InitMacTCPParamBlock(&closePB, TCPClose);    	closePB.tcpStream = tcpStream;    	closePB.ioCompletion = NULL;     	err = PBControlSync((ParmBlkPtr) &closePB);    	if (err != noErr) {    	    Debugger();            panic("error closing server socket");    	}	statePtr->flags |= TCP_RELEASE;	/*	 * Server sockets are closed sync.  Therefor, we know it is OK to	 * release the socket now.	 */	InitMacTCPParamBlock(&statePtr->pb, TCPRelease);	statePtr->pb.tcpStream = statePtr->tcpStream;	err = PBControlSync((ParmBlkPtr) &statePtr->pb);	if (err != noErr) {            panic("error releasing server socket");	}	/*	 * Free the buffer space used by the socket and the 	 * actual socket state data structure.	 */	ckfree((char *) statePtr->pb.csParam.create.rcvBuff);	FreeSocketInfo(statePtr);	return 0;    }    /*     * If this socket is in the midddle on async connect we can just     * abort the connect and release the stream right now.     */     if (statePtr->flags & TCP_ASYNC_CONNECT) {	InitMacTCPParamBlock(&closePB, TCPClose);    	closePB.tcpStream = tcpStream;    	closePB.ioCompletion = NULL;     	err = PBControlSync((ParmBlkPtr) &closePB);    	if (err != noErr) {            panic("error closing async connect socket");    	}	statePtr->flags |= TCP_RELEASE;	InitMacTCPParamBlock(&statePtr->pb, TCPRelease);	statePtr->pb.tcpStream = statePtr->tcpStream;	err = PBControlSync((ParmBlkPtr) &statePtr->pb);	if (err != noErr) {            panic("error releasing async connect socket");	}	/*	 * Free the buffer space used by the socket and the 	 * actual socket state data structure.	 */	ckfree((char *) statePtr->pb.csParam.create.rcvBuff);	FreeSocketInfo(statePtr);	return 0;    }    /*     * Client sockets:     * If a background write is in progress, don't close     * the socket yet.  The completion routine for the      * write will take care of it.     */        if (!(statePtr->flags & TCP_WRITING)) {	InitMacTCPParamBlock(&statePtr->pb, TCPClose);    	statePtr->pb.tcpStream = tcpStream;    	statePtr->pb.ioCompletion = closeUPP;     	statePtr->pb.csParam.close.userDataPtr = (Ptr) statePtr;    	err = PBControlAsync((ParmBlkPtr) &statePtr->pb);    	if (err != noErr) {	    Debugger();	    statePtr->flags |= TCP_RELEASE;            /* return 0; */    	}    }    SocketFreeProc(instanceData);    return 0;}/* *---------------------------------------------------------------------- * * CloseCompletionRoutine -- * *	Handles the close protocol for a Tcp socket.  This will do *	a series of calls to release all data currently buffered for *	the socket.  This is important to do to as it allows the remote *	connection to recieve and issue it's own close on the socket. *	Note that this function is running at interupt time and can't *	allocate memory or do much else except set state. * * Results: *	None. * * Side effects: *	The buffers for the socket are flushed. * *---------------------------------------------------------------------- */static voidCloseCompletionRoutine(    TCPiopb *pbPtr)		/* Tcp parameter block. */{    TcpState *statePtr;    OSErr err;        if (pbPtr->csCode == TCPClose) {	statePtr = (TcpState *) (pbPtr->csParam.close.userDataPtr);    } else {	statePtr = (TcpState *) (pbPtr->csParam.receive.userDataPtr);    }    /*     * It's very bad if the statePtr is nNULL - we should probably panic...     */    if (statePtr == NULL) {	Debugger();	return;    }        WakeUpProcess(&statePtr->psn);    /*     * If there is an error we assume the remote side has already     * close.  We are done closing as soon as we decide that the     * remote connection has closed.     */        if (pbPtr->ioResult != noErr) {	statePtr->flags |= TCP_RELEASE;	return;    }    if (statePtr->flags & TCP_REMOTE_CLOSED) {	statePtr->flags |= TCP_RELEASE;	return;    }        /*     * If we just did a recieve we need to return the buffers.     * Otherwise, attempt to recieve more data until we recieve an     * error (usually because we have no more data).     */    if (statePtr->pb.csCode == TCPNoCopyRcv) {	InitMacTCPParamBlock(&statePtr->pb, TCPRcvBfrReturn);    	statePtr->pb.tcpStream = statePtr->tcpStream;	statePtr->pb.ioCompletion = closeUPP; 	statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;    	statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;	err = PBControlAsync((ParmBlkPtr) &statePtr->pb);    } else {	InitMacTCPParamBlock(&statePtr->pb, TCPNoCopyRcv);    	statePtr->pb.tcpStream = statePtr->tcpStream;	statePtr->pb.ioCompletion = closeUPP; 	statePtr->pb.csParam.receive.commandTimeoutValue = 1;	statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;	statePtr->pb.csParam.receive.rdsLength = 5;    	statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;	err = PBControlAsync((ParmBlkPtr) &statePtr->pb);    }    if (err != noErr) {	statePtr->flags |= TCP_RELEASE;    }}/* *---------------------------------------------------------------------- * * SocketFreeProc -- * *      This callback is invoked in order to delete *      the notifier data associated with a file handle. * * Results: *      None. * * Side effects: *      Removes the SocketInfo from the global socket list. * *---------------------------------------------------------------------- */static voidSocketFreeProc(    ClientData clientData)      /* Channel state. */{    TcpState *statePtr = (TcpState *) clientData;    OSErr err;    TCPiopb statusPB;    /*     * Get the status of this connection.  We need to do a     * few tests to see if it's OK to release the stream now.     */    if (!(statePtr->flags & TCP_RELEASE)) {	return;    }    statusPB.ioCRefNum = driverRefNum;    statusPB.tcpStream = statePtr->tcpStream;    statusPB.csCode = TCPStatus;    err = PBControlSync((ParmBlkPtr) &statusPB);    if ((statusPB.csParam.status.connectionState == 0) ||	(statusPB.csParam.status.connectionState == 2)) {	/*	 * If the conection state is 0 then this was a client	 * connection and it's closed.  If it is 2 then this a	 * server client and we may release it.  If it isn't	 * one of those values then we return and we'll try to	 * clean up later.	 */    } else {	return;    }        /*     * The Close request is made async.  We know it's     * OK to release the socket when the TCP_RELEASE flag     * gets set.     */    InitMacTCPParamBlock(&statePtr->pb, TCPRelease);    statePtr->pb.tcpStream = statePtr->tcpStream;    err = PBControlSync((ParmBlkPtr) &statePtr->pb);    if (err != noErr) {        Debugger(); /* Ignoreing leaves stranded stream.  Is there an		       alternative?  */    }    /*     * Free the buffer space used by the socket and the      * actual socket state data structure.     */    ckfree((char *) statePtr->pb.csParam.create.rcvBuff);    FreeSocketInfo(statePtr);}/* *---------------------------------------------------------------------- * * TcpInput -- * *	Reads input from the IO channel into the buffer given. Returns *	count of how many bytes were actually read, and an error  *	indication. * * Results: *	A count of how many bytes were read is returned.  A value of -1 *	implies an error occured.  A value of zero means we have reached *	the end of data (EOF). * * Side effects: *	Reads input from the actual channel. * *---------------------------------------------------------------------- */intTcpInput(    ClientData instanceData,		/* Channel state. */

⌨️ 快捷键说明

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