📄 xtransam.c
字号:
if (ERR_STATUS(size)) { Error(("TCP/IP read failed (%s)\n", tcpip_why(ERR_CONVERT(size)))); chandesc->status |= CONN_KILLED; chandesc->status &= ~CONN_ALIVE; chandesc->signal = -1; thread_exit(); } if (size == 0 || cb_puts(chandesc->circbuf, buffer, size)) { if (size != 0) { Error(("TCP/IP short write to circular buffer for %d\n", XAmChanDescToFd(chandesc))); } else { Error(("TCP/IP read failed for client %d\n", XAmChanDescToFd(chandesc))); } chandesc->status |= CONN_KILLED; chandesc->status &= ~CONN_ALIVE; chandesc->signal = -1; thread_exit(); } UnblockMain(XAmChanDescToFd(chandesc)); }}static XAmChanDesc *AllocClientChannel(){ XAmChanDesc *chandesc; int fd; chandesc = XAmAllocChanDesc(); if (chandesc == NULL) { return NULL; } fd = XAmChanDescToFd(chandesc); if (fd >= maxClient) { maxClient = fd + 1; dbprintf(("new max Client: %d\n", fd)); } if (fd < minClient) { minClient = fd; } return chandesc;}static errstatAmRegisterRPCconn(client_ports, server_ports)am_port_t client_ports[2];am_port_t server_ports[2];{ XAmChanDesc *chandesc; if ((chandesc = AllocClientChannel()) == NULL) { return STD_NOSPACE; } chandesc->type = ACDT_VIRTCIRC; chandesc->virtcirc = vc_create(&server_ports[0], &server_ports[1], MAXBUFSIZE, MAXBUFSIZE); if (chandesc->virtcirc == NULL) { Error(("Connection refused: No memory for virtual circuit\n")); XAmFreeChanDesc(chandesc); return STD_NOSPACE; } dbprintf(("Amoeba connection registered\n")); vc_warn(chandesc->virtcirc, VC_IN, UnblockMain, XAmChanDescToFd(chandesc)); chandesc->status = CONN_INIT; /* cause WaitFor to call EstablishNewConnections: */ nNewConns++; WakeUpMainThread(); return STD_OK;}static XAmChanDesc *XAmFetchConnectingClient(){ XAmChanDesc *chandesc; int fd; for (fd = minClient; fd < maxClient; fd++) { chandesc = XAmFdToChanDesc(fd); if (chandesc->status & CONN_INIT) { Error(("Client %d is connecting\n", fd)); chandesc->status &= ~CONN_INIT; return chandesc; } } return NULL;}static errstatAmRegisterTCPconn(chancap)capability *chancap;{ XAmChanDesc *chandesc, **param; if ((chandesc = AllocClientChannel()) == NULL) { return STD_NOSPACE; } chandesc->type = ACDT_TCPIP; chandesc->chancap = *chancap; if ((chandesc->circbuf = cb_alloc(MAXBUFSIZE)) == NULL) { Error(("TCPconn refused: No memory for circular buffer\n")); XAmFreeChanDesc(chandesc); return STD_NOSPACE; } chandesc->signal = sig_uniq(); param = (XAmChanDesc **) xalloc(sizeof(XAmChanDesc *)); /* error checking? */ *param = chandesc; if (thread_newthread(TcpIpReaderThread, MAXBUFSIZE + CONNECTOR_STACK, (char *)param, sizeof(XAmChanDesc *)) == 0) { Error(("TCPconn refused: Cannot start reader thread\n")); cb_close(chandesc->circbuf); cb_free(chandesc->circbuf); XAmFreeChanDesc(chandesc); return STD_NOSPACE; } dbprintf(("TCP connection registered\n")); chandesc->status = CONN_INIT; /* cause WaitFor to call EstablishNewConnections: */ nNewConns++; WakeUpMainThread(); return STD_OK;}/* * Establishing a new connection is done in two phases. This thread does the * first part. It filters out bad connect requests. A new rendevous port is * sent to the client and the main loop is informed if there is a legal * request. The sleep synchronizes with the main loop so that the paperwork * is finished for the current connect request before the thread is ready to * accept another connect. */static voidAmConnectorThread(){ header req, rep; am_port_t client_ports[2]; am_port_t server_ports[2]; short s; char *repb; extern CreateNewClient(); WaitForInitialization(); dbprintf(("AmConnectorThread() running ...\n")); if ((repb = (char *)xalloc(REPLY_BUFSIZE)) == NULL) { Fatal(("Amoeba connector thread: malloc failed")); } for (;;) { do { req.h_port = X.cap_port; s = getreq(&req, NILBUF, 0); } while (ERR_CONVERT(s) == RPC_ABORTED); if (ERR_STATUS(s)) Fatal(("Amoeba connector thread: getreq failed")); /* TODO: check privilege fields here */ dbprintf(("AmConnectorThread() accepting a request\n")); switch (req.h_command) { case STD_INFO: rep.h_status = STD_OK; sprintf(repb, "X11R6 server on %s", XServerHostName); rep.h_size = strlen(repb); putrep(&rep, repb, rep.h_size); break; case STD_STATUS: rep.h_status = ConnectionStatus(&rep, repb, REPLY_BUFSIZE); putrep(&rep, repb, rep.h_size); break;#ifdef XSERV_t case AX_SHUTDOWN: rep.h_status = STD_OK; putrep(&rep, NILBUF, 0); GiveUp(SIGTERM); break; case AX_REINIT: rep.h_status = STD_OK; putrep(&rep, NILBUF, 0); AutoResetServer(SIGINT); break;#endif case AX_CONNECT: uniqport(&client_ports[0]); uniqport(&server_ports[1]); priv2pub(&client_ports[0], &server_ports[0]); priv2pub(&server_ports[1], &client_ports[1]); rep.h_status = AmRegisterRPCconn(client_ports, server_ports); if (rep.h_status == STD_OK) { putrep(&rep, (bufptr)client_ports, 2*sizeof(am_port_t)); } else { putrep(&rep, NILBUF, 0); } break; default: rep.h_status = STD_COMBAD; putrep(&rep, NILBUF, 0); break; } }}#ifdef XSERV_t/* * To prevent the X-server from generating lots of error messages, * in case the server is gone or when its full. */#define LOOP_OPEN 1#define LOOP_SETCONF 2#define LOOP_LISTEN 4extern char *display; /* The display number *//* * The TCP/IP connector thread listens to a well known port (6000 + * display number) for connection request. When such a request arrives * it allocates a communication structure and a reader thread. This * thread prevents the main loop from blocking when there's no data. */static voidAmTCPConnectorThread(){ capability svrcap, chancap; nwio_tcpconf_t tcpconf; nwio_tcpcl_t tcpconnopt; char name[BUFSIZ]; errstat err; int result; int looping = 0; strncpy(name, XTcpServerName, BUFSIZ); if ((err = name_lookup(name, &svrcap)) != STD_OK) { sprintf(name, "%s/%s", TCP_SVR_NAME, XTcpServerName); if ((err = name_lookup(name, &svrcap)) != STD_OK) Fatal(("Lookup %s failed: %s\n", XTcpServerName, err_why(err))); } WaitForInitialization(); dbprintf(("AmTCPConnectorThread() running ...\n")); for (;;) { /* * Listen to TCP/IP port X_TCP_PORT + display for connections. * Some interesting actions have to be taken to keep this connection * alive and kicking :-) */ if ((err = tcpip_open(&svrcap, &chancap)) != STD_OK) { /* the server probably disappeared, just wait for it to return */ if (looping & LOOP_OPEN) { Error(("TCP/IP open failed: %s\n", tcpip_why(err))); looping |= LOOP_OPEN; } sleep(60); (void) name_lookup(name, &svrcap); continue; } looping &= ~LOOP_OPEN; tcpconf.nwtc_locport = htons(X_TCP_PORT + atoi(display)); tcpconf.nwtc_flags = NWTC_EXCL | NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP; if ((err = tcp_ioc_setconf(&chancap, &tcpconf)) != STD_OK) { /* couldn't configure, probably server space problem */ if (looping & LOOP_SETCONF) { Error(("TCP/IP setconf failed: %s\n", tcpip_why(err))); looping |= LOOP_SETCONF; } std_destroy(&chancap); sleep(60); continue; } looping &= ~LOOP_SETCONF; tcpconnopt.nwtcl_flags = 0; if ((err = tcp_ioc_listen(&chancap, &tcpconnopt)) != STD_OK) { /* couldn't listen, definitely a server memory problem */ if (looping & LOOP_LISTEN) { Error(("TCP/IP listen failed: %s\n", tcpip_why(err))); looping |= LOOP_LISTEN; } std_destroy(&chancap); sleep(60); continue; } looping &= ~LOOP_LISTEN; if ((err = tcpip_keepalive_cap(&chancap)) != STD_OK) { Error(("TCP/IP keep alive failed: %s\n", tcpip_why(err))); std_destroy(&chancap); continue; } err = AmRegisterTCPconn(&chancap); if (err != STD_OK) { Error(("AmRegisterTCPconn failed (%s)\n", err_why(err))); std_destroy(&chancap); } }}static voidAmStartXserverThreads(chandesc)XAmChanDesc *chandesc;{ char host[100]; errstat err; capability pubX; static int threadsStarted = 0; /* * Each time the server is reset this routine is called to * setup the new well known sockets. For Amoeba we'll just * keep using the old threads that are already running. */ if (!threadsStarted) { threadsStarted = 1; /* * Create a new capability for this X server */ if (XServerHostName == NULL) XServerHostName = getenv("XHOST"); if (XServerHostName == NULL) { Fatal(("XHOST not set, or server host name not given\n")); } sprintf(host, "%s/%s:%s", DEF_XSVRDIR, XServerHostName, display); uniqport(&X.cap_port); priv2pub(&X.cap_port, &pubX.cap_port); (void) name_delete(host); if ((err = name_append(host, &pubX)) != 0) { Error(("Cannot create capability %s: %s\n", host, err_why(err))); exit(1); } /* Allow WaitFor module to initialize */ AmInitWaitFor(); /* Also, initialize main thread locking */ InitMainThread(); /* Initialize and start IOP reader thread */ InitializeIOPServerReader(); /* Start native Amoeba service threads */ if (thread_newthread(AmConnectorThread, CONNECTOR_STACK, 0, 0) <= 0) { Fatal(("Cannot start Amoeba connector thread\n")); } if (thread_newthread(AmConnectorThread, CONNECTOR_STACK, 0, 0) <= 0) { Fatal(("Cannot start Amoeba connector thread\n")); } chandesc->type = ACDT_VIRTCIRC; chandesc->status = CONN_ALIVE; /* * Start TCP/IP service threads */ if (XTcpServerName) { if (thread_newthread(AmTCPConnectorThread, CONNECTOR_STACK, 0, 0) <= 0) Fatal(("Cannot start TCP connector thread\n")); if (thread_newthread(AmTCPConnectorThread, CONNECTOR_STACK, 0, 0) <= 0) Fatal(("Cannot start TCP connector thread\n")); } }}intAmFindReadyClients(pClientsReady, mask)int *pClientsReady;long *mask;{ /* Check for clients needing attention. They may have input, * or they might be dying. Ignore the clients not present in * the file descriptor bit vector `mask'. This is used for * implementing server grabs. * Returns the number of clients having data for us. */ extern int ConnectionTranslation[]; XAmChanDesc *chandesc; int fd; int nready; /* Since we're scheduled non-preemptively by default, allow the * listener threads to run first, if needed: */ threadswitch(); nready = 0; for (fd = minClient; fd < maxClient; fd++) { int which; int n; if (fd > 0 && (fd % 32) == 0) { /* switch to next fd mask */ mask++; } if ((*mask & (1L << fd)) == 0) { dbprintf(("skip %d\n", fd)); continue; } chandesc = XAmFdToChanDesc(fd); if (chandesc->state != ACDS_USED) { dbprintf(("AmFindReady: fd %d not in use\n", fd)); continue; } which = ConnectionTranslation[fd]; dbprintf(("checking client %d (fd %d) of %d\n", fd, which, maxClient)); if (chandesc->status & CONN_KILLED) { dbprintf(("conn killed; close client with fd %d\n", fd)); CloseDownClient(clients[which]); chandesc->status &= ~(CONN_KILLED | CONN_ALIVE); continue; } if ((chandesc->status & CONN_ALIVE) == 0) { dbprintf(("conn with %d is not alive\n", fd)); continue; } /* see if there is data available */ switch (chandesc->type) { case ACDT_TCPIP: n = cb_full(chandesc->circbuf); break; case ACDT_VIRTCIRC: n = vc_avail(chandesc->virtcirc, VC_IN); break; default: n = -1; } if (n < 0) { dbprintf(("avail %d; close client %d\n", n, which)); CloseDownClient(clients[which]); continue; } else { if (n > 0) { *pClientsReady++ = which; nready++; dbprintf(("client %d has %d bytes available\n", which, n)); } else { dbprintf(("client %d has no data available\n", which, n)); } } /* Clients that already have (possibly inserted) data are found * with help from io.c (the ClientsWithData bit array). */ } return nready;}#endif /* XSERV_t */#endif /* XSERV_t || FS_t */staticTRANS(AmSetAddr)(ciptr, chandesc) XtransConnInfo ciptr; XAmChanDesc *chandesc;{ switch (chandesc->type) { case ACDT_TCPIP: /* should really ask the TCP/IP server */ ciptr->family = AF_INET; ciptr->addr = strdup("XXXXTODO");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -