Site hosted by Angelfire.com: Build your free website today!

Hands-on Projects for the Linux Graphics Subsystem

New book from Christos Karayiannis

Available in Amazon Kindle format at:

amazon.com   amazon.co.uk   amazon.de   amazon.es   amazon.fr   amazon.it

EstablishNewConnections()

EstablishNewConnections(), called from WaitForSomething() via QueueWorkProc(), in the Dispatch() loop is the X Server mechanism to accept new X Clients. It also updates the AllClients and AllSockets fd sets used by select().

For QueueWorkProc we read at the Definition of the Porting Layer for the X v11 Sample Server:

5.9.  Work Queue

To queue work for execution when all clients are in a stable
state (i.e.  just before calling select() in WaitForSome-
thing), call:
     Bool QueueWorkProc(function,client,closure)
	  Bool	    (*function)();
	  ClientPtr client;
	  pointer	 closure;

When the server is about to suspend itself, the given func-
tion will be executed:
     (*function) (client, closure)

Neither client nor closure are actually used inside the work
queue routines.

A simplified WaitForSomething() while loop with the QueueWorkProc() and ProcessWorkQueue(), that processes the work queue is shown bellow. For more details on WaitForSomething() see section 3.2.5.2.

    while (1)
    {
	if (workQueue)
	    ProcessWorkQueue();
.  .  .
	    i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
.  .  .
	    XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
	    if (XFD_ANYSET(&tmp_set))
		QueueWorkProc(EstablishNewConnections, NULL,
			      (pointer)&LastSelectMask);
.  .  .
    }

EstablishNewConnections() commnetary

EstablishNewConnections() has the prototype:

Bool
EstablishNewConnections(ClientPtr clientUnused, pointer closure)

    XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
    XFD_COPYSET(&tmask, &readyconnections);
    if (!XFD_ANYSET(&readyconnections))
	return TRUE;

the closure is substituted by the LastSelectMask argument. As seen also in section 3.2.5.2 WellKnownConnections is defined in connection.c as the fd set of the client connections with the X Server so far. LastSelectMask is filtered with the 'known connections' since LastSelectMask include other fds as well e.g. of device connections. Then it is copied to readyconnections.

The following part closes X Clients that timeout. TimeOutValue is defined in globals.c as:

CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;

Where DEFAULT_TIMEOUT is defined to site.h as:

#define DEFAULT_TIMEOUT		60	/* seconds */
and MILLI_PER_SECOND is defined in misc.h as:
#define MILLI_PER_SECOND (1000)


    connect_time = GetTimeInMillis();
    /* kill off stragglers */
    for (i=1; i<currentMaxClients; i++)
    {
	if ((client = clients[i]))
	{
	    oc = (OsCommPtr)(client->osPrivate);
	    if ((oc && (oc->conn_time != 0) &&
		(connect_time - oc->conn_time) >= TimeOutValue) || 
		(client->noClientException != Success && !client->clientGone))
		CloseDownClient(client);     
	}
    }

    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
    {
      while (readyconnections.fds_bits[i])
      {
	XtransConnInfo trans_conn, new_trans_conn;
	int status;

	curconn = ffs (readyconnections.fds_bits[i]) - 1;
	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
	curconn += (i * (sizeof(fd_mask)*8))
	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
	    continue;

	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
	    continue;

	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);

	if (newconn < lastfdesc)
	{
		int clientid;
  		clientid = ConnectionTranslation[newconn];
		if(clientid && (client = clients[clientid]))
 			CloseDownClient(client);
	}

	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);

	if (!AllocNewConnection (new_trans_conn, newconn, connect_time
				))
	{
	    ErrorConnMax(new_trans_conn);
	    _XSERVTransClose(new_trans_conn);
	}
      }
    }
    return TRUE;

fd_set is defined in the header file sys/select.h included via the X11/Xos.h header file as:

typedef struct fd_set {
	fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} fd_set;

for a description on fd_set see Waiting for I/O.

fd_mask is defined in select.h as long and howmany as:

#define	howmany(x, y)	(((x)+((y)-1))/(y))

XFD_SETSIZE is defined as:

#define XFD_SETSIZE	256

and NFDBITS as:

#define	NFDBITS		(sizeof (fd_mask) * NBBY)	/* bits per mask */

