/* * 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; }