IpDrv
Class UdpServerQuery

source: C:\XIII\IpDrv\Classes\UDPSERVERQUERY.UC
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Info
         |
         +--Engine.InternetInfo
            |
            +--IpDrv.InternetLink
               |
               +--IpDrv.UdpLink
                  |
                  +--IpDrv.UdpServerQuery
Direct Known Subclasses:None

class UdpServerQuery
extends IpDrv.UdpLink

//============================================================================= // UdpServerQuery // // Version: 1.5 // // This query server is compliant with the GameSpy Uplink Specification. // The specification is available at http://www.gamespy.com/developer // and might be of use to progammers who are writing or maintaining // their own stat gathering/game querying software. // // Note: Currently, SendText returns false if successful. // // Full documentation on this class is available at http://unreal.epicgames.com/ // //=============================================================================
Variables
 int CurrentQueryNum
           Query ID Number.
 string GameName
           Query ID Number.
 int MinNetVer
           Query ID Number.
 name QueryName
           Name to set this object's Tag to.
 string ReplyData
           Query ID Number.


Function Summary
 string GetBasic()
     
// Return a string of basic information.
 string GetGameProperty(string Prop)
     
// Get an arbitrary property from the game object.
 string GetInfo()
     
// Return a string of important system information.
 string GetLevelProperty(string Prop)
     
// Get an arbitrary property from the level object.
 string GetPlayer(Controller P, int PlayerNum)
     
// Return a string of information on a player.
 string GetPlayerProperty(string Prop)
     
// Get an arbitrary property from the players.
 string GetRules()
     
// Return a string of miscellaneous information.
// Game specific information, user defined data, custom parameters for the command line.
 bool ParseNextQuery(string Query, out string, out string, out string, out int)
 string ParseQuery(IpAddr Addr, string Query, int QueryNum, out int)
 void PostBeginPlay()
 void PreBeginPlay()
     
// Initialize.
 bool SendAPacket(IpAddr Addr, int QueryNum, out int, int bFinalPacket)
 bool SendPlayers(IpAddr Addr, int QueryNum, out int, int bFinalPacket)
     
// Send data for each player
 bool SendQueryPacket(IpAddr Addr, string SendString, int QueryNum, out int, int bFinalPacket)
     
// SendQueryPacket is a wrapper for SendText that allows for packet numbering.



Source Code


