+ case CCREQ_CONNECT:
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2);
+ if (length < (int)strlen("QUAKE") + 1 + 1)
+ break;
+
+ if (memcmp(data, "QUAKE", strlen("QUAKE") + 1) != 0 || (int)data[strlen("QUAKE") + 1] != NET_PROTOCOL_VERSION)
+ {
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2);
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_REJECT);
+ MSG_WriteString(&net_message, "Incompatible version.\n");
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+ break;
+ }
+
+ // see if this connect request comes from a known client
+ for (clientnum = 0, client = svs.clients;clientnum < svs.maxclients;clientnum++, client++)
+ {
+ if (client->netconnection && LHNETADDRESS_Compare(peeraddress, &client->netconnection->peeraddress) == 0)
+ {
+ // this is either a duplicate connection request
+ // or coming back from a timeout
+ // (if so, keep their stuff intact)
+
+ // send a reply
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2);
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_ACCEPT);
+ MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(client->netconnection->mysocket)));
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+
+ // if client is already spawned, re-send the
+ // serverinfo message as they'll need it to play
+ if (client->spawned)
+ SV_SendServerinfo(client);
+ return true;
+ }
+ }
+
+ // this is a new client, check for connection flood
+ if (NetConn_PreventConnectFlood(peeraddress))
+ break;
+
+ // find a slot for the new client
+ for (clientnum = 0, client = svs.clients;clientnum < svs.maxclients;clientnum++, client++)
+ {
+ netconn_t *conn;
+ if (!client->active && (client->netconnection = conn = NetConn_Open(mysocket, peeraddress)) != NULL)
+ {
+ // connect to the client
+ // everything is allocated, just fill in the details
+ strlcpy (conn->address, addressstring2, sizeof (conn->address));
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
+ // send back the info about the server connection
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_ACCEPT);
+ MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(conn->mysocket)));
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+ // now set up the client struct
+ SV_VM_Begin();
+ SV_ConnectClient(clientnum, conn);
+ SV_VM_End();
+ NetConn_Heartbeat(1);
+ return true;
+ }
+ }
+
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2);
+ // no room; try to let player know
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_REJECT);
+ MSG_WriteString(&net_message, "Server is full.\n");
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+ break;
+ case CCREQ_SERVER_INFO:
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
+ if (sv.active && !strcmp(MSG_ReadString(), "QUAKE"))
+ {
+ int numclients;
+ char myaddressstring[128];
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2);
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
+ LHNETADDRESS_ToString(LHNET_AddressFromSocket(mysocket), myaddressstring, sizeof(myaddressstring), true);
+ MSG_WriteString(&net_message, myaddressstring);
+ MSG_WriteString(&net_message, hostname.string);
+ MSG_WriteString(&net_message, sv.name);
+ // How many clients are there?
+ for (i = 0, numclients = 0;i < svs.maxclients;i++)
+ if (svs.clients[i].active)
+ numclients++;
+ MSG_WriteByte(&net_message, numclients);
+ MSG_WriteByte(&net_message, svs.maxclients);
+ MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+ }
+ break;
+ case CCREQ_PLAYER_INFO:
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2);
+ if (sv.active)
+ {
+ int playerNumber, activeNumber, clientNumber;
+ client_t *client;
+
+ playerNumber = MSG_ReadByte();
+ activeNumber = -1;
+ for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
+ if (client->active && ++activeNumber == playerNumber)
+ break;
+ if (clientNumber != svs.maxclients)
+ {
+ SZ_Clear(&net_message);
+ // save space for the header, filled in later
+ MSG_WriteLong(&net_message, 0);
+ MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
+ MSG_WriteByte(&net_message, playerNumber);
+ MSG_WriteString(&net_message, client->name);
+ MSG_WriteLong(&net_message, client->colors);
+ MSG_WriteLong(&net_message, (int)client->edict->fields.server->frags);
+ MSG_WriteLong(&net_message, (int)(realtime - client->connecttime));
+ MSG_WriteString(&net_message, client->netconnection ? client->netconnection->address : "botclient");
+ *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+ SZ_Clear(&net_message);
+ }
+ }
+ break;
+ case CCREQ_RULE_INFO:
+ if (developer.integer >= 10)
+ Con_Printf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2);
+ if (sv.active)