/* * TV_Downstream_UserinfoCommand_f */ static void TV_Downstream_UserinfoCommand_f( client_t *client ) { char *info; info = Cmd_Argv( 1 ); if( !Info_Validate( info ) ) { TV_Downstream_DropClient( client, DROP_TYPE_GENERAL, "Error: Invalid userinfo" ); return; } Q_strncpyz( client->userinfo, info, sizeof( client->userinfo ) ); TV_Downstream_UserinfoChanged( client ); }
/* * TV_Relay_ClientConnect */ void TV_Relay_ClientConnect( relay_t *relay, client_t *client ) { int edictnum; assert( relay ); assert( relay->module_export ); assert( client ); edictnum = client - tvs.clients; client->edict = LOCAL_EDICT_NUM( relay, edictnum ); client->relay = relay; relay->module_export->ClientConnect( relay->module, client->edict, client->userinfo ); relay->num_active_specs++; // update the upstream name to "name (no_of_players)" TV_Relay_UpstreamUserinfoChanged( relay ); // parse some info from the info strings TV_Downstream_UserinfoChanged( client ); }
/* * 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; }