00001	//=============================================================================
00002	// UdpServerQuery
00003	//
00004	// Version: 1.5
00005	//
00006	// This query server is compliant with the GameSpy Uplink Specification.
00007	// The specification is available at http://www.gamespy.com/developer
00008	// and might be of use to progammers who are writing or maintaining
00009	// their own stat gathering/game querying software.
00010	//
00011	// Note: Currently, SendText returns false if successful.
00012	//
00013	// Full documentation on this class is available at http://unreal.epicgames.com/
00014	//
00015	//=============================================================================
00016	class UdpServerQuery extends UdpLink config;
00017	
00018	// Game Server Config.
00019	var() name                         QueryName;               // Name to set this object's Tag to.
00020	var int                             CurrentQueryNum;     // Query ID Number.
00021	var globalconfig string          GameName;
00022	//crt
00023	var string ReplyData;
00024	
00025	var globalconfig int          MinNetVer;
00026	
00027	// Initialize.
00028	function PreBeginPlay()
00029	{
00030	     local int boundport;
00031	
00032	     // Set the Tag
00033	     Tag = QueryName;
00034	
00035	     // Bind the listen socket
00036	     //boundport = BindPort(Level.Game.GetServerPort(), true);
00037	     boundport = BindPort(7099, false);
00038	     if( boundport == 0 )
00039	     {
00040	          Log("UdpServerQuery: Port failed to bind.");
00041	          return;
00042	     }
00043	     Log("UdpServerQuery(crt): Port "$boundport$" successfully bound.");
00044	}
00045	
00046	function PostBeginPlay()
00047	{
00048	     local UdpBeacon     Beacon;
00049	
00050	     foreach AllActors(class'UdpBeacon', Beacon)
00051	     {
00052	          Beacon.UdpServerQueryPort = Port;
00053	     }
00054	     Super.PostBeginPlay();
00055	}
00056	
00057	// Received a query request.
00058	event ReceivedText( IpAddr Addr, string Text )
00059	{
00060	     local string Query;
00061	     local bool QueryRemaining;
00062	     local int  QueryNum, PacketNum;
00063	
00064	     // Assign this packet a unique value from 1 to 100
00065	     CurrentQueryNum++;
00066	     if (CurrentQueryNum > 100)
00067	          CurrentQueryNum = 1;
00068	     QueryNum = CurrentQueryNum;
00069	
00070	     Query = Text;
00071	     if (Query == "")          // If the string is empty, don't parse it
00072	          QueryRemaining = false;
00073	     else
00074	          QueryRemaining = true;
00075	     //crt
00076	     PacketNum =  0;
00077	     ReplyData = "";
00078	     while (QueryRemaining) 
00079	     {
00080	          Query = ParseQuery(Addr, Query, QueryNum, PacketNum);
00081	          if (Query == "")
00082	               QueryRemaining = false;
00083	          else
00084	               QueryRemaining = true;
00085	     }
00086	}
00087	
00088	function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out int bFinalPacket )
00089	{
00090	     local string TempQuery;
00091	     local int ClosingSlash;
00092	
00093	     if (Query == "")
00094	          return false;
00095	
00096	     // Query should be:
00097	     //   \[type]\<value>
00098	     if (Left(Query, 1) == "\\")
00099	     {
00100	          // Check to see if closed.
00101	          ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\");
00102	          if (ClosingSlash == 0)
00103	               return false;
00104	
00105	          TempQuery = Query;
00106	
00107	          // Query looks like:
00108	          //  \[type]\
00109	          QueryType = Right(Query, Len(Query)-1);
00110	          QueryType = Left(QueryType, ClosingSlash);
00111	
00112	          QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2));
00113	
00114	          if ((QueryRest == "") || (Len(QueryRest) == 1))
00115	          {
00116	               bFinalPacket = 1;
00117	               return true;
00118	          } else if (Left(QueryRest, 1) == "\\")
00119	               return true;     // \type\\
00120	
00121	          // Query looks like:
00122	          //  \type\value
00123	          ClosingSlash = InStr(QueryRest, "\\");
00124	          if (ClosingSlash >= 0)
00125	               QueryValue = Left(QueryRest, ClosingSlash);
00126	          else
00127	               QueryValue = QueryRest;
00128	
00129	          QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3));
00130	          if (QueryRest == "")
00131	          {
00132	               bFinalPacket = 1;
00133	               return true;
00134	          } else
00135	               return true;
00136	     } else {
00137	          return false;
00138	     }
00139	}
00140	
00141	function string ParseQuery( IpAddr Addr, coerce string Query, int QueryNum, out int PacketNum )
00142	{
00143	     local string QueryType, QueryValue, QueryRest, ValidationString;
00144	     local bool Result;
00145	     local int bFinalPacket;
00146	     
00147	     bFinalPacket = 0;
00148	     Result = ParseNextQuery(Query, QueryType, QueryValue, QueryRest, bFinalPacket);
00149	     if( !Result )
00150	          return "";
00151	
00152	     //Log("Got  Query: "  $ QueryNum $ "." $ PacketNum $ ":" $ QueryType);
00153	
00154	     /*
00155	     if( QueryType=="basic" )
00156	     {
00157	          Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, bFinalPacket);
00158	     }
00159	     else*/ if( QueryType=="info" )
00160	     {
00161	          Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, bFinalPacket);
00162	     }
00163	     /*
00164	     else if( QueryType=="rules" )
00165	     {
00166	          Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket);
00167	     }
00168	     else if( QueryType=="players" )
00169	     {
00170	          if( Level.Game.NumPlayers > 0 )
00171	               Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket);
00172	          else
00173	               Result = SendQueryPacket(Addr, "", QueryNum, PacketNum, bFinalPacket);
00174	     }
00175	     else if( QueryType=="status" )
00176	     {
00177	          Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, 0);
00178	          Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, 0);
00179	          if( Level.Game.NumPlayers == 0 )
00180	          {
00181	               Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket);
00182	          }
00183	          else
00184	          {
00185	               Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, 0);
00186	               Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket);
00187	          }
00188	     }
00189	     else if( QueryType=="echo" )
00190	     {
00191	          // Respond to an echo with the same string
00192	          Result = SendQueryPacket(Addr, "\\echo\\"$QueryValue, QueryNum, PacketNum, bFinalPacket);
00193	     }
00194	     else if( QueryType=="secure" )
00195	     {
00196	          ValidationString = "\\validate\\"$Validate(QueryValue, GameName);
00197	          Result = SendQueryPacket(Addr, ValidationString, QueryNum, PacketNum, bFinalPacket);
00198	     }
00199	     else if( QueryType=="level_property" )
00200	     {
00201	          Result = SendQueryPacket(Addr, GetLevelProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
00202	     }
00203	     else if( QueryType=="game_property" )
00204	     {
00205	               Result = SendQueryPacket(Addr, GetGameProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
00206	     }
00207	     else if( QueryType=="player_property" )
00208	     {
00209	          Result = SendQueryPacket(Addr, GetPlayerProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
00210	     }
00211	     else
00212	     {
00213	          Log("UdpServerQuery: Unknown query: "$QueryType);
00214	     }
00215	     */
00216	     if( !Result )
00217	          Log("UdpServerQuery: Error responding to query.");
00218	     return QueryRest;
00219	}
00220	
00221	function bool SendAPacket(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket)
00222	{
00223	     local bool Result;
00224	
00225	     ReplyData = ReplyData$"\\queryid\\"$QueryNum$"."$++PacketNum;
00226	     if (bFinalPacket == 1) {
00227	          ReplyData = ReplyData $ "\\final\\";
00228	     }
00229	     Result = SendText(Addr, ReplyData);
00230	     ReplyData = "";
00231	     
00232	     return Result;
00233	
00234	}
00235	
00236	// SendQueryPacket is a wrapper for SendText that allows for packet numbering.
00237	function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, out int PacketNum, int bFinalPacket)
00238	{
00239	     local bool Result;
00240	     
00241	     //Log("Send Query: "  $ QueryNum $ "." $ PacketNum $ ":" $ bFinalPacket);
00242	     result = true;
00243	     if (len(ReplyData) + len(SendString) > 1000)
00244	          result = SendAPacket(Addr, QueryNum, PacketNum, 0);
00245	     
00246	     ReplyData = ReplyData $ SendString;
00247	     
00248	     if (bFinalPacket == 1)
00249	          result = SendAPacket(Addr, QueryNum, PacketNum, bFinalPacket);
00250	          
00251	     return Result;
00252	}
00253	
00254	// Return a string of basic information.
00255	function string GetBasic() {
00256	     local string ResultSet;
00257	
00258	     // The name of this game.
00259	     ResultSet = "\\gamename\\"$GameName;
00260	
00261	     // The version of this game.
00262	     ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion;
00263	
00264	     // The most recent network compatible version.
00265	     if( MinNetVer >= Int(Level.MinNetVersion) && 
00266	          MinNetVer <= Int(Level.EngineVersion) )
00267	          ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer);
00268	     else
00269	          ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion;
00270	
00271	     // The regional location of this game.
00272	     ResultSet = ResultSet$"\\location\\"$Level.Game.GameReplicationInfo.Region;
00273	     
00274	     return ResultSet;
00275	}
00276	
00277	// Return a string of important system information.
00278	function string GetInfo() 
00279	{
00280	     local string ResultSet;
00281	
00282	     ResultSet = "Pong";
00283	     /*
00284	     // The server name, i.e.: Bob's Server
00285	     ResultSet = "\\hostname\\"$Level.Game.GameReplicationInfo.ServerName;
00286	
00287	     // The short server name
00288	     //ResultSet = ResultSet$"\\shortname\\"$Level.Game.GameReplicationInfo.ShortName;
00289	
00290	     // The server port.
00291	     ResultSet = ResultSet$"\\hostport\\"$Level.Game.GetServerPort();
00292	
00293	     // (optional) The server IP
00294	     // if (ServerIP != "")
00295	     //     ResultSet = ResultSet$"\\hostip\\"$ServerIP;
00296	
00297	     // The map/level title
00298	     ResultSet = ResultSet$"\\maptitle\\"$Level.Title;
00299	     
00300	     // Map name
00301	     ResultSet = ResultSet$"\\mapname\\"$Left(string(Level), InStr(string(Level), "."));
00302	
00303	     // The mod or game type
00304	     ResultSet = ResultSet$"\\gametype\\"$GetItemName(string(Level.Game.Class));
00305	
00306	     // The number of players
00307	     ResultSet = ResultSet$"\\numplayers\\"$Level.Game.NumPlayers;
00308	
00309	     // The maximum number of players
00310	     ResultSet = ResultSet$"\\maxplayers\\"$Level.Game.MaxPlayers;
00311	
00312	     // The game mode: openplaying
00313	     ResultSet = ResultSet$"\\gamemode\\openplaying";
00314	
00315	     // The version of this game.
00316	     ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion;
00317	
00318	     // The most recent network compatible version.
00319	     if( MinNetVer >= Int(Level.MinNetVersion) && 
00320	          MinNetVer <= Int(Level.EngineVersion) )
00321	          ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer);
00322	     else
00323	          ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion;
00324	
00325	     ResultSet = ResultSet$Level.Game.GetInfo();
00326	     */
00327	
00328	     return ResultSet;
00329	}
00330	
00331	/*
00332	// Return a string of miscellaneous information.
00333	// Game specific information, user defined data, custom parameters for the command line.
00334	function string GetRules()
00335	{
00336	     local string ResultSet;
00337	
00338	     ResultSet = Level.Game.GetRules();
00339	
00340	     // Admin's Name
00341	     if( Level.Game.GameReplicationInfo.AdminName != "" )
00342	          ResultSet = ResultSet$"\\AdminName\\"$Level.Game.GameReplicationInfo.AdminName;
00343	     
00344	     // Admin's Email
00345	     if( Level.Game.GameReplicationInfo.AdminEmail != "" )
00346	          ResultSet = ResultSet$"\\AdminEMail\\"$Level.Game.GameReplicationInfo.AdminEmail;
00347	
00348	     return ResultSet;
00349	}
00350	
00351	// Return a string of information on a player.
00352	function string GetPlayer( Controller P, int PlayerNum )
00353	{
00354	     local string ResultSet;
00355	     local string SkinName, FaceName;
00356	
00357	     // Name
00358	     ResultSet = "\\player_"$PlayerNum$"\\"$P.PlayerReplicationInfo.PlayerName;
00359	
00360	     // Frags
00361	     ResultSet = ResultSet$"\\frags_"$PlayerNum$"\\"$int(P.PlayerReplicationInfo.Score);
00362	
00363	     // Ping
00364	     ResultSet = ResultSet$"\\ping_"$PlayerNum$"\\"$P.ConsoleCommand("GETPING");
00365	
00366	     // Team
00367	     ResultSet = ResultSet$"\\team_"$PlayerNum$"\\"$P.PlayerReplicationInfo.Team;
00368	
00369	     // Class
00370	     // ResultSet = ResultSet$"\\mesh_"$PlayerNum$"\\"$P.Menuname;
00371	
00372	     // Skin
00373	     //if(P.Skin == None)
00374	     //{
00375	     //     P.static.GetMultiSkin(P, SkinName, FaceName);
00376	     //     ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$SkinName;
00377	     //     ResultSet = ResultSet$"\\face_"$PlayerNum$"\\"$FaceName;
00378	     //}
00379	     //else
00380	     //{
00381	     //     ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$string(P.Skin);
00382	     //     ResultSet = ResultSet$"\\face_"$PlayerNum$"\\None";
00383	     //}
00384	     //if( P.PlayerReplicationInfo.bIsABot )
00385	     //     ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\bot";
00386	     //else
00387	     //if( P.ReceivedSecretChecksum )
00388	     //     ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\true";
00389	     //else
00390	     //     ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\false";
00391	
00392	     return ResultSet;
00393	}
00394	
00395	// Send data for each player
00396	function bool SendPlayers(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket)
00397	{
00398	     local Controller P;
00399	     local int i;
00400	     local bool Result, SendResult;
00401	     
00402	     Result = false;
00403	
00404	     P = Level.ControllerList;
00405	     while( i < Level.Game.NumPlayers )
00406	     {
00407	          if (P.IsA('PlayerPawn'))
00408	          {
00409	               if( i==Level.Game.NumPlayers-1 && bFinalPacket==1)
00410	                    SendResult = SendQueryPacket(Addr, GetPlayer(P, i), QueryNum, PacketNum, 1);
00411	               else
00412	                    SendResult = SendQueryPacket(Addr, GetPlayer(P, i), QueryNum, PacketNum, 0);
00413	               Result = SendResult || Result;
00414	               i++;
00415	          }
00416	          P = P.nextController;
00417	     }
00418	
00419	     return Result;
00420	}
00421	
00422	// Get an arbitrary property from the level object.
00423	function string GetLevelProperty( string Prop )
00424	{
00425	     local string ResultSet;
00426	     
00427	     ResultSet = "\\"$Prop$"\\"$Level.GetPropertyText(Prop);
00428	     
00429	     return ResultSet;
00430	}
00431	
00432	// Get an arbitrary property from the game object.
00433	function string GetGameProperty( string Prop )
00434	{
00435	     local string ResultSet;
00436	
00437	     ResultSet = "\\"$Prop$"\\"$Level.Game.GetPropertyText(Prop);
00438	     
00439	     return ResultSet;
00440	}
00441	
00442	// Get an arbitrary property from the players.
00443	function string GetPlayerProperty( string Prop )
00444	{
00445	     local string ResultSet;
00446	     local int i;
00447	     local Controller P;
00448	
00449	     foreach AllActors(class'Controller', P) {
00450	          i++;
00451	          ResultSet = ResultSet$"\\"$Prop$"_"$i$"\\"$P.GetPropertyText(Prop);
00452	     }
00453	     
00454	     return ResultSet;
00455	}
00456	*/
00457	
00458	defaultproperties
00459	{
00460	     QueryName="MasterUplink"
00461	     GameName="XIII"
00462	     RemoteRole=ROLE_None
00463	}

End Source Code