/* * TV_Downstream_ChangeStream */ qboolean TV_Downstream_ChangeStream( client_t *client, relay_t *relay ) { relay_t *oldrelay; assert( client ); oldrelay = client->relay; if( relay ) { if( !TV_Relay_CanConnect( relay, client, client->userinfo ) ) return qfalse; } else { if( !TV_Lobby_CanConnect( client, client->userinfo ) ) return qfalse; } if( oldrelay ) TV_Relay_ClientDisconnect( oldrelay, client ); else TV_Lobby_ClientDisconnect( client ); TV_Downstream_ClientResetCommandBuffers( client, qfalse ); if( relay ) TV_Relay_ClientConnect( relay, client ); else TV_Lobby_ClientConnect( client ); TV_Downstream_SendServerCommand( client, "changing" ); TV_Downstream_SendServerCommand( client, "reconnect" ); client->state = CS_CONNECTED; return qtrue; }
/* * TV_Downstream_ClientConnect */ static bool TV_Downstream_ClientConnect( const socket_t *socket, const netadr_t *address, client_t *client, char *userinfo, int game_port, int challenge, bool tv_client ) { assert( socket ); assert( address ); assert( client ); assert( userinfo ); // it may actually happen that we reuse a client slot (same IP, same port), // which is "attached" to an active relay, so we need to notify the relay that client // isn't active anymore, otherwise it'll get confused after we set the client's state // to CS_CONNECTING down below if( client->relay ) TV_Relay_ClientDisconnect( client->relay, client ); if( !TV_Lobby_CanConnect( client, userinfo ) ) return false; TV_Lobby_ClientConnect( client ); // the upstream is accepted, set up the client slot client->challenge = challenge; // save challenge for checksumming client->tv = (tv_client ? true : false); switch( socket->type ) { #ifdef TCP_ALLOW_TVCONNECT case SOCKET_TCP: client->reliable = true; client->individual_socket = true; client->socket = *socket; break; #endif case SOCKET_UDP: case SOCKET_LOOPBACK: client->reliable = false; client->individual_socket = false; client->socket.open = false; break; default: assert( false ); } TV_Downstream_ClientResetCommandBuffers( client, true ); // reset timeouts client->lastPacketReceivedTime = tvs.realtime; client->lastconnect = tvs.realtime; // init the upstream client->state = CS_CONNECTING; if( client->individual_socket ) Netchan_Setup( &client->netchan, &client->socket, address, game_port ); else Netchan_Setup( &client->netchan, socket, address, game_port ); // parse some info from the info strings Q_strncpyz( client->userinfo, userinfo, sizeof( client->userinfo ) ); TV_Downstream_UserinfoChanged( client ); Com_Printf( "%s" S_COLOR_WHITE " connected\n", client->name ); return true; }
/* * TV_Downstream_DropClient */ void TV_Downstream_DropClient( client_t *drop, int type, const char *format, ... ) { va_list argptr; char string[1024]; msg_t Message; qbyte MessageData[MAX_MSGLEN]; va_start( argptr, format ); Q_vsnprintfz( string, sizeof( string ), format, argptr ); va_end( argptr ); Com_Printf( "%s" S_COLOR_WHITE " dropped: %s\n", drop->name, string ); TV_Downstream_InitClientMessage( drop, &Message, MessageData, sizeof( MessageData ) ); TV_Downstream_SendServerCommand( drop, "disconnect %i \"%s\"", type, string ); TV_Downstream_AddReliableCommandsToMessage( drop, &Message ); TV_Downstream_SendMessageToClient( drop, &Message ); Netchan_PushAllFragments( &drop->netchan ); if( drop->relay && /*drop->relay->state == CA_ACTIVE && */drop->state >= CS_CONNECTING ) TV_Relay_ClientDisconnect( drop->relay, drop ); // make sure everything is clean TV_Downstream_ClientResetCommandBuffers( drop, qtrue ); SNAP_FreeClientFrames( drop ); if( drop->download.name ) { if( drop->download.data ) { FS_FreeBaseFile( drop->download.data ); drop->download.data = NULL; } Mem_ZoneFree( drop->download.name ); drop->download.name = NULL; drop->download.size = 0; drop->download.timeout = 0; } if( drop->individual_socket ) NET_CloseSocket( &drop->socket ); if( drop->mv ) { tvs.nummvclients--; drop->mv = qfalse; } memset( &drop->flood, 0, sizeof( drop->flood ) ); drop->edict = NULL; drop->relay = NULL; drop->tv = qfalse; drop->state = CS_ZOMBIE; // become free in a few seconds drop->name[0] = 0; }