where NBBY is 8.

Also for the ffs() (find first bit) read the ffs man page.

We examine next more detailed the parts of the previous green code box:

    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
    {
      while (readyconnections.fds_bits[i])

the for loop increases i from 0 to the max number of long (4-bytes) integer dedicated for file descriptors. This is returned by howmany.

The while loop then searches in each of those long integers for bits that are set (longs have a non zero value).

	curconn = ffs (readyconnections.fds_bits[i]) - 1;

ffs() is used to extract the position of the first bit set and this is returned as curconn (current connection). This is the fd of listener that's ready.

	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
	curconn += (i * (sizeof(fd_mask)*8))

The specific fd is cleared from readyconnections and the curconn from relative value (bit inside a long) takes an absolute value (bit inside all longs that make up fds_bits[]).

	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
	    continue;

lookup_trans_conn() is used, which returns for a given fd to trans_conn the XtransConnInfo info connection struct:

static XtransConnInfo
lookup_trans_conn (int fd)
{
    if (ListenTransFds)
    {
	int i;
	for (i = 0; i < ListenTransCount; i++)
	    if (ListenTransFds[i] == fd)
		return ListenTransConns[i];
    }

    return (NULL);
}

ListenTransFds[], ListenTransConns[] are filled in CreateWellKnownSockets() via _XSERVTransMakeAllCOTSServerListeners() or TRANS(MakeAllCOTSServerListeners) (see section 3.2.1).

We return back to EstablishNewConnections() code:

	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
	    continue;

trans_conn is passed then to _XSERVTransAccept(), which is implemented as TRANS(Accept), since the latter according to Xtrans.h is resolved to _XSERVTransAccept():

#ifdef XSERV_t
#if !defined(UNIXCPP) || defined(ANSICPP)
#define TRANS(func) _XSERVTrans##func

The implementation of of TRANS(Accept) is found at Xtrans.c:

XtransConnInfo
TRANS(Accept) (XtransConnInfo ciptr, int *status)

{
    XtransConnInfo	newciptr;

    PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0);

    newciptr = ciptr->transptr->Accept (ciptr, status);

    if (newciptr)
	newciptr->transptr = ciptr->transptr;

    return newciptr;
}

trans_conn (the argument of type XtransConnInfo that substitutes the ciptr parameter) provides the specific 'Accept' routine. If as case example considers that the Xtransport, transptr points to, is the TRANS(SocketTCPFuncs) - see section 1.4.2 - then Accept becomes TRANS(SocketINETAccept), which is actually resolved to a socket API's accept() call. As a result a new XtransConnInfo is returned for the new connection as new_trans_conn.

	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);

From XtransConnInfo the fd of the new connection (newconn), which is usually of interest in the sockets API is extracted with _XSERVTransGetConnectionNumber, implemented as TRANS(GetConnectionNumber):

int
TRANS(GetConnectionNumber) (XtransConnInfo ciptr)

{
    return ciptr->fd;
}

The TRANS_NONBLOCKING option is set for the new connection:

	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);

_XSERVTransSetOption() is implemented as TRANS(SetOption), which for TRANS_NONBLOCKING with the third argument 1 sets the well known socket API's O_NONBLOCK flag.

	if (!AllocNewConnection (new_trans_conn, newconn, connect_time
				))
	{
	    ErrorConnMax(new_trans_conn);
	    _XSERVTransClose(new_trans_conn);
	}

AllocNewConnection()

AllocNewConnection() is implemented as:

static ClientPtr
#ifdef LBX
AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time, 
    int (*Flush)(
        ClientPtr /*who*/, OsCommPtr /*oc*/,
        char * /*extraBuf*/, int /*extraCount*/),
    void (*Close)(
        ClientPtr /*client*/),
    LbxProxyPtr proxy)
