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

📄 tclmacsock.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
WaitForSocketEvent(    TcpState *statePtr,		/* Information about this socket. */    int mask,			/* Events to look for. */    int *errorCodePtr)		/* Where to store errors? */{    OSErr err;    TCPiopb statusPB;    EventRecord dummy;    /*     * Loop until we get the specified condition, unless the socket is     * asynchronous.     */        do {	statusPB.ioCRefNum = driverRefNum;	statusPB.tcpStream = statePtr->tcpStream;	statusPB.csCode = TCPStatus;	err = PBControlSync((ParmBlkPtr) &statusPB);	if (err != noErr) {	    statePtr->checkMask |= (TCL_READABLE | TCL_WRITABLE);	    return 1;	}	statePtr->checkMask = 0;	if (statusPB.csParam.status.amtUnreadData > 0) {	    statePtr->checkMask |= TCL_READABLE;	}	if (!(statePtr->flags & TCP_WRITING)		&& (statusPB.csParam.status.sendWindow - 			statusPB.csParam.status.amtUnackedData) > 0) {	    statePtr->flags &= ~(TCP_ASYNC_CONNECT);	    statePtr->checkMask |= TCL_WRITABLE;	}	if (mask & statePtr->checkMask) {	    return 1;	}	/*	 * Call the system to let other applications run while we	 * are waiting for this event to occur.	 */		WaitNextEvent(0, &dummy, 1, NULL);    } while (!(statePtr->flags & TCP_ASYNC_SOCKET));    *errorCodePtr = EWOULDBLOCK;    return 0;} /* *---------------------------------------------------------------------- * * TcpAccept -- *	Accept a TCP socket connection.  This is called by the event  *	loop, and it in turns calls any registered callbacks for this *	channel. * * Results: *	None. * * Side effects: *	Evals the Tcl script associated with the server socket. * *---------------------------------------------------------------------- */static voidTcpAccept(    TcpState *statePtr){    TcpState *newStatePtr;    StreamPtr tcpStream;    char remoteHostname[255];    OSErr err;    ip_addr remoteAddress;    long remotePort;    char channelName[20];        statePtr->flags &= ~TCP_LISTEN_CONNECT;    statePtr->checkMask &= ~TCL_READABLE;    /*     * Transfer sever stream to new connection.     */    tcpStream = statePtr->tcpStream;    newStatePtr = NewSocketInfo(tcpStream);    newStatePtr->tcpStream = tcpStream;    sprintf(channelName, "sock%d", socketNumber++);    newStatePtr->flags |= TCP_CONNECTED;    newStatePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,            (ClientData) newStatePtr, (TCL_READABLE | TCL_WRITABLE));    Tcl_SetChannelBufferSize(newStatePtr->channel, socketBufferSize);    Tcl_SetChannelOption(NULL, newStatePtr->channel, "-translation",	    "auto crlf");    remoteAddress = statePtr->pb.csParam.open.remoteHost;    remotePort = statePtr->pb.csParam.open.remotePort;    /*     * Reopen passive connect.  Make new tcpStream the server.     */    ClearZombieSockets();    InitMacTCPParamBlock(&statePtr->pb, TCPCreate);    statePtr->pb.csParam.create.rcvBuff = ckalloc(socketBufferSize);    statePtr->pb.csParam.create.rcvBuffLen = socketBufferSize;    err = PBControlSync((ParmBlkPtr) &statePtr->pb);    if (err != noErr) {	/* 	 * Hmmm...  We can't reopen the server.  We'll go ahead	 * an continue - but we are kind of broken now...	 */	 Debugger();	 statePtr->tcpStream = -1;	 statePtr->flags |= TCP_SERVER_ZOMBIE;    }    tcpStream = statePtr->tcpStream = statePtr->pb.tcpStream;        InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);    statePtr->pb.tcpStream = tcpStream;    statePtr->pb.csParam.open.localHost = 0;    statePtr->pb.csParam.open.localPort = statePtr->port;    statePtr->pb.ioCompletion = completeUPP;     statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;    statePtr->flags |= TCP_LISTENING;    err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));    /*     * TODO: deal with case where we can't recreate server socket...     */    /*     * Finally we run the accept procedure.  We must do this last to make     * sure we are in a nice clean state.  This Tcl code can do anything     * including closing the server or client sockets we've just delt with.     */    if (statePtr->acceptProc != NULL) {	sprintf(remoteHostname, "%d.%d.%d.%d", remoteAddress>>24,		remoteAddress>>16 & 0xff, remoteAddress>>8 & 0xff,		remoteAddress & 0xff);			(statePtr->acceptProc)(statePtr->acceptProcData, newStatePtr->channel, 	    remoteHostname, remotePort);    }}/* *---------------------------------------------------------------------- * * Tcl_GetHostName -- * *	Returns the name of the local host. * * Results: *	A string containing the network name for this machine, or *	an empty string if we can't figure out the name.  The caller  *	must not modify or free this string. * * Side effects: *	None. * *---------------------------------------------------------------------- */char *Tcl_GetHostName(){    static int  hostnameInited = 0;    static char hostname[255];    ip_addr ourAddress;    Tcl_DString dString;    OSErr err;        if (hostnameInited) {        return hostname;    }        if (TclHasSockets(NULL) == TCL_OK) {	err = GetLocalAddress(&ourAddress);	if (err == noErr) {	    /*	     * Search for the doman name and return it if found.  Otherwise, 	     * just print the IP number to a string and return that.	     */	    Tcl_DStringInit(&dString);	    err = ResolveAddress(ourAddress, &dString);	    if (err == noErr) {		strcpy(hostname, dString.string);	    } else {		sprintf(hostname, "%d.%d.%d.%d", ourAddress>>24, ourAddress>>16 & 0xff,		    ourAddress>>8 & 0xff, ourAddress & 0xff);	    }	    Tcl_DStringFree(&dString);	    	    hostnameInited = 1;	    return hostname;	}    }    hostname[0] = '\0';    hostnameInited = 1;    return hostname;}/* *---------------------------------------------------------------------- * * ResolveAddress -- * *	This function is used to resolve an ip address to it's full  *	domain name address. * * Results: *	An os err value. * * Side effects: *	Treats client data as int we set to true. * *---------------------------------------------------------------------- */static OSErr ResolveAddress(    ip_addr tcpAddress, 	/* Address to resolve. */    Tcl_DString *dsPtr)		/* Returned address in string. */{    int i;    EventRecord dummy;    DNRState dnrState;    OSErr err;    /*     * Call AddrToName to resolve our ip address to our domain name.     * The call is async, so we must wait for a callback to tell us     * when to continue.     */     for (i = 0; i < NUM_ALT_ADDRS; i++) {	dnrState.hostInfo.addr[i] = 0;     }    dnrState.done = 0;    GetCurrentProcess(&(dnrState.psn));    err = AddrToName(tcpAddress, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);    if (err == cacheFault) {	while (!dnrState.done) {	    WaitNextEvent(0, &dummy, 1, NULL);	}    }        /*     * If there is no error in finding the domain name we set the     * result into the dynamic string.  We also work around a bug in     * MacTcp where an extranious '.' may be found at the end of the name.     */    if (dnrState.hostInfo.rtnCode == noErr) {	i = strlen(dnrState.hostInfo.cname) - 1;	if (dnrState.hostInfo.cname[i] == '.') {	    dnrState.hostInfo.cname[i] = '\0';	}	Tcl_DStringAppend(dsPtr, dnrState.hostInfo.cname, -1);    }        return dnrState.hostInfo.rtnCode;}/* *---------------------------------------------------------------------- * * DNRCompletionRoutine -- * *	This function is called when the Domain Name Server is done *	seviceing our request.  It just sets a flag that we can poll *	in functions like Tcl_GetHostName to let them know to continue. * * Results: *	None. * * Side effects: *	Treats client data as int we set to true. * *---------------------------------------------------------------------- */static pascal void DNRCompletionRoutine(    struct hostInfo *hostinfoPtr, 	/* Host infor struct. */    DNRState *dnrStatePtr)		/* Completetion state. */{    dnrStatePtr->done = true;    WakeUpProcess(&(dnrStatePtr->psn));}/* *---------------------------------------------------------------------- * * CleanUpExitProc -- * *	This procedure is invoked as an exit handler when ExitToShell *	is called.  It aborts any lingering socket connections.  This  *	must be called or the Mac OS will more than likely crash. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static pascal voidCleanUpExitProc(){    TCPiopb exitPB;    TcpState *statePtr;    while (socketList != NULL) {	statePtr = socketList;	socketList = statePtr->nextPtr;	/*	 * Close and Release the connection.	 */	exitPB.ioCRefNum = driverRefNum;	exitPB.csCode = TCPClose;	exitPB.tcpStream = statePtr->tcpStream;	exitPB.csParam.close.ulpTimeoutValue = 60 /* seconds */;	exitPB.csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */;	exitPB.csParam.close.validityFlags = timeoutValue | timeoutAction;	exitPB.ioCompletion = NULL; 	PBControlSync((ParmBlkPtr) &exitPB);	exitPB.ioCRefNum = driverRefNum;	exitPB.csCode = TCPRelease;	exitPB.tcpStream = statePtr->tcpStream;	exitPB.ioCompletion = NULL; 	PBControlSync((ParmBlkPtr) &exitPB);    }}/* *---------------------------------------------------------------------- * * GetHostFromString -- * *	Looks up the passed in domain name in the domain resolver.  It *	can accept strings of two types: 1) the ip number in string *	format, or 2) the domain name. * * Results: *	We return a ip address or 0 if there was an error or the  *	domain does not exist. * * Side effects: *	None. * *---------------------------------------------------------------------- */static OSErrGetHostFromString(    char *name, 		/* Host in string form. */    ip_addr *address)		/* Returned IP address. */{    OSErr err;    int i;    EventRecord dummy;    DNRState dnrState;	    if (TclHasSockets(NULL) != TCL_OK) {	return 0;    }    /*     * Call StrToAddr to get the ip number for the passed in domain     * name.  The call is async, so we must wait for a callback to      * tell us when to continue.     */    for (i = 0; i < NUM_ALT_ADDRS; i++) {	dnrState.hostInfo.addr[i] = 0;    }    dnrState.done = 0;    GetCurrentProcess(&(dnrState.psn));    err = StrToAddr(name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);    if (err == cacheFault) {	while (!dnrState.done) {	    WaitNextEvent(0, &dummy, 1, NULL);	}    }        /*     * For some reason MacTcp may return a cachFault a second time via     * the hostinfo block.  This seems to be a bug in MacTcp.  In this case      * we run StrToAddr again - which seems to then work just fine.     */    if (dnrState.hostInfo.rtnCode == cacheFault) {	dnrState.done = 0;	err = StrToAddr(name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);	if (err == cacheFault) {	    while (!dnrState.done) {		WaitNextEvent(0, &dummy, 1, NULL);	    }	}    }    if (dnrState.hostInfo.rtnCode == noErr) {	*address = dnrState.hostInfo.addr[0];    }        return dnrState.hostInfo.rtnCode;}/* *---------------------------------------------------------------------- * * IOCompletionRoutine -- * *	This function is called when an asynchronous socket operation *	completes.  Since this routine runs as an interrupt handler,  *	it will simply set state to tell the notifier that this socket *	is now ready for action.  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: *	Sets some state in the socket state.  May also wake the process *	if we are not currently running. * *---------------------------------------------------------------------- */static voidIOCompletionRoutine(    TCPiopb *pbPtr)		/* Tcp parameter block. */{    TcpState *statePtr;        if (pbPtr->csCode == TCPSend) {    	statePtr = (TcpState *) pbPtr->csParam.send.userDataPtr;    } else {	statePtr = (TcpState *) pbPtr->csParam.open.userDataPtr;    }        /*     * Always wake the process in case it's in WaitNextEvent.     * If an error has a occured - just return.  We will deal     * with the problem later.     */    WakeUpProcess(&statePtr->psn);    if (pbPtr->ioResult != noErr) {	return;    }        if (statePtr->flags & TCP_ASYNC_CONNECT) {	statePtr->flags &= ~TCP_ASYNC_CONNECT;	statePtr->flags |= TCP_CONNECTED;	statePtr->checkMask |= TCL_READABLE & TCL_WRITABLE;    } else if (statePtr->flags & TCP_LISTENING) {	if (statePtr->port == 0) {	    Debugger();	}	statePtr->flags &= ~TCP_LISTENING;	statePtr->flags |= TCP_LISTEN_CONNECT;	statePtr->checkMask |= TCL_READABLE;    } else if (statePtr->flags & TCP_WRITING) {	statePtr->flags &= ~TCP_WRITING;	statePtr->checkMask |= TCL_WRITABLE;	if (!(statePtr->flags & TCP_CONNECTED)) {	    InitMacTCPParamBlock(&statePtr->pb, TCPClose);    	    statePtr->pb.tcpStream = statePtr->tcpStream;    	    statePtr->pb.ioCompletion = closeUPP;    

⌨️ 快捷键说明

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