test network 3
[carveJwlIkooP6JGAAIwe30JlM.git] / gameserver.c
index c63711ab30883f6cfcea0d17f09e2f5b611635f7..e2082cb39fc77f82ff2d0664a235b2aad0cfa6f3 100644 (file)
@@ -34,21 +34,107 @@ static void set_connection_authsteamid(HSteamNetConnection con, u64_steamid id){
          hSteamNetworkingSockets, con, userdata );
 }
 
+static void gameserver_send_to_all( int ignore, 
+                                    const void *pData, u32 cbData, 
+                                    int nSendFlags ){
+   for( int i=0; i<vg_list_size(gameserver.clients); i++ ){
+      struct gameserver_client *client = &gameserver.clients[i];
+
+      if( (i==ignore) || !client->active )
+         continue;
+
+      SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+            hSteamNetworkingSockets, client->connection,
+            pData, cbData, nSendFlags, NULL );
+   }
+}
+
+static void gameserver_populate_join_msg( int index, netmsg_playerjoin *msg ){
+   memset( msg, 0, sizeof(*msg) );
+   msg->inetmsg_id = k_inetmsg_playerjoin;
+   msg->index = index;
+   vg_strncpy( gameserver.clients[index].username, msg->username, 
+               sizeof(msg->username), k_strncpy_always_add_null );
+}
+
+static void gameserver_player_join( int index ){
+   struct gameserver_client *joiner = &gameserver.clients[index];
+   
+   netmsg_playerjoin join;
+   gameserver_populate_join_msg( index, &join );
+   gameserver_send_to_all( index, &join, sizeof(join),
+                           k_nSteamNetworkingSend_Reliable );
+
+   /* update the joining user about current connections */
+   for( int i=0; i<vg_list_size(gameserver.clients); i++ ){
+      struct gameserver_client *client = &gameserver.clients[i];
+
+      if( (i==index) || !client->active )
+         continue;
+
+      netmsg_playerjoin init;
+      gameserver_populate_join_msg( i, &init );
+
+      SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+            hSteamNetworkingSockets, joiner->connection,
+            &join, sizeof(join), k_nSteamNetworkingSend_Reliable, NULL );
+   }
+}
+
+static void gameserver_player_leave( int index ){
+   netmsg_playerjoin leave;
+   leave.inetmsg_id = k_inetmsg_playerleave;
+   leave.index = index;
+
+   vg_info( "Player leave (%d)\n", index );
+   gameserver_send_to_all( index, &leave, sizeof(leave),
+                           k_nSteamNetworkingSend_Reliable );
+}
+
 static void new_client_connecting( HSteamNetConnection client ){
+   int index = -1;
+
+   /* TODO: LRU */
+   for( int i=0; i<vg_list_size(gameserver.clients); i++ ){
+      if( !gameserver.clients[i].active ){
+         index = i;
+         break;
+      }
+   }
+
+   if( index == -1 ){
+      vg_error( "Server full\n" );
+      SteamAPI_ISteamNetworkingSockets_CloseConnection( 
+            hSteamNetworkingSockets, client, 
+            4500,
+            NULL, 1 );
+      return;
+   }
+
    EResult accept_status = SteamAPI_ISteamNetworkingSockets_AcceptConnection(
             hSteamNetworkingSockets, client );
-
    if( accept_status == k_EResultOK ){
-      vg_success( "Accepted client (id: %u)\n", client );
+      vg_success( "Accepted client (id: %u, index: %d)\n", client, index );
+
+      gameserver.clients[index].active = 1;
+      gameserver.clients[index].connection = client;
+
       SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup(
             hSteamNetworkingSockets,
             client, gameserver.client_group );
       
       /* Just to be sure */
       set_connection_authsteamid( client, -1 );
+      gameserver_player_join( index );
    }
    else{
       vg_warn( "Error accepting client (id: %u)\n", client );
+      SteamAPI_ISteamNetworkingSockets_CloseConnection( 
+            hSteamNetworkingSockets, client, 
+            k_ESteamNetConnectionEnd_Misc_InternalError,
+            NULL, 1 );
+      gameserver.clients[index].active = 0;
+      gameserver.clients[index].connection = 0;
    }
 }
 
@@ -59,6 +145,19 @@ static void on_auth_status( CallbackMsg_t *msg ){
    vg_info( "  %s\n", info->m_debugMsg );
 }
 