#else
AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
#endif
{
    OsCommPtr	oc;
    ClientPtr	client;
    
    if (
#ifdef LBX
	trans_conn &&
#endif
#ifndef WIN32
	fd >= lastfdesc
#else
	XFD_SETCOUNT(&AllClients) >= MaxClients
#endif
	)
	return NullClient;
    oc = (OsCommPtr)xalloc(sizeof(OsCommRec));
    if (!oc)
	return NullClient;
    oc->trans_conn = trans_conn;
    oc->fd = fd;
    oc->input = (ConnectionInputPtr)NULL;
    oc->output = (ConnectionOutputPtr)NULL;
    oc->auth_id = None;
    oc->conn_time = conn_time;
#ifdef LBX
    oc->proxy = proxy;
    oc->Flush = Flush;
    oc->Close = Close;
    oc->largereq = (ConnectionInputPtr) NULL;
#endif
    if (!(client = NextAvailableClient((pointer)oc)))
    {
	xfree (oc);
	return NullClient;
    }
#ifdef LBX
    if (trans_conn)
#endif
    {
#if !defined(WIN32)
	ConnectionTranslation[fd] = client->index;
#else
	SetConnectionTranslation(fd, client->index);
#endif
	if (GrabInProgress)
	{
	    FD_SET(fd, &SavedAllClients);
	    FD_SET(fd, &SavedAllSockets);
	}
	else
	{
	    FD_SET(fd, &AllClients);
	    FD_SET(fd, &AllSockets);
	}
    }

In the case fd >= lastfdesc, where lastfdesc is the maximum file descriptor no more clients are accepted and the NullClient is returned. This is defined in dix.h as:

#define NullClient ((ClientPtr) 0)

oc a OsCommPtr is allocated from the heap via xalloc. Some of its fields like trans_conn and fd are filled then. As we saw in section 3.2.5.3 OsCommPtr is defined in osdep.h as:

typedef struct _osComm {
    int fd;
    ConnectionInputPtr input;
    ConnectionOutputPtr output;
    XID	auth_id;		/* authorization id */
#ifdef K5AUTH
    k5_state	authstate;	/* state of setup auth conversation */
#endif
    CARD32 conn_time;		/* timestamp if not established, else 0  */
    struct _XtransConnInfo *trans_conn; /* transport connection object */
#ifdef LBX
    OsProxyPtr proxy;
    ConnectionInputPtr largereq;
    OsCloseFunc Close;
    OsFlushFunc Flush;
#endif
} OsCommRec, *OsCommPtr;

oc is the argument for NextAvailableClient() that is called next.

NextAvailableClient()

This function is implemented as:

/************************
 * int NextAvailableClient(ospriv)
 *
 * OS dependent portion can't assign client id's because of CloseDownModes.
 * Returns NULL if there are no free clients.
 *************************/

ClientPtr NextAvailableClient(pointer ospriv)
{
    register int i;
    register ClientPtr client;
    xReq data;

    i = nextFreeClientID;
    if (i == MAXCLIENTS)
	return (ClientPtr)NULL;
    clients[i] = client = (ClientPtr)xalloc(totalClientSize);
    if (!client)
	return (ClientPtr)NULL;
    InitClient(client, i, ospriv);
    InitClientPrivates(client);
    if (!InitClientResources(client))
    {
	xfree(client);
	return (ClientPtr)NULL;
    }
    data.reqType = 1;
    data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
    if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
    {
	FreeClientResources(client);
	xfree(client);
	return (ClientPtr)NULL;
    }
    if (i == currentMaxClients)
	currentMaxClients++;
    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
	nextFreeClientID++;
    if (ClientStateCallback)
    {
	NewClientInfoRec clientinfo;

        clientinfo.client = client; 
        clientinfo.prefix = (xConnSetupPrefix *)NULL;  
        clientinfo.setup = (xConnSetup *) NULL;
	CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
    } 	
    return(client);
}

NextAvailableClient() allocates a new client from the heap via xalloc() and places it in the next available entry in clients[]. It then initializes the client by calling InitClient(), implemented as:

void InitClient(ClientPtr client, int i, pointer ospriv)
{
    client->index = i;
    client->sequence = 0; 
    client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
    client->clientGone = FALSE;
    if (i)
    {
	client->closeDownMode = DestroyAll;
	client->lastDrawable = (DrawablePtr)WindowTable[0];
	client->lastDrawableID = WindowTable[0]->drawable.id;
    }
    else
    {
	client->closeDownMode = RetainPermanent;
	client->lastDrawable = (DrawablePtr)NULL;
	client->lastDrawableID = INVALID;
    }
    client->lastGC = (GCPtr) NULL;
    client->lastGCID = INVALID;
    client->numSaved = 0;
    client->saveSet = (SaveSetElt *)NULL;
    client->noClientException = Success;
#ifdef DEBUG
    client->requestLogIndex = 0;
#endif
    client->requestVector = InitialVector;
    client->osPrivate = ospriv;
    client->swapped = FALSE;
    client->big_requests = FALSE;
    client->priority = 0;
    client->clientState = ClientStateInitial;
#ifdef XKB
    if (!noXkbExtension) {
	client->xkbClientFlags = 0;
	client->mapNotifyMask = 0;
	QueryMinMaxKeyCodes(&client->minKC,&client->maxKC);
    }
#endif
    client->replyBytesRemaining = 0;
#ifdef LBX
    client->readRequest = StandardReadRequestFromClient;
#endif
#ifdef XCSECURITY
    client->trustLevel = XSecurityClientTrusted;
    client->CheckAccess = NULL;
    client->authId = 0;
#endif
#ifdef XAPPGROUP
    client->appgroup = NULL;
#endif
    client->fontResFunc = NULL;
#ifdef SMART_SCHEDULE
    client->smart_priority = 0;
    client->smart_start_tick = SmartScheduleTime;
    client->smart_stop_tick = SmartScheduleTime;
    client->smart_check_tick = SmartScheduleTime;
#endif
}

At this point the request vector of the client (the array of the X Protocol routines that execute according to the reqType the client sends) is set to InitialVector, so that it has the chance to change latter to ProcVector[] or SwappedProcVector[].
    client->requestVector = InitialVector;

InitialVector is found in tables.c as:

int (* InitialVector[3]) (
	ClientPtr /* client */
    ) =
{
    0,
    ProcInitialConnection,
    ProcEstablishConnection
};

NextAvailableClient() calls also InitClientPrivates() to initialize devPrivates. For devPrivates we read from Definition of the Porting Layer for the X v11 Sample Server:

devPrivates are arrays of values attached to various data structures (Screens, GCs, Windows, and Pixmaps currently). These arrays are sized dynamically at server startup (and reset) time as various modules allocate portions of them. They can be used for any purpose; each array entry is actually a union, DevUnion, of common useful types (pointer, long and unsigned long).

NextAvailableClient() executes then the following important lines of code:

    data.reqType = 1;
    data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
    if (!InsertFakeRequest(client, (char *)&data, sz_xReq))

InsertFakeRequest() places a fake request (that is a request the client never issued) on the client's buffer (As we see bellow the initial message to the X server doe not include a reqType and the X Server prepares one on behalf of the client). This function is implemented as:

Bool
InsertFakeRequest(ClientPtr client, char *data, int count)
{
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
    ConnectionInputPtr oci = oc->input;
    int fd = oc->fd;
    int gotnow, moveup;

    if (AvailableInput)
    {
	if (AvailableInput != oc)
	{
	    ConnectionInputPtr aci = AvailableInput->input;
	    if (aci->size > BUFWATERMARK)
	    {
		xfree(aci->buffer);
		xfree(aci);
	    }
	    else
	    {
		aci->next = FreeInputs;
		FreeInputs = aci;
	    }
	    AvailableInput->input = (ConnectionInputPtr)NULL;
	}
	AvailableInput = (OsCommPtr)NULL;
    }
    if (!oci)
    {
	if ((oci = FreeInputs))
	    FreeInputs = oci->next;
	else if (!(oci = AllocateInputBuffer()))
	    return FALSE;
	oc->input = oci;
    }
    oci->bufptr += oci->lenLastReq;
    oci->lenLastReq = 0;
    gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
    if ((gotnow + count) > oci->size)
    {
	char *ibuf;

	ibuf = (char *)xrealloc(oci->buffer, gotnow + count);
	if (!ibuf)
	    return(FALSE);
	oci->size = gotnow + count;
	oci->buffer = ibuf;
	oci->bufptr = ibuf + oci->bufcnt - gotnow;
    }
    moveup = count - (oci->bufptr - oci->buffer);
    if (moveup > 0)
    {
	if (gotnow > 0)
	    memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
	oci->bufptr += moveup;
	oci->bufcnt += moveup;
    }
    memmove(oci->bufptr - count, data, count);
    oci->bufptr -= count;
    gotnow += count;
    if ((gotnow >= sizeof(xReq)) &&
	(gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2)))
	FD_SET(fd, &ClientsWithInput);
    else
	YieldControlNoInput();
    return(TRUE);
}

