void NET_Shutdown (void) { qsocket_t *sock; SetNetTime(); for (sock = net_activeSockets; sock; sock = sock->next) NET_Close(sock); // // shutdown the drivers // for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++) { if (net_drivers[net_driverlevel].initialized == true) { net_drivers[net_driverlevel].Shutdown (); net_drivers[net_driverlevel].initialized = false; } } if (vcrFile != -1) { Con_Printf ("Closing vcrfile.\n"); Sys_FileClose(vcrFile); } }
/* ===================== CL_Disconnect Sends a disconnect message to the server This is also called on Host_Error, so it shouldn't cause any errors ===================== */ void CL_Disconnect(void) { // stop sounds (especially looping!) S_StopAllSounds(true); /* Clear up view, remove palette shift */ scr_centertime_off = 0; cl.cshifts[0].percent = 0; VID_SetPalette(host_basepal); // if running a local server, shut it down if (cls.demoplayback) CL_StopPlayback(); else if (cls.state >= ca_connected) { if (cls.demorecording) CL_Stop_f(); Con_DPrintf("Sending clc_disconnect\n"); SZ_Clear(&cls.message); MSG_WriteByte(&cls.message, clc_disconnect); NET_SendUnreliableMessage(cls.netcon, &cls.message); SZ_Clear(&cls.message); NET_Close(cls.netcon); cls.state = ca_disconnected; if (sv.active) Host_ShutdownServer(false); } cls.demoplayback = false; cls.timedemo = false; cls.signon = 0; cl.intermission = 0; /* FIXME - for SCR_UpdateScreen */ }
/** * Sends a disconnect message to the server * This is also called on Host_Error, so it shouldn't cause any errors */ void CL_Disconnect(void) { // stop sounds (especially looping!) S_StopAllSounds(true); // bring the console down and fade the colors back to normal // SCR_BringDownConsole (); // if running a local server, shut it down if (cls.demoplayback) CL_StopPlayback(); else if (cls.state == ca_connected) { if (cls.demorecording) CL_Stop_f(); Con_DPrintf("Sending clc_disconnect\n"); SZ_Clear(&cls.message); MSG_WriteByte(&cls.message, clc_disconnect); NET_SendUnreliableMessage(cls.netcon, &cls.message); SZ_Clear(&cls.message); NET_Close(cls.netcon); cls.state = ca_disconnected; if (sv.active) Host_ShutdownServer(false); } cls.demoplayback = cls.timedemo = false; cls.signon = 0; }
/* ===================== SV_DropClient Called when the player is getting totally kicked off the host if (crash = true), don't bother sending signofs ===================== */ void SV_DropClient (bool crash) { int saveSelf; int i; client_t *client; if (!host_client->active) return; if (!crash) { // send any final messages (don't check for errors) if (NET_CanSendMessage (host_client->netconnection)) { MSG_WriteByte (&host_client->message, svc_disconnect); NET_SendMessage (host_client->netconnection, &host_client->message); } if (host_client->edict && host_client->spawned) { // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram (pr_global_struct->ClientDisconnect); pr_global_struct->self = saveSelf; } Sys_Printf ("Client %s removed\n",host_client->name); } /*if (host_client->netconnection->proquake_connection == MOD_QSMACK) qsmackActive = false;*/ // break the net connection NET_Close (host_client->netconnection); host_client->netconnection = NULL; // free the client (the body stays around) host_client->active = false; host_client->name[0] = 0; host_client->old_frags = -999999; net_activeconnections--; // send notification to all clients for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++) { if (!client->active) continue; MSG_WriteByte (&client->message, svc_updatename); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteString (&client->message, ""); MSG_WriteByte (&client->message, svc_updatefrags); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteShort (&client->message, 0); MSG_WriteByte (&client->message, svc_updatecolors); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteByte (&client->message, 0); } }
void NET_Shutdown (void) { qsocket_t *sock; SetNetTime(); for (sock = net_activeSockets; sock; sock = sock->next) NET_Close(sock); // shutdown the drivers for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++) if (net_drivers[net_driverlevel].initialized == TRUE) { net_drivers[net_driverlevel].Shutdown (); net_drivers[net_driverlevel].initialized = FALSE; } }
int NET_GetMessage (qsocket_t *sock) { int ret; if (!sock) return -1; if (sock->disconnected) { Con_Printf("NET_GetMessage: disconnected socket\n"); return -1; } SetNetTime(); ret = sfunc.QGetMessage(sock); // see if this connection has timed out if (ret == 0 && sock->driver) { if (net_time - sock->lastMessageTime > net_messagetimeout.value) { NET_Close(sock); return -1; } } if (ret > 0) { if (sock->driver) { sock->lastMessageTime = net_time; if (ret == 1) messagesReceived++; else if (ret == 2) unreliableMessagesReceived++; } } return ret; }
/* * ==================== * NET_Shutdown * ==================== */ void NET_Shutdown(void) { int i; qsocket_t *sock; SetNetTime(); for (sock = net_activeSockets; sock; sock = sock->next) NET_Close(sock); /* * shutdown the drivers */ for (i = 0; i < net_numdrivers; i++) { net_driver = &net_drivers[i]; if (net_driver->initialized == true) { net_driver->Shutdown(); net_driver->initialized = false; } } }
/* * ================= * NET_GetMessage * * If there is a complete message, return it in net_message * * returns 0 if no data is waiting * returns 1 if a message was received * returns -1 if connection is invalid * ================= */ int NET_GetMessage(qsocket_t *sock) { int ret; if (!sock) return -1; if (sock->disconnected) { Con_Printf("%s: disconnected socket\n", __func__); return -1; } SetNetTime(); ret = sock->driver->QGetMessage(sock); /* see if this connection has timed out (not for loop) */ if (ret == 0 && (!IS_LOOP_DRIVER(sock->driver))) { if (net_time - sock->lastMessageTime > net_messagetimeout.value) { NET_Close(sock); return -1; } } if (ret > 0) { if (!IS_LOOP_DRIVER(sock->driver)) { sock->lastMessageTime = net_time; if (ret == 1) messagesReceived++; else if (ret == 2) unreliableMessagesReceived++; } } return ret; }
int NET_GetMessage (qsocket_t *sock) { int ret; if (!sock) return -1; if (sock->disconnected) { Con_Printf("NET_GetMessage: disconnected socket\n"); return -1; } SetNetTime(); ret = sfunc.QGetMessage(sock); // see if this connection has timed out if (ret == 0 && sock->driver) { if (net_time - sock->lastMessageTime > net_messagetimeout.value) { NET_Close(sock); return -1; } } if (ret > 0) { if (sock->driver) { sock->lastMessageTime = net_time; if (ret == 1) messagesReceived++; else if (ret == 2) unreliableMessagesReceived++; } if (recording) { vcrGetMessage.time = host_time; vcrGetMessage.op = VCR_OP_GETMESSAGE; vcrGetMessage.session = (long)sock; vcrGetMessage.ret = ret; vcrGetMessage.len = net_message.cursize; Sys_FileWrite (vcrFile, &vcrGetMessage, 24); Sys_FileWrite (vcrFile, net_message.data, net_message.cursize); } } else { if (recording) { vcrGetMessage.time = host_time; vcrGetMessage.op = VCR_OP_GETMESSAGE; vcrGetMessage.session = (long)sock; vcrGetMessage.ret = ret; Sys_FileWrite (vcrFile, &vcrGetMessage, 20); } } return ret; }
static qsocket_t *_Datagram_CheckNewConnections (void) { struct qsockaddr clientaddr; struct qsockaddr newaddr; int newsock; int acceptsock; qsocket_t *sock; qsocket_t *s; int len; int command; int control; int ret; acceptsock = dfunc.CheckNewConnections(); if (acceptsock == -1) return NULL; SZ_Clear(&net_message); len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); if (len < sizeof(int)) return NULL; net_message.cursize = len; MSG_BeginReading (); control = BigLong(*((int *)net_message.data)); MSG_ReadLong(); if (control == -1) return NULL; if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) return NULL; if ((control & NETFLAG_LENGTH_MASK) != len) return NULL; command = MSG_ReadByte(); if (command == CCREQ_SERVER_INFO) { if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) return NULL; SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_SERVER_INFO); dfunc.GetSocketAddr(acceptsock, &newaddr); MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); MSG_WriteString(&net_message, hostname.string); MSG_WriteString(&net_message, sv.name); MSG_WriteByte(&net_message, net_activeconnections); 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)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command == CCREQ_PLAYER_INFO) { int playerNumber; int activeNumber; int clientNumber; client_t *client; playerNumber = MSG_ReadByte(); activeNumber = -1; for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) { if (client->active) { activeNumber++; if (activeNumber == playerNumber) break; } } if (clientNumber == svs.maxclients) return NULL; 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->v.frags); MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); MSG_WriteString(&net_message, client->netconnection->address); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command == CCREQ_RULE_INFO) { char *prevCvarName; cvar_t *var; // find the search start location prevCvarName = MSG_ReadString(); if (*prevCvarName) { var = Cvar_FindVar (prevCvarName); if (!var) return NULL; var = var->next; } else var = cvar_vars; // search for the next server cvar while (var) { if (var->server) break; var = var->next; } // send the response SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_RULE_INFO); if (var) { MSG_WriteString(&net_message, var->name); MSG_WriteString(&net_message, var->string); } *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } if (command != CCREQ_CONNECT) return NULL; if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) return NULL; if (MSG_ReadByte() != NET_PROTOCOL_VERSION) { 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)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } #ifdef BAN_TEST // check for a ban if (clientaddr.sa_family == AF_INET) { unsigned long testAddr; testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; if ((testAddr & banMask) == banAddr) { 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, "You have been banned.\n"); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } } #endif // see if this guy is already connected for (s = net_activeSockets; s; s = s->next) { if (s->driver != net_driverlevel) continue; ret = dfunc.AddrCompare(&clientaddr, &s->addr); if (ret >= 0) { // is this a duplicate connection reqeust? if (ret == 0 && net_time - s->connecttime < 2.0) { // yes, so send a duplicate reply SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); dfunc.GetSocketAddr(s->socket, &newaddr); MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } // it's somebody coming back in from a crash/disconnect // so close the old qsocket and let their retry get them back in NET_Close(s); return NULL; } } // allocate a QSocket sock = NET_NewQSocket (); if (sock == NULL) { // no room; try to let him 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)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return NULL; } // allocate a network socket newsock = dfunc.OpenSocket(0); if (newsock == -1) { NET_FreeQSocket(sock); return NULL; } // connect to the client if (dfunc.Connect (newsock, &clientaddr) == -1) { dfunc.CloseSocket(newsock); NET_FreeQSocket(sock); return NULL; } // everything is allocated, just fill in the details sock->socket = newsock; sock->landriver = net_landriverlevel; sock->addr = clientaddr; Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr)); // send him back the info about the server connection he has been allocated SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); dfunc.GetSocketAddr(newsock, &newaddr); MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); // MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); SZ_Clear(&net_message); return sock; }
/* ===================== SV_DropClient Called when the player is getting totally kicked off the host if (crash = true), don't bother sending signofs ===================== */ void SV_DropClient (qboolean crash) { int saveSelf; int i; client_t *client; // JPG 3.00 - don't drop a client that's already been dropped! if (!host_client->active) return; if (!crash) { // send any final messages (don't check for errors) if (NET_CanSendMessage (host_client->netconnection)) { MSG_WriteByte (&host_client->message, svc_disconnect); NET_SendMessage (host_client->netconnection, &host_client->message); } if (host_client->edict && host_client->spawned) { // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram (pr_global_struct->ClientDisconnect); pr_global_struct->self = saveSelf; } // Slot Zero 3.50-2 Added edict to client removed message. if (pq_showedict.value) Sys_Printf("#%d ", NUM_FOR_EDICT(host_client->edict)); Sys_Printf ("Client %s removed\n",host_client->name); } // JPG 3.00 - check to see if it's a qsmack client if (host_client->netconnection->mod == MOD_QSMACK) qsmackActive = false; // break the net connection NET_Close (host_client->netconnection); host_client->netconnection = NULL; // free the client (the body stays around) host_client->active = false; host_client->name[0] = 0; host_client->old_frags = -999999; net_activeconnections--; // send notification to all clients for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++) { if (!client->active) continue; MSG_WriteByte (&client->message, svc_updatename); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteString (&client->message, ""); MSG_WriteByte (&client->message, svc_updatefrags); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteShort (&client->message, 0); MSG_WriteByte (&client->message, svc_updatecolors); MSG_WriteByte (&client->message, host_client - svs.clients); MSG_WriteByte (&client->message, 0); } }
int NET_GetMessage (qsocket_t *sock) { int ret; if (!sock) return -1; if (sock->disconnected) { Con_Printf("NET_GetMessage: disconnected socket\n"); return -1; } SetNetTime(); ret = sfunc.QGetMessage(sock); // see if this connection has timed out if (ret == 0 && sock->driver) { /* RFC: Why doesn't this work!!! It's the same... or not?? Since when I compile it it evaluates the if body even if it's a smaller number... if ((net_time - sock->lastMessageTime) > (double)net_messagetimeout.value) { Con_Printf("*** Connection timed out after %f s of inactivity (max is %f)\n",delta,net_messagetimeout.value); //NET_Close(sock); //return -1; } */ float delta = (net_time - sock->lastMessageTime); if (delta > net_messagetimeout.value) { Con_Printf("*** Connection timed out after %f s of inactivity (max is %f)\n",delta,net_messagetimeout.value); NET_Close(sock); return -1; } } if (ret > 0) { if (sock->driver) { sock->lastMessageTime = net_time; if (ret == 1) messagesReceived++; else if (ret == 2) unreliableMessagesReceived++; } if (recording) { vcrGetMessage.time = host_time; vcrGetMessage.op = VCR_OP_GETMESSAGE; vcrGetMessage.session = (long)sock; vcrGetMessage.ret = ret; vcrGetMessage.len = net_message.cursize; Sys_FileWrite (vcrFile, &vcrGetMessage, 24); Sys_FileWrite (vcrFile, net_message.data, net_message.cursize); } } else { if (recording) { vcrGetMessage.time = host_time; vcrGetMessage.op = VCR_OP_GETMESSAGE; vcrGetMessage.session = (long)sock; vcrGetMessage.ret = ret; Sys_FileWrite (vcrFile, &vcrGetMessage, 20); } } return ret; }