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

📄 tclmacsock.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclMacSock.c * *	Channel drivers for Macintosh sockets. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclMacSock.c 1.59 97/10/09 18:24:42 */#include "tclInt.h"#include "tclPort.h"#include "tclMacInt.h"#include <AddressXlation.h>#include <Aliases.h>#undef Status#include <Devices.h>#include <Errors.h>#include <Events.h>#include <Files.h>#include <Gestalt.h>#include <MacTCP.h>#include <Processes.h>#include <Strings.h>/* * The following variable is used to tell whether this module has been * initialized. */static int initialized = 0;/* * If debugging is on we may drop into the debugger to handle certain cases * that are not supposed to happen.  Otherwise, we change ignore the error * and most code should handle such errors ok. */#ifndef TCL_DEBUG    #define Debugger()#endif/* * The preferred buffer size for Macintosh channels. */#define CHANNEL_BUF_SIZE	8192/* * Port information structure.  Used to match service names * to a Tcp/Ip port number. */typedef struct {    char *name;			/* Name of service. */    int port;			/* Port number. */} PortInfo;/* * This structure describes per-instance state of a tcp based channel. */typedef struct TcpState {    TCPiopb pb;			   /* Parameter block used by this stream. 				    * This must be in the first position. */    ProcessSerialNumber	psn;	   /* PSN used to wake up process. */    StreamPtr tcpStream;	   /* Macintosh tcp stream pointer. */    int port;			   /* The port we are connected to. */    int flags;			   /* Bit field comprised of the flags				    * described below.  */    int checkMask;		   /* OR'ed combination of TCL_READABLE and				    * TCL_WRITABLE as set by an asynchronous				    * event handler. */    int watchMask;		   /* OR'ed combination of TCL_READABLE and				    * TCL_WRITABLE as set by Tcl_WatchFile. */    Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */    ClientData acceptProcData;	   /* The data for the accept proc. */    wdsEntry dataSegment[2];       /* List of buffers to be written async. */    rdsEntry rdsarray[5+1];	   /* Array used when cleaning out recieve 				    * buffers on a closing socket. */    Tcl_Channel channel;	   /* Channel associated with this socket. */    struct TcpState *nextPtr;	   /* The next socket on the global socket				    * list. */} TcpState;/* * This structure is used by domain name resolver callback. */typedef struct DNRState {    struct hostInfo hostInfo;	/* Data structure used by DNR functions. */    int done;			/* Flag to determine when we are done. */    ProcessSerialNumber psn;	/* Process to wake up when we are done. */} DNRState;/* * The following macros may be used to set the flags field of * a TcpState structure. */#define TCP_ASYNC_SOCKET	(1<<0)  /* The socket is in async mode. */#define TCP_ASYNC_CONNECT	(1<<1)  /* The socket is trying to connect. */#define TCP_CONNECTED		(1<<2)  /* The socket is connected. */#define TCP_PENDING		(1<<3)	/* A SocketEvent is on the queue. */#define TCP_LISTENING 		(1<<4)  /* This socket is listening for					 * a connection. */#define TCP_LISTEN_CONNECT 	(1<<5)  /* Someone has connect to the					 * listening port. */#define TCP_REMOTE_CLOSED 	(1<<6)  /* The remote side has closed					 * the connection. */#define TCP_RELEASE	 	(1<<7)  /* The socket may now be released. */#define TCP_WRITING		(1<<8)  /* A background write is in progress. */#define TCP_SERVER_ZOMBIE	(1<<9)  /* The server can no longer accept connects. *//* * The following structure is what is added to the Tcl event queue when * a socket event occurs. */typedef struct SocketEvent {    Tcl_Event header;		/* Information that is standard for				 * all events. */    TcpState *statePtr;		/* Socket descriptor that is ready. */    StreamPtr tcpStream;	/* Low level Macintosh stream. */} SocketEvent;/* * Static routines for this file: */static pascal void	CleanUpExitProc _ANSI_ARGS_((void));static void		ClearZombieSockets _ANSI_ARGS_((void));static void		CloseCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));static TcpState *	CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,			    int port, char *host, char *myAddr,  int myPort,			    int server, int async));static pascal void	DNRCompletionRoutine _ANSI_ARGS_((			    struct hostInfo *hostinfoPtr,			    DNRState *dnrStatePtr));static void		FreeSocketInfo _ANSI_ARGS_((TcpState *statePtr));static long		GetBufferSize _ANSI_ARGS_((void));static OSErr		GetHostFromString _ANSI_ARGS_((char *name,			    ip_addr *address));static OSErr		GetLocalAddress _ANSI_ARGS_((unsigned long *addr));static void		IOCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));static void		InitMacTCPParamBlock _ANSI_ARGS_((TCPiopb *pBlock,			    int csCode));static void		InitSockets _ANSI_ARGS_((void));static TcpState *	NewSocketInfo _ANSI_ARGS_((StreamPtr stream));static OSErr		ResolveAddress _ANSI_ARGS_((ip_addr tcpAddress,			    Tcl_DString *dsPtr));static void		SocketCheckProc _ANSI_ARGS_((ClientData clientData,			    int flags));static int		SocketEventProc _ANSI_ARGS_((Tcl_Event *evPtr,			    int flags));static void		SocketExitHandler _ANSI_ARGS_((ClientData clientData));static void		SocketFreeProc _ANSI_ARGS_((ClientData clientData));static int		SocketReady _ANSI_ARGS_((TcpState *statePtr));static void		SocketSetupProc _ANSI_ARGS_((ClientData clientData,			    int flags));static void		TcpAccept _ANSI_ARGS_((TcpState *statePtr));static int		TcpBlockMode _ANSI_ARGS_((ClientData instanceData, int mode));static int		TcpClose _ANSI_ARGS_((ClientData instanceData,			    Tcl_Interp *interp));static int		TcpGetHandle _ANSI_ARGS_((ClientData instanceData,		            int direction, ClientData *handlePtr));static int		TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,                            Tcl_Interp *interp, char *optionName,			    Tcl_DString *dsPtr));static int		TcpInput _ANSI_ARGS_((ClientData instanceData,			    char *buf, int toRead, int *errorCodePtr));static int		TcpOutput _ANSI_ARGS_((ClientData instanceData,			    char *buf, int toWrite, int *errorCodePtr));static void		TcpWatch _ANSI_ARGS_((ClientData instanceData,		            int mask));static int		WaitForSocketEvent _ANSI_ARGS_((TcpState *infoPtr,		            int mask, int *errorCodePtr));/* * This structure describes the channel type structure for TCP socket * based IO: */static Tcl_ChannelType tcpChannelType = {    "tcp",			/* Type name. */    TcpBlockMode,		/* Set blocking or                                 * non-blocking mode.*/    TcpClose,			/* Close proc. */    TcpInput,			/* Input proc. */    TcpOutput,			/* Output proc. */    NULL,			/* Seek proc. */    NULL,			/* Set option proc. */    TcpGetOptionProc,		/* Get option proc. */    TcpWatch,			/* Initialize notifier. */    TcpGetHandle		/* Get handles out of channel. */};/* * Universal Procedure Pointers (UPP) for various callback * routines used by MacTcp code. */ResultUPP resultUPP = NULL;TCPIOCompletionUPP completeUPP = NULL;TCPIOCompletionUPP closeUPP = NULL;/* * Built-in commands, and the procedures associated with them: */static PortInfo portServices[] = {    {"echo",		7},    {"discard",		9},    {"systat",		11},    {"daytime",		13},    {"netstat",		15},    {"chargen",		19},    {"ftp-data",	20},    {"ftp",		21},    {"telnet",		23},    {"telneto",		24},    {"smtp",		25},    {"time",		37},    {"whois",		43},    {"domain",		53},    {"gopher",		70},    {"finger",		79},    {"hostnames",	101},    {"sunrpc",		111},    {"nntp",		119},    {"exec",		512},    {"login",		513},    {"shell",		514},    {"printer",		515},    {"courier",		530},    {"uucp",		540},    {NULL,		0},};/* * Every open socket has an entry on the following list. */static TcpState *socketList = NULL;/* * Globals for holding information about OS support for sockets. */static int socketsTestInited = false;static int hasSockets = false;static short driverRefNum = 0;static int socketNumber = 0;static int socketBufferSize = CHANNEL_BUF_SIZE;static ProcessSerialNumber applicationPSN;/* *---------------------------------------------------------------------- * * InitSockets -- * *	Load the MacTCP driver and open the name resolver.  We also *	create several UPP's used by our code.  Lastly, we install *	a patch to ExitToShell to clean up socket connections if *	we are about to exit. * * Results: *	1 if successful, 0 on failure. * * Side effects: *	Creates a new event source, loads the MacTCP driver, *	registers an exit to shell callback. * *---------------------------------------------------------------------- */#define gestaltMacTCPVersion 'mtcp'static voidInitSockets(){    ParamBlockRec pb;     OSErr err;    long response;    initialized = 1;    Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL);	    if (Gestalt(gestaltMacTCPVersion, &response) == noErr) {	hasSockets = true;    } else {	hasSockets = false;    }    if (!hasSockets) {	return;    }    /*     * Load MacTcp driver and name server resolver.     */			    pb.ioParam.ioCompletion = 0L;     pb.ioParam.ioNamePtr = "\p.IPP";     pb.ioParam.ioPermssn = fsCurPerm;     err = PBOpenSync(&pb);     if (err != noErr) {	hasSockets = 0;	return;    }    driverRefNum = pb.ioParam.ioRefNum; 	    socketBufferSize = GetBufferSize();    err = OpenResolver(NULL);    if (err != noErr) {	hasSockets = 0;	return;    }    GetCurrentProcess(&applicationPSN);    /*     * Create UPP's for various callback routines.     */    resultUPP = NewResultProc(DNRCompletionRoutine);    completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine);    closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine);    /*     * Install an ExitToShell patch.  We use this patch instead     * of the Tcl exit mechanism because we need to ensure that     * these routines are cleaned up even if we crash or are forced     * to quit.  There are some circumstances when the Tcl exit     * handlers may not fire.     */    TclMacInstallExitToShellPatch(CleanUpExitProc);        Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);    initialized = 1;}/* *---------------------------------------------------------------------- * * SocketExitHandler -- * *	Callback invoked during exit clean up to deinitialize the *	socket module. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidSocketExitHandler(    ClientData clientData)              /* Not used. */{    if (hasSockets) {	Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL);	/* CleanUpExitProc();	TclMacDeleteExitToShellPatch(CleanUpExitProc); */    }    initialized = 0;}/* *---------------------------------------------------------------------- * * TclHasSockets -- * *	This function determines whether sockets are available on the *	current system and returns an error in interp if they are not. *	Note that interp may be NULL. * * Results: *	Returns TCL_OK if the system supports sockets, or TCL_ERROR with *	an error in interp. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTclHasSockets(    Tcl_Interp *interp)		/* Interp for error messages. */{    if (!initialized) {	InitSockets();    }    if (hasSockets) {	return TCL_OK;    }    if (interp != NULL) {	Tcl_AppendResult(interp, "sockets are not available on this system",		NULL);    }    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * SocketSetupProc -- * *	This procedure is invoked before Tcl_DoOneEvent blocks waiting *	for an event. * * Results: *	None. * * Side effects: *	Adjusts the block time if needed. * *---------------------------------------------------------------------- */static voidSocketSetupProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    TcpState *statePtr;    Tcl_Time blockTime = { 0, 0 };    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Check to see if there is a ready socket.  If so, poll.     */    for (statePtr = socketList; statePtr != NULL;	    statePtr = statePtr->nextPtr) {	if (statePtr->flags & TCP_RELEASE) {	    continue;	}	if (SocketReady(statePtr)) {	    Tcl_SetMaxBlockTime(&blockTime);	    break;	}    }}/* *---------------------------------------------------------------------- * * SocketCheckProc -- * *	This procedure is called by Tcl_DoOneEvent to check the socket *	event source for events.  * * Results: *	None. * * Side effects: *	May queue an event. * *---------------------------------------------------------------------- */static voidSocketCheckProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    TcpState *statePtr;    SocketEvent *evPtr;    TcpState dummyState;    if (!(flags & TCL_FILE_EVENTS)) {	return;    }    

⌨️ 快捷键说明

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