In our case the request type is 1 and the request vector is InitialVector[]. The routine we find at index 1 in InitialVector[] is ProcInitialConnection().

ProcInitialConnection


int
ProcInitialConnection(register ClientPtr client)
{
    REQUEST(xReq);
    register xConnClientPrefix *prefix;
    int whichbyte = 1;

    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
    if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
	return (client->noClientException = -1);
    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
	(!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
    {
	client->swapped = TRUE;
	SwapConnClientPrefix(prefix);
    }
    stuff->reqType = 2;
    stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) +
		     ((prefix->nbytesAuthString + (unsigned)3) >> 2);
    if (client->swapped)
    {
	swaps(&stuff->length, whichbyte);
    }
    ResetCurrentRequest(client);
    return (client->noClientException);
}

ProcInitialConnection() is executed with the following instruction of the Dispatch() loop (see section 3.2.5):

result = (* client->requestVector[MAJOROP])(client);
This is described more detailed in section 3.2.5.3.

As we mentioned in section 1.2 the initial message the X client sends to the X server has the format:

typedef struct {
    CARD8	byteOrder;
    BYTE	pad;
    CARD16	majorVersion B16, minorVersion B16;
    CARD16	nbytesAuthProto B16;	/* Authorization protocol */
    CARD16	nbytesAuthString B16;	/* Authorization string */
    CARD16	pad2 B16;
} xConnClientPrefix;