+static int gameserver_client_index( HSteamNetConnection hconn ){
+   for( int i=0; i<vg_list_size(gameserver.clients); i++ ){
+      struct gameserver_client *client = &gameserver.clients[i];
+
+      if( client->active ){
+         if( client->connection == hconn ){
+            return i;
+         }
+      }
+   }
+   return -1;
+}
+
 static void on_connect_status( CallbackMsg_t *msg ){
    SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
    vg_info( "  Connection status changed for %lu\n", info->m_hConn );
@@ -70,9 +169,27 @@ static void on_connect_status( CallbackMsg_t *msg ){
    if( info->m_info.m_eState==k_ESteamNetworkingConnectionState_Connecting ){
       new_client_connecting( info->m_hConn );
    }
+
+   if( (info->m_info.m_eState == 
+            k_ESteamNetworkingConnectionState_ClosedByPeer ) ||
+       (info->m_info.m_eState == 
+        k_ESteamNetworkingConnectionState_ProblemDetectedLocally ) ){
+
+      int client_id = gameserver_client_index( info->m_hConn );
+      if( client_id != -1 ){
+         struct gameserver_client *client = &gameserver.clients[client_id];
+         client->connection = 0;
+         client->active = 0;
+         gameserver_player_leave(client_id);
+      }
+
+      vg_info( "End reason: %d\n", info->m_info.m_eEndReason );
+      SteamAPI_ISteamNetworkingSockets_CloseConnection( 
+            hSteamNetworkingSockets, info->m_hConn, 0, NULL, 0 );
+   }
 }
 
-static void on_inet_auth( SteamNetworkingMessage_t *msg ){
+static void gameserver_rx_auth( SteamNetworkingMessage_t *msg ){
    if( gameserver.auth_mode != eServerModeAuthentication ){
       vg_error( "Running server without authentication. "
                 "Connection %u tried to authenticate.\n", msg->m_conn );
@@ -150,7 +267,7 @@ static int inet_require_auth( SteamNetworkingMessage_t *msg ){
 
    if( get_connection_authsteamid( msg ) == k_connection_unauthorized ){
       vg_warn( "Unauthorized request! Disconnecting client: %u\n", 
-            msg->m_conn );
+               msg->m_conn );
 
       SteamAPI_ISteamNetworkingSockets_CloseConnection(
             hSteamNetworkingSockets,
@@ -161,6 +278,51 @@ static int inet_require_auth( SteamNetworkingMessage_t *msg ){
    else return 1;
 }
 
+/*
+ * Player updates sent to us
+ * -----------------------------------------------------------------------------
+ */
+
+static int packet_minsize( SteamNetworkingMessage_t *msg, u32 size ){
+   if( msg->m_cbSize < size ) {
+      vg_error( "Invalid packet size (must be at least %u)\n", size );
+      return 0;
+   }
+   else{
+      return 1;
+   }
+}
+
+static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){
+   netmsg_blank *tmp = msg->m_pData;
+
+   if( tmp->inetmsg_id == k_inetmsg_playerusername ){
+      if( !packet_minsize( msg, sizeof(netmsg_playerusername) ))
+         return;
+      
+      int client_id = gameserver_client_index( msg->m_conn );
+      if( client_id != -1 ){
+         struct gameserver_client *client = &gameserver.clients[ client_id ];
+         netmsg_playerusername *src = msg->m_pData;
+
+         vg_strncpy( src->username, client->username, sizeof(client->username),
+                     k_strncpy_always_add_null );
+
+         /* update other users about this change */
+         netmsg_playerusername msg;
+         memset( &msg, 0, sizeof(msg) );
+         msg.inetmsg_id = k_inetmsg_playerusername;
+         msg.index = client_id;
+         vg_strncpy( client->username, msg.username, sizeof(msg.username),
+                     k_strncpy_always_add_null );
+
+         gameserver_send_to_all( client_id, &msg, sizeof(msg), 
+                                 k_nSteamNetworkingSend_Reliable );
+      }
+   }
+}
+
+#if 0
 static void on_inet_score_request( SteamNetworkingMessage_t *msg ){
    if( !inet_require_auth(msg) ) return;
 
@@ -215,18 +377,7 @@ static void on_inet_set_score( SteamNetworkingMessage_t *msg ){
       highscores_push_record( &temp );
    }
 }
-
-static void on_inet_playerframe( SteamNetworkingMessage_t *msg ){
-   if( msg->m_cbSize < sizeof(netmsg_playerframe) ){
-      return;
-   }
-
-
-   netmsg_playerframe *info = msg->m_pData;
-   vg_info( "... @: %.2f %.2f %.2f\n", 
-               //msg->m_identityPeer,
-               info->pos_temp[0], info->pos_temp[1], info->pos_temp[2] );
-}
+#endif
 
 static void poll_connections(void){
    SteamNetworkingMessage_t *messages[32];
@@ -251,21 +402,29 @@ static void poll_connections(void){
 
          netmsg_blank *tmp = msg->m_pData;
 
-         if( tmp->inetmsg_id == k_inetmsg_auth )
-            on_inet_auth( msg );
-         else if( tmp->inetmsg_id == k_inetmsg_scores_request )
-            on_inet_score_request( msg );
-         else if( tmp->inetmsg_id == k_inetmsg_set_nickname )
-            on_inet_set_nickname( msg );
-         else if( tmp->inetmsg_id == k_inetmsg_set_score )
-            on_inet_set_score( msg );
-         else if( tmp->inetmsg_id == k_inetmsg_playerframe )
-            on_inet_playerframe( msg );
-         else {
-            vg_warn( "Unknown inetmsg_id recieved from client. (%u)\n",
-                     tmp->inetmsg_id );
+         if( (tmp->inetmsg_id >= 200) && (tmp->inetmsg_id < 300) ){
+            gameserver_rx_200_300( msg );
+         }
+         else{
+            if( tmp->inetmsg_id == k_inetmsg_auth )
+               gameserver_rx_auth( msg );
+#if 0
+            else if( tmp->inetmsg_id == k_inetmsg_scores_request )
+               on_inet_score_request( msg );
+            else if( tmp->inetmsg_id == k_inetmsg_set_nickname )
+               on_inet_set_nickname( msg );
+            else if( tmp->inetmsg_id == k_inetmsg_set_score )
+               on_inet_set_score( msg );
+            else if( tmp->inetmsg_id == k_inetmsg_playerframe )
+               on_inet_playerframe( msg );
+#endif
+            else {
+               vg_warn( "Unknown inetmsg_id recieved from client. (%u)\n",
+                        tmp->inetmsg_id );
+            }
          }
 
+
          SteamAPI_SteamNetworkingMessage_t_Release( msg );
       }
    }