The byteOrder field is examined. This indicates the byte order. It was either filled by the X client as 'B' (Most Significant Byte - MSB first) or 'l' (Less Significant Byte - LSB first). ASCII upper case B is the octal 102 and ASCII lower case l is the octal 154 (see the ascii table). The code that does that in the X client side is found at OpenDis.c:

	endian = 1;
	if (*(char *) &endian)
	    client.byteOrder = '\154'; /* 'l' */
	else
	    client.byteOrder = '\102'; /* 'B' */

endian is declared in this file as int (32 bits). Variable "endian" is an integer variable, thus a 32-bit variable (on most systems) and by doing "&endian" it converts the variable from "int" to "int*" and therefore &endian describes the location of the number in memory. By doing:

(char *) &endian
It tells that from the 4 bytes in memory used for the variable "endian", only use the first one. (It casts the variable as a char*, instead of int*. int = 4bytes; char = 1 byte). And finally when doing:
*(char*)&endian
It tells to read the content of that byte in memory. If it is set to "1" we're on a little endian machine. This should be the memory content in both systems:

Little endian: 00 00 00 01
Big endian:    01 00 00 00
So, by reading the first byte we can tell if it is little- of big-endian.

The X Server checks the endianess with the following code of ProcInitialConnection():

    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
	(!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
    {
	client->swapped = TRUE;
where whichbyte is defined as:
int	    whichbyte = 1;

whichbyte for the X Server (the current process) can either be:

00 00 00 01 (Little endian X Server) or
01 00 00 00 (Big endian X Server) 

In the Little endian X Server case (*(char *) &whichbyte) is 01
and (!(*(char *) &whichbyte) is 00.

In the Big endian X Server case (*(char *) &whichbyte) is 00
and (!(*(char *) &whichbyte) is 01.

We try to detected the swapped case, where X Server and X client looks opsite at the byte order. Let's say that the X Server is Little endian. In that case from the previous 'if' condition ((*(char *) &whichbyte) is TRUE and (in the oposite case that X client is Big endian (prefix->byteOrder == 'B') also holds TRUE and the result is TRUE. A case that requires swapping in the client bytes is therefore detected and SwapConnClientPrefix() is used to put the bytes in order of the client prefix (the initial message).

We continue with the following part of ProcInitialConnection() code:

    stuff->reqType = 2;
    stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) +
		     ((prefix->nbytesAuthString + (unsigned)3) >> 2);

reqType becomes 2, which is the index in InitialVector[] for the ProcEstablishConnection() routine.

ProcEstablishConnection()

int
ProcEstablishConnection(register ClientPtr client)
{
    char *reason, *auth_proto, *auth_string;
    register xConnClientPrefix *prefix;
    REQUEST(xReq);

    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
    auth_proto = (char *)prefix + sz_xConnClientPrefix;
    auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3);
    if ((prefix->majorVersion != X_PROTOCOL) ||
	(prefix->minorVersion != X_PROTOCOL_REVISION))
	reason = "Protocol version mismatch";
    else
	reason = ClientAuthorized(client,
				  (unsigned short)prefix->nbytesAuthProto,
				  auth_proto,
				  (unsigned short)prefix->nbytesAuthString,
				  auth_string);
    /*
     * If Kerberos is being used for this client, the clientState
     * will be set to ClientStateAuthenticating at this point.
     * More messages need to be exchanged among the X server, Kerberos
     * server, and client to figure out if everyone is authorized.
     * So we don't want to send the connection setup info yet, since
     * the auth step isn't really done.
     */
    if (client->clientState == ClientStateCheckingSecurity)
	client->clientState = ClientStateCheckedSecurity;
    else if (client->clientState != ClientStateAuthenticating)
	return(SendConnSetup(client, reason));
    return(client->noClientException);
}

The following instruction, which is called from ProcInitialConnection():

ResetCurrentRequest(client);
causes ProcEstablishConnection() to be executed replacing ProcInitialConnection() as the current fake request. Again with the following instruction of the Dispatch() loop (see section 3.2.5):
result = (* client->requestVector[MAJOROP])(client);

ResetCurrentRequest() is implemented as:

void
ResetCurrentRequest(ClientPtr client)
{
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
    register ConnectionInputPtr oci = oc->input;
    int fd = oc->fd;
    register xReq *request;
    int gotnow, needed;
#ifdef LBX
    LbxClientPtr lbxClient = LbxClient(client);

    if (lbxClient) {
	LbxSetForBlock(lbxClient);
	if (!oci) {
	    AppendFakeRequest(client,
			      client->requestBuffer, client->req_len << 2);
	    return;
	}
    }
#endif
    if (AvailableInput == oc)
	AvailableInput = (OsCommPtr)NULL;
    oci->lenLastReq = 0;
    gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
    if (gotnow < sizeof(xReq))
    {
	YieldControlNoInput();
    }
    else
    {
	request = (xReq *)oci->bufptr;
	needed = get_req_len(request, client);
#ifdef BIGREQS
	if (!needed && client->big_requests)
	{
	    oci->bufptr -= sizeof(xBigReq) - sizeof(xReq);
	    *(xReq *)oci->bufptr = *request;
	    ((xBigReq *)oci->bufptr)->length = client->req_len;
	    if (client->swapped)
	    {
		char n;
		swapl(&((xBigReq *)oci->bufptr)->length, n);
	    }
	}
#endif
	if (gotnow >= (needed << 2))
	{
	    if (FD_ISSET(fd, &AllClients))
	    {
		FD_SET(fd, &ClientsWithInput);
	    }
	    else
	    {
		FD_SET(fd, &IgnoredClientsWithInput);
	    }
	    YieldControl();
	}
	else
	    YieldControlNoInput();
    }
}

Two are the important parts of ProcEstablishConnection():

I. The client authorization via ClientAuthorized():

/*****************************************************************
 * ClientAuthorized
 *
 *    Sent by the client at connection setup:
 *                typedef struct _xConnClientPrefix {
 *                   CARD8	byteOrder;
 *                   BYTE	pad;
 *                   CARD16	majorVersion, minorVersion;
 *                   CARD16	nbytesAuthProto;    
 *                   CARD16	nbytesAuthString;   
 *                 } xConnClientPrefix;
 *
 *     	It is hoped that eventually one protocol will be agreed upon.  In the
 *        mean time, a server that implements a different protocol than the
 *        client expects, or a server that only implements the host-based
 *        mechanism, will simply ignore this information.
 *
 *****************************************************************/

char * 
ClientAuthorized(ClientPtr client, 
    unsigned int proto_n, char *auth_proto, 
    unsigned int string_n, char *auth_string)
{
    OsCommPtr 		priv;
    Xtransaddr		*from = NULL;
    int 		family;
    int			fromlen;
    XID	 		auth_id;
    char	 	*reason = NULL;
    XtransConnInfo	trans_conn;
    int			restore_trans_conn = 0;
    ClientPtr           lbxpc = NULL;

    priv = (OsCommPtr)client->osPrivate;
    trans_conn = priv->trans_conn;

#ifdef LBX
    if (!trans_conn) {
	/*
	 * Since trans_conn is NULL, this must be a proxy's client for
	 * which we have NO address.  Therefore, we will temporarily
	 * set the client's trans_conn to the proxy's trans_conn and
	 * after CheckAuthorization the client's trans_conn will be
	 * restored. 
	 *
	 * If XDM-AUTHORIZATION-1 is being used, CheckAuthorization
	 * will eventually call XdmAuthorizationValidate and this
	 * later function may use the client's trans_conn to get the 
	 * client's address.  Since a XDM-AUTH-1 auth string includes 
	 * the client's address, this address is compared to the address 
	 * in the client's trans_conn.  If the proxy and client are 
	 * on the same host, the comparison will fail; otherwise the
	 * comparison will fail and the client will not be authorized
	 * to connect to the server.
	 *
	 * The basis for this additional code is to prevent a
	 * NULL pointer dereference of the client's trans_conn.
	 * The fundamental problem - the fact that the client's
	 * trans_conn is NULL - is because the NewClient
	 * request in version 1.0 of the LBX protocol does not
	 * send the client's address to the server.  When the
	 * spec is changed and the client's address is sent to
	 * server in the NewClient request, this additional code
	 * should be removed.
	 *
	 * See defect number XWSog08218 for more information.
	 */
	lbxpc = LbxProxyClient(priv->proxy);
	trans_conn = ((OsCommPtr)lbxpc->osPrivate)->trans_conn;
        priv->trans_conn = trans_conn;
	restore_trans_conn = 1;
    }
#endif

    auth_id = CheckAuthorization (proto_n, auth_proto,
				  string_n, auth_string, client, &reason);

#ifdef LBX
    if (! priv->trans_conn) {
	if (auth_id == (XID) ~0L && !GetAccessControl())
	    auth_id = ((OsCommPtr)lbxpc->osPrivate)->auth_id;
#ifdef XCSECURITY
	else if (auth_id != (XID) ~0L && !SecuritySameLevel(lbxpc, auth_id)) {
	    auth_id = (XID) ~0L;
	    reason = "Client trust level differs from that of LBX Proxy";
	}
#endif
    }
#endif
    if (auth_id == (XID) ~0L)
    {
	if (
#ifdef XCSECURITY	    
	    (proto_n == 0 ||
	    strncmp (auth_proto, XSecurityAuthorizationName, proto_n) != 0) &&
#endif
	    _XSERVTransGetPeerAddr (trans_conn,
	        &family, &fromlen, &from) != -1)
	{
	    if (
#ifdef LBX
		!trans_conn ||
#endif
		InvalidHost ((struct sockaddr *) from, fromlen, client))
		AuthAudit(client, FALSE, (struct sockaddr *) from,
			  fromlen, proto_n, auth_proto, auth_id);
	    else
	    {
		auth_id = (XID) 0;
		if (auditTrailLevel > 1)
		    AuthAudit(client, TRUE,
			(struct sockaddr *) from, fromlen,
			proto_n, auth_proto, auth_id);
	    }

	    xfree ((char *) from);
	}

	if (auth_id == (XID) ~0L) {
#ifdef LBX
	  /*
	   * Restore client's trans_conn state
	   */
	  if (restore_trans_conn) {
		priv->trans_conn = NULL;
	  }
#endif
	    if (reason)
		return reason;
	    else
		return "Client is not authorized to connect to Server";
	}
    }
    else if (auditTrailLevel > 1)
    {
	if (_XSERVTransGetPeerAddr (trans_conn,
	    &family, &fromlen, &from) != -1)
	{
	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
		      proto_n, auth_proto, auth_id);

	    xfree ((char *) from);
	}
    }
    priv->auth_id = auth_id;
    priv->conn_time = 0;

#ifdef XDMCP
    /* indicate to Xdmcp protocol that we've opened new client */
    XdmcpOpenDisplay(priv->fd);
#endif /* XDMCP */
#ifdef XAPPGROUP
    if (ClientStateCallback)
        XagCallClientStateChange (client);
#endif
    /* At this point, if the client is authorized to change the access control
     * list, we should getpeername() information, and add the client to
     * the selfhosts list.  It's not really the host machine, but the
     * true purpose of the selfhosts list is to see who may change the
     * access control list.
     */
#ifdef LBX
     if (restore_trans_conn) {
	priv->trans_conn = NULL;
     }
#endif
    return((char *)NULL);
}

For the Kerberos Authentication see Kerberos Authentication of X Connections.

II. The execution of the following instruction:

	return(SendConnSetup(client, reason));

SendConnSetup()

SendConnSetup() is implemented as:

int
SendConnSetup(register ClientPtr client, char *reason)
{
    register xWindowRoot *root;
    register int i;
    int numScreens;
    char* lConnectionInfo;
    xConnSetupPrefix* lconnSetupPrefix;

    if (reason)
    {
	xConnSetupPrefix csp;

	csp.success = xFalse;
	csp.lengthReason = strlen(reason);
	csp.length = (csp.lengthReason + (unsigned)3) >> 2;
	csp.majorVersion = X_PROTOCOL;
	csp.minorVersion = X_PROTOCOL_REVISION;
	if (client->swapped)
	    WriteSConnSetupPrefix(client, &csp);
	else
	    (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp);
        (void)WriteToClient(client, (int)csp.lengthReason, reason);
	return (client->noClientException = -1);
    }

    numScreens = screenInfo.numScreens;
    lConnectionInfo = ConnectionInfo;
    lconnSetupPrefix = &connSetupPrefix;

    /* We're about to start speaking X protocol back to the client by
     * sending the connection setup info.  This means the authorization
     * step is complete, and we can count the client as an
     * authorized one.
     */
    nClients++;

    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
    client->sequence = 0;
#ifdef XAPPGROUP
    XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens);
#endif
    ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask;
    ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
#ifdef MATCH_CLIENT_ENDIAN
    ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client);
    ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client);
#endif
    /* fill in the "currentInputMask" */
    root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart);
#ifdef PANORAMIX
    if (noPanoramiXExtension)
	numScreens = screenInfo.numScreens;
    else 
        numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
#endif

    for (i=0; icurrentInputMask = WindowTable[i]->eventMask |
			         wOtherEventMasks (WindowTable[i]);
	pDepth = (xDepth *)(root + 1);
	for (j = 0; j < root->nDepths; j++)
	{
	    pDepth = (xDepth *)(((char *)(pDepth + 1)) +
				pDepth->nVisuals * sizeof(xVisualType));
	}
	root = (xWindowRoot *)pDepth;
    }

    if (client->swapped)
    {
	WriteSConnSetupPrefix(client, lconnSetupPrefix);
	WriteSConnectionInfo(client,
			     (unsigned long)(lconnSetupPrefix->length << 2),
			     lConnectionInfo);
    }
    else
    {
	(void)WriteToClient(client, sizeof(xConnSetupPrefix),
			    (char *) lconnSetupPrefix);
	(void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2),
			    lConnectionInfo);
    }
    client->clientState = ClientStateRunning;
    if (ClientStateCallback)
    {
	NewClientInfoRec clientinfo;

        clientinfo.client = client; 
        clientinfo.prefix = lconnSetupPrefix;  
        clientinfo.setup = (xConnSetup *)lConnectionInfo;
	CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
    } 	
    return (client->noClientException);
}

SendConnSetup() updates the client's requestvector, which is the table with the opcodes that correspond to a client's request to either SwappedProcVector or ProcVector:

 client->requestVector = client->swapped ? SwappedProcVector : ProcVector;

Both tables ProcVector, which provides the functions that server the client request using as index the reqType for client messages that need not swapping in their byte order the and SwappedProcVector which is the table for swapped clients are found in tables.c.

Also SendConnSetup() uses WriteToClient() to send a reply of the form xConnSetupPrefix and establish the connection.

typedef struct {
    CARD8          success;
    BYTE           lengthReason; /*num bytes in string following if failure */
    CARD16         majorVersion B16, 
                   minorVersion B16;
    CARD16         length B16;  /* 1/4 additional bytes in setup info */
} xConnSetupPrefix;

REFERENCES:

Xserver man page