*'L!*iZOMk$l7u}######&&&&'''NoneSendQueryPacket CollisionKarma LightColorIpDrv MovementSystemForce LightingEngineCore SendText ReceivedTextUdpGamespyUplink BindPortNone QueryData GetRulesParseNextQuery ParseQuery SendAPacket bAlwaysTick BeginPlay GetBasicMasterServerPortGameSpyValidateTimerGetInfoGameSpyGameName Reconnect SendPlayers GotMatch GetPlayerNone SendBinaryReceivedBinaryNoneMasterServerAddress ReadBinaryQueryGetLevelPropertyResolveFailed Resolved IsConnectedTickIpAddrToStringResolveNoneGetGamePropertyUdpGamespyQueryGetPlayerPropertyUdpLinkGotMatchTimeoutResumeNoneGetServerPortPoll ReadText PreBeginPlay LogStatLine PingServer ReceivedLineNone MasterUplinkOnReceivedServerOnQueryFinishedLaunchAutoUpdateConsoleCommand StartQuery MR_Command GetItemNameMR_IniSetting MR_NewServerMR_OptionalUpgradeMR_MandatoryUpgradeMR_MOTDRI_MustUpgrade RI_SuccessRI_ConnectionTimeoutRI_ConnectionFailedRI_AuthenticationFailedQT_GreaterThanEqualsQT_GreaterThanQT_LessThanEqualsIpAddr QT_LessThanGetServerInfo QT_NotEqualsGetServerDetailsGetServerPlayers QT_EqualsCTM_QueryUpgrade CTM_GetMOTD CTM_QueryBroadcastPingRequest CancelPingsOnPingTimeoutOnReceivedPingInfo bLANQueryPC_LANBroadcastNoneNone PC_AutoPing PC_Clicked PC_UnknownQI_RulesAndPlayers QI_Players QI_RulesNoneLogfQI_PingRequiresPasswordRefreshConnectionFailed SendStatsUplinkToGamespy DoUplinkHB_GamespyQueryPort HB_GamePortHB_QueryInterfaceCloseOpen MTS_MatchID MTS_Shutdown InternetLinkTcpLinkMasterServerGameStatsMasterServerUplinkMasterServerLinkMasterServerClientServerQueryClientBufferedTCPLinkNoneMTS_ClientAuthFailedLANQueryClientMTS_ClientChallengeSTM_ClientDisconnectFailed STM_StatsSTM_GameState MODE_Text MODE_Line MODE_BinarySTM_ClientResponseGetMasterServerLANServerPortLANPortDoBufferQueueIOSendBufferedData RMODE_Manual RMODE_Event ReceiveModeIsDataPending ParseURLReadBufferedLine PeekChar ReadChar GetLastErrorParseDelimited WaitForCountStringToIpAddrWaitFor ResetBufferClosed GetLocalIPOpened AcceptedBroadcastAddrListenSTATE_ConnectClosingPlayerControllerSTATE_ListenClosingSTATE_ConnectClosePendingSTATE_ListenClosePendingSTATE_ConnectedNoneNoneNoneNoneNoneSTATE_ConnectingSTATE_Listening STATE_ReadyNoneNoneSTATE_InitializedHaltTargetQueryName QueryNameUpdateMinutesOnReceivedMOTDDataNoneNoneStopInitNoneQueryRemaining QueryNum PacketNumTag QueryType QueryValue QueryRest bFinalPacket TempQuery ClosingSlashClassPackagebRestartServerOnPortSwap SendStringOldQueryPortNumber MinNetVer TextBufferObject SendResultEnumProp ReplyDataStructCurrentQueryNum StrPropertyStructPropertyNoneMasterServerIpAddrHeartbeatMessage UplinkPortTitleArrayProperty FinalPacket QueryStr ELinkStateNoneCount boundportNoneActorInfoLevel TeamInfobUseNextAvailable LinkState RemoteAddr AcceptClass SendFIFO ControllerClassPropertyGameReplicationInfo InternetInfoPlayerReplicationInfo InputBuffer OutputBufferCRLFLF bWaitingWaitTimeoutTime WaitingForWaitForCountChars WaitResultWaitMatchDataValidationString GameInfoWhat MatchDataArgDelegateProperty NameProperty LevelInfo Delimiter bToEndOfLineFoundDomain GameStats EntryName EReceiveMode DataPendingUplinkLinkPtrPrivateResolveInfo RemoteSocketNoneObjectProperty WaitTimeSocket OutAddressOutPortEServerToMaster LinkMode ELinkModeAddr ScriptTextEMasterToServerNoneBC ReturnValueEHeartbeatType LevelNameLineCRGamespyQueryLinkReconnectTimebReconnectPendingTempstrnextControllerServerBehindNATDoLANBroadcastFloatPropertyNoneNone ResultSetbShouldReconnectS BoolProperty StatLineEQueryInterfaceCommand LogStringiControllerListGame EPingCauseMinNetVersionEngineVersion TimeSecondsbBotNoneMatchIDListID PingCause__OnReceivedPingInfo__Delegate ServerRegion__OnPingTimeout__Delegate IntProperty CurrentState AdminEmail AdminNameEClientToMaster TeamIndexTeamResult EQueryTypej ServerStateNone NumPlayers MaxPlayers ServerName BytePropertyEResponseInfoIPServerResponseLineScore PlayerName PlayerNumEMOTDResponseValueKeyTimeOutPTextDelta MSLinkPtr ResultCountCommandGetPropertyTextAccessControl ResponseInfo__OnQueryFinished__DelegateURL__OnReceivedServer__Delegate Function__OnReceivedMOTDData__DelegatePortNoneMD5UpdateDataMTS_MD5Update QI_SmallPingSTM_MD5Version RevisionGuidMD5NoneGetNumPlayersbOnlySpectatorNoneNoneNoneNoneNoneNoneNoneNonePointerPropertyNoneNoneNoneNoneNoneNoneNoneNoneNoneNone ReplaceTextNoneNoneMTS_CheckOptionMTS_UpdateOptionSTM_CheckOptionReplyNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNone MSUPropTextGetDescriptionText FillPlayInfo QT_Disabled MSUPROPNUM MSUPropDescNone PlayInfoNoneConst PropNameNone GetFullNameAddressDebugPortSwapOnReceivedOwnageItembDebugPortSwaps LMODE_auto LMODE_UNIX LMODE_MACtMasterServerEntryCTM_GetOwnageListMTS_ClientDupKey NetworkErrorCTM_GetModMOTDMTS_ClientBanned RI_DevClient RI_BadClientRI_BannedClientMTS_ClientMD5FailOnReceivedModMOTDDataMasterServerList LMODE_DOS FullName GameEngine LinkClass OwnageLevel ELineModeOptionalResult ItemNameIndex Referencers InLineModeGetReferencersQ"__OnReceivedModMOTDData__DelegateRecvBuf ItemDescItemURL!__OnReceivedOwnageItem__Delegateobj ServerGroupName requestportQueries OutLineModeRefDynamicLoadObjectOutersOuterNoneNoneNoneNoneNone ModRevLevelNoneCachePlayerCountCacheRefreshTimeCachedServerStateFullCachedServerStatebInitialStateCachedNoneNoneNoneNoneNoneNone LastMSIndexActiveMasterServerListNoneNoneNoneNoneMultiMinPlayersNoneNone|U|"@||e@||||w||||n||||!@||9@||,@||@||d@||@||N@||-||@||}@||1||||W|=og4:$b.=C%  g"||e@||/||G||@||s@||a@|yQ2>Z#NA$b.,e,ezVGB,e3}Zs3}3}3}Zs,e,e,ezVGB3}Zs,e uzVGB uzVGB u uzVGB uzVGBJ3}Zs- =13}Zs- =13}Zs- =13}Zs- =13}Zs3}Zs±3}Zs- =13}Zs3}3}Zs3}Zs3}Zs3}Zs3}Zs3}3}3}3}3}3}3}3}D[I3}Zs3}Zs@E@E@Eʁ)ʁ)ʁ)ʁ)ʁ)ʁ)@Eʁ)ʁ)3}Zs  |@Pv||A@||||||z|||E|||f@||||P||||a||||Y||3||l|J|Y||K@||V@||G||:@|~JA><Ҝ׿e]  R".Q"*EYUs]ut2004master1.epicgames.comt"p|s]ut2004master2.epicgames.comt"p||H^}:=C%w  ||||o@|Z||7||||S@|t[>D[I$b.#NA#NA  }""l{@|<}k@>E<Ҳв3}3}Zs3}Zs3}Zs3}3}Zs3}Zs3}ZsJ4@J4@  i"utsf]Advertise ServerfProcess Statsk]ECif true, your server is advertised on the internet server browser.kGEPublishes player stats from your server on the UT2004 stats website.|<|@C>Fx<ҏEE  ||+@||I|#||AB6J4@E  ||||_||W||N||O||P||j@||@||||@||@||K@||_@||om .3 G|p||H@|||={K~:cK=C%  ||G@||W@||@||H||ihgd||@||t@||k||||@||r@||u||x||c||||I||@@||{||G4|U@||@||R@||@||H@||||@||E@||D|||||P@||MQ-> 9% G|>||q@|L@||E||||||||^]\~{|B2|E@||FH ^  G|@||C||@||Z||^||;@||[||_||F@||@||U[XVTSRi|`@||dE|e|h||||(@||i||gQPONM@AB|@||mLKJIHF|x@|||U|~@||QSBO G|vWAP G|q||z||{|||||k||l||B||}||||D||F|| yvutnmlki|||z@||a@||k||H||J||wZ~QA G|n||8||M||O||r@||Q||w@||x||T||U||@||@|||@||Y||||[||@||`*s  G|{@||GF+pz  G|||h||T||L||c||K@||e@||O||g||h@||U||X||?@|@||M@|y@||0|[@||r@||s||t@||u@||%@||b||z@||^@||~UV|||i@||olkjx|A||w@||LMN|Dua#G G|npb"  G|||G ^hz (cz &\%~ } &\G%%(w , } &,,% } },,z }&Nfinal'z&\'%~\ %%f%f } },}f,^zNfinal'`'e( G|^H@ ~ II,dI&PIwAGzw-.(O-.'-.w@wPEzw-.(-.'O G|I6r a9?m,<' G|Jzl a( G|KRd S-R 0aP-RFailed to send heartbeat to master server. G|^M*[ KUdpGameSpyUplink: Failed to resolve master server address, aborting. G|w||`Nx+?XI606xe60%UdpGameSpyUplink: Invalid master server address, aborting. pppUdpGameSpyUplink: Master Server is ?:9S610bHg&b'%UdpGameSpyUplink: Error binding port, aborting. ppUdpGameSpyUplink: Port 9Sb successfully bound.6 G|m;%/a0 #Hq10orH*UdpGameSpyUplink: Could not find a UdpGameSpyQuery object, aborting. appp\heartbeat\9SHg\gamename\610oz??ppmaster9SM.gamespy.com/? G|Fi`-@gCSjZ4-@PzCbasic-@'zCsecure|p\validate\S-@i|ecZj G|[@||SI3:/a0 >w>*>-K[pppppp[\I_9SK\> I10[ G|B@||VA1 9=Bppp\A\ AB G|C@||@@||X)84@ppp\\ @ G|||ZQK5-(-r*tN&-/QPON--/-a/!jw*-A-& N&-/Q!.-PO&s-/Q!.-PO%--/--- G|@||]5!?2dd5d\ppp\player_9S3\dpppp\frags_9S3\9S9D5pppp\ping_9S3\5DGETPING7w5*pppp\team_9S3\9S5[ppp\team_9S3\0 G|ONw'zHfinal8p8\final\8pppp8\queryid\9SK.9SJ-y N8-y G|@||_\j/Jc{pp\AdminName\{pp\AdminEMail\'w*"pp\password\1Ap\password\0 G|@||b^t(ee\p\hostname\epp\hostport\9S8pp\maptitle\pp\mapname\9V~9V.pp\gametype\G9Vg~yg%gz&pp\numplayers\9Sgpp\maxplayers\9Sp\gamemode\openplayingpp\gamever\{9J9Jpp\minnetver\9Spp\minnetver\ G|@||y||j`\+%p\gamename\pp\gamever\9J9Jpp\minnetver\9Spp\minnetver\pp\location\9S DM G|K||e|E|f||g|c|I@|h|||d4s ))} G|poK#-K'?}}k-Kotu%pk}x&-Kotux-K G|q||||inh8# G|||mxz;)x G|zy:!{pppp\queryid\9Sz.9S{R|&p\final\-q y-q G|||osy> G|||ru,A  G|||tq E )q G| @||||vl#H* )l)i G|~s%-n !s;-vz basic-z info-z rules-ez players?%-b-Kz status-%-%%-H-%-z echo-p\ignoring\!z securerp\validate\!-r5z level_property-)!}z game_property-1!z player_property-3!s G|j||||yc:L )c G|A \z (Wz &\(~ } &\G(%(j 9 } &99( } }9,z }&}&'z&\'(~\(%V(V } }9}V,Rz}&'T'Y( G|||}\'O )\)Z G|^U] BB,dB&GB;^Gz;-:(O-:'D%-:;];GDz;-:(-:'^ G|||@fU  G|DeX  G|Ec[u  G|V);%xVz8, )z't)%UdpServerQuery: Port failed to bind. ppUdpServerQuery(crt): Port 9S) successfully bound.u-Wge%ge)pppppPORTSWAP detected, exiting... old port: 9Se, new port: 9S), requested port: 9SzX-Et :e)e)b G|@||XJ>b  G|@||IL$e G|M||||b5A"-(F, E, apFE G|Yta!K-'t%W~+BG G|ZC_+L-'CWD+FG G|||_||`||^c 6 G|||be5;* G|||dd^C$A&7%7}dYd7&~GYAz-Ip$d7$AAz$p$Y7$ G|ja$4L G|@||h||^i>1 G|$@||@||l||||vP'(P)P)O)M G|fq\d5z%T&&T G|T||||pt[pz%& G|||sSZ$ dz()aS'DFS'_ES'( G|zR:% )R)Q G|||||uWTi aB"W G|~V#!J)V)U)T G|XyX aBX G|||{S* m2-4W-(5+%S}2G-( +/~ zF~E,G}}-( +/2j,j{" """ G|CZ  )Z)Y G|||*Br/MasterServerGameStats initializing G|@]n<]r**99* <]** G|~\A )\)[ G|_@||||Iadi )a G|@||NHga  G|ad9")d G|@||||JCP+~7d%|%~|7{7d|&6C|d6C|{6@|d6@|{||7de|C6C|dH6@|d G|Pff6 )f G|||Vj`c )j)h G|||OKJIyX|R HF|{wWVC||Sxwv|@||Yk.`: )k G|||L||ZW]] G|\n/Z)n G|||bvYT)v)u)t)s)r G|||_@||i@||lK G|`uR*LC-p-yuIpDrv.UdpGamespyQuery Xwu*lauuIpDrv.UdpGamespyUplink wu*auC-z/a0 J6r6**6*6*10Cr6*MasterServerUplink: MasterServerGameStats not found - stats uploading disabled. G||]XI G|B|||a}ryB Master server connection failed-_-}-}c7d%e7dAde&}7d%L AL@L G|c||dq 9-ca W_ Y_`_ Z_\_a9?,<-c(b\` Z\_\\_b G|f~<)~ G |||JgS-]mJSj-_LSjLAttempting to reconnect to master server!-_( G|P|B|s||R//============================================================================= // UdpLink: An Internet UDP connectionless socket. //============================================================================= class UdpLink extends InternetLink native transient; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) //----------------------------------------------------------------------------- // Variables. var() const int BroadcastAddr; var const string RecvBuf; // Recveive buffer (only used with MODE_Line) //----------------------------------------------------------------------------- // Natives. // BindPort: Binds a free port or optional port specified in argument one. native function int BindPort( optional int Port, optional bool bUseNextAvailable ); // SendText: Sends text string. // Appends a cr/lf if LinkMode=MODE_Line . native function bool SendText( IpAddr Addr, coerce string Str ); // SendBinary: Send data as a byte array. native function bool SendBinary( IpAddr Addr, int Count, byte B[255] ); // ReadText: Reads text string. // Returns number of bytes read. native function int ReadText( out IpAddr Addr, out string Str ); // ReadBinary: Read data as a byte array. native function int ReadBinary( out IpAddr Addr, int Count, out byte B[255] ); //----------------------------------------------------------------------------- // Events. // ReceivedText: Called when data is received and connection mode is MODE_Text. event ReceivedText( IpAddr Addr, string Text ); // ReceivedLine: Called when data is received and connection mode is MODE_Line. event ReceivedLine( IpAddr Addr, string Line ); // ReceivedBinary: Called when data is received and connection mode is MODE_Binary. event ReceivedBinary( IpAddr Addr, int Count, byte B[255] ); |q||r|h|@||w@|D|`b//============================================================================= // UdpGameSpyUplink // // Version: 1.3 // // This uplink 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 want to adapt their own // server uplinks. // // UdpGameSpyUplink sends a heartbeat to the specified master server // every five minutes. The heartbeat is in the form: // \heartbeat\QueryPort\gamename\unreal // // Full documentation on this class is available at http://unreal.epicgames.com/ // //============================================================================= class UdpGameSpyUplink extends UdpLink config; // Master Uplink Config. var() config int UpdateMinutes; // Period of update (in minutes) var() string MasterServerAddress; // Address of the master server var() config int MasterServerPort; // Optional port that the master server is listening on var() config int ServerRegion; // Region of the game server var() name TargetQueryName; // Name of the query server object to use. var IpAddr MasterServerIpAddr; // Master server's address. var string HeartbeatMessage; // The message that is sent to the master server. var UdpGameSpyQuery Query; // The query object. var int CurrentQueryNum; // Query ID Number. // Initialize. function PreBeginPlay() { // Find a the server query handler. foreach AllActors(class'UdpGameSpyQuery', Query, TargetQueryName) break; if( Query==None ) { Log("UdpGameSpyUplink: Could not find a UdpGameSpyQuery object, aborting."); return; } HeartbeatMessage = "\\heartbeat\\"$Query.Port$"\\gamename\\"$GameSpyGameName(); // Set the Port. MasterServerIpAddr.Port = MasterServerPort; // Resolve the Address. if( MasterServerAddress=="" ) MasterServerAddress = "master"$ServerRegion$".gamespy.com"; Resolve( MasterServerAddress ); } // When master server address is resolved. function Resolved( IpAddr Addr ) { local int UplinkPort; // Set the address MasterServerIpAddr.Addr = Addr.Addr; // Handle failure. if( MasterServerIpAddr.Addr == 0 ) { Log("UdpGameSpyUplink: Invalid master server address, aborting."); return; } // Display success message. Log("UdpGameSpyUplink: Master Server is "$MasterServerAddress$":"$string(MasterServerIpAddr.Port)); // Bind the local port. UplinkPort = Query.Port + 1; if( BindPort(UplinkPort, true) == 0 ) { Log( "UdpGameSpyUplink: Error binding port, aborting." ); return; } Log("UdpGameSpyUplink: Port "$UplinkPort$" successfully bound."); // Start transmitting. Resume(); } // Host resolution failue. function ResolveFailed() { Log("UdpGameSpyUplink: Failed to resolve master server address, aborting."); } // Notify the MasterServer we exist. function Timer() { local bool Result; // Log("Sending GameSpy heartbeat:"@HeartbeatMessage); Result = SendText( MasterServerIpAddr, HeartbeatMessage ); if ( !Result ) Log( "Failed to send heartbeat to master server."); } // Stop the uplink. function Halt() { SetTimer(0.0, false); } // Resume the uplink. function Resume() { SetTimer(UpdateMinutes * 60, true); Timer(); } // Received a query request. event ReceivedText( IpAddr Addr, string Text ) { local string QueryStr; local bool QueryRemaining; local int QueryNum, PacketNum; // Assign this packet a unique value from 1 to 100 CurrentQueryNum++; if (CurrentQueryNum > 100) CurrentQueryNum = 1; QueryNum = CurrentQueryNum; QueryStr = Text; if (QueryStr == "") // If the string is empty, don't parse it QueryRemaining = false; else QueryRemaining = true; while (QueryRemaining) { QueryStr = ParseQuery(Addr, QueryStr, QueryNum, PacketNum); if (QueryStr == "") QueryRemaining = false; else QueryRemaining = true; } } function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out string FinalPacket ) { local string TempQuery; local int ClosingSlash; if (Query == "") return false; // Query should be: // \[type]\ if (Left(Query, 1) == "\\") { // Check to see if closed. ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\"); if (ClosingSlash == 0) return false; TempQuery = Query; // Query looks like: // \[type]\ QueryType = Right(Query, Len(Query)-1); QueryType = Left(QueryType, ClosingSlash); QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2)); if ((QueryRest == "") || (Len(QueryRest) == 1)) { FinalPacket = "final"; return true; } else if (Left(QueryRest, 1) == "\\") return true; // \type\\ // Query looks like: // \type\value ClosingSlash = InStr(QueryRest, "\\"); if (ClosingSlash >= 0) QueryValue = Left(QueryRest, ClosingSlash); else QueryValue = QueryRest; QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3)); if (QueryRest == "") { FinalPacket = "final"; return true; } else return true; } else { return false; } } function string ParseQuery( IpAddr Addr, coerce string QueryStr, int QueryNum, out int PacketNum ) { local string QueryType, QueryValue, QueryRest, ValidationString; local bool Result; local string FinalPacket; Result = ParseNextQuery(QueryStr, QueryType, QueryValue, QueryRest, FinalPacket); if( !Result ) return ""; if( QueryType=="basic" ) { // Ignore. Result = true; } else if( QueryType=="secure" ) { ValidationString = "\\validate\\"$GameSpyValidate(QueryValue); Result = SendQueryPacket(Addr, ValidationString, QueryNum, ++PacketNum, FinalPacket); } return QueryRest; } // SendQueryPacket is a wrapper for SendText that allows for packet numbering. function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, int PacketNum, string FinalPacket) { local bool Result; if (FinalPacket == "final") { SendString = SendString$"\\final\\"; } SendString = SendString$"\\queryid\\"$QueryNum$"."$PacketNum; Result = SendText(Addr, SendString); return Result; } |v|||h|h@|C|Cb=% )b)h)e)`)_)[ G|f//============================================================================= // UdpGameSpyQuery // // 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/ // //============================================================================= class UdpGameSpyQuery extends UdpLink config; // Game Server Config. var() name QueryName; // Name to set this object's Tag to. var int CurrentQueryNum; // Query ID Number. //crt var string ReplyData; var globalconfig int MinNetVer; //!! Hack to prevent port swapping var globalconfig int OldQueryPortNumber; var globalconfig bool bRestartServerOnPortSwap; var globalconfig bool bDebugPortSwaps; // Initialize. function PreBeginPlay() { local int boundport, requestport; // Set the Tag Tag = QueryName; // Bind the listen socket requestport = Level.Game.GetServerPort()+10; boundport = BindPort(requestport, true); if( boundport == 0 ) { Log("UdpServerQuery: Port failed to bind."); return; } Log("UdpServerQuery(crt): Port "$boundport$" successfully bound."); if( bRestartServerOnPortSwap ) { if( OldQueryPortNumber != 0 ) { if( OldQueryPortNumber != boundport ) { Log("PORTSWAP detected, exiting... old port: "$OldQueryPortNumber$", new port: "$boundport$", requested port: "$requestport); if ( bDebugPortSwaps ) DebugPortSwap(Level); assert( OldQueryPortNumber == boundport ); } } OldQueryPortNumber = boundport; SaveConfig(); } } static function DebugPortSwap( Actor Ref ) { local array Queries; local array Referencers; local UdpGamespyQuery Q; local int i, j; local string str; Log("***************"); Log(" Complete OBJ LIST:"); Ref.ConsoleCommand("obj list", true); Log("***************"); log(""); Log("Current UdpGameSpyQuery objects:"); foreach Ref.AllObjects( class'UdpGamespyQuery', Q ) Queries[Queries.Length] = Q; if ( Queries.Length == 0 ) { log("No UdpGamespyQuery objects found!"); return; } Ref.ConsoleCommand("obj list class=udpgamespyquery", true); log("***************"); log("Tracing UdpGamespyQuery objects"); for ( i = 0; i < Queries.Length; i++ ) { str = GetFullName(Queries[i]); log("==================================================================="); Log(" Referencers of '"$str$"'"); Ref.ConsoleCommand("obj refs class=udpgamespyquery name="$str, true); Ref.GetReferencers( Queries[i], Referencers ); for ( j = 0; j < Referencers.Length; j++ ) { if ( Level(Referencers[j]) == None && GameEngine(Referencers[j]) == None ) { str = GetFullName(Referencers[j]); log(""); log(" Referencers of '"$str$"'"); Ref.ConsoleCommand("obj refs class="$Referencers[j].Class$" name="$str, true); log("**************************************************************************"); } } log("==================================================================="); log(""); } log("Performing garbage collection"); Ref.ConsoleCommand("obj garbage", true); Log("***************"); Log("Remaining UdpGameSpyQuery objects:"); Ref.ConsoleCommand("obj list class=udpgamespyquery", true); Log("***************"); } static function string GetFullName( Object Obj ) { local string FullName; local array Outers; local int i; if ( Obj == None ) return ""; Outers[0] = Obj; while ( Outers[0].Outer != None ) { Outers.Insert(0, 1); Outers[0] = Outers[1].Outer; } for ( i = 0; i < Outers.Length; i++ ) { if ( FullName != "" ) FullName $= "."; FullName $= Outers[i].Name; } return FullName; } // Received a query request. event ReceivedText( IpAddr Addr, string Text ) { local string Query; local bool QueryRemaining; local int QueryNum, PacketNum; // Assign this packet a unique value from 1 to 100 CurrentQueryNum++; if (CurrentQueryNum > 100) CurrentQueryNum = 1; QueryNum = CurrentQueryNum; Query = Text; if (Query == "") // If the string is empty, don't parse it QueryRemaining = false; else QueryRemaining = true; //crt PacketNum = 0; ReplyData = ""; while (QueryRemaining) { Query = ParseQuery(Addr, Query, QueryNum, PacketNum); if (Query == "") QueryRemaining = false; else QueryRemaining = true; } } function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out int bFinalPacket ) { local string TempQuery; local int ClosingSlash; if (Query == "") return false; // Query should be: // \[type]\ if (Left(Query, 1) == "\\") { // Check to see if closed. ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\"); if (ClosingSlash == 0) return false; TempQuery = Query; // Query looks like: // \[type]\ QueryType = Right(Query, Len(Query)-1); QueryType = Left(QueryType, ClosingSlash); QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2)); if ((QueryRest == "") || (Len(QueryRest) == 1)) { bFinalPacket = 1; return true; } else if (Left(QueryRest, 1) == "\\") return true; // \type\\ // Query looks like: // \type\value ClosingSlash = InStr(QueryRest, "\\"); if (ClosingSlash >= 0) QueryValue = Left(QueryRest, ClosingSlash); else QueryValue = QueryRest; QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3)); if (QueryRest == "") { bFinalPacket = 1; return true; } else return true; } else { return false; } } function string ParseQuery( IpAddr Addr, coerce string Query, int QueryNum, out int PacketNum ) { local string QueryType, QueryValue, QueryRest, ValidationString; local bool Result; local int bFinalPacket; bFinalPacket = 0; Result = ParseNextQuery(Query, QueryType, QueryValue, QueryRest, bFinalPacket); if( !Result ) return ""; //Log("Got Query: " $ QueryNum $ "." $ PacketNum $ ":" $ QueryType); if( QueryType=="basic" ) { Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="info" ) { Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="rules" ) { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="players" ) { if( Level.Game.NumPlayers > 0 ) Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket); else Result = SendQueryPacket(Addr, "", QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="status" ) { Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, 0); Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, 0); if( Level.Game.NumPlayers == 0 ) { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket); } else { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, 0); Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket); } } else if( QueryType=="echo" ) { // Respond to an echo with the same string //!! disabled due to security problem - the remote ip/port could be spoofed to cause an echo loop! Result = SendQueryPacket(Addr, "\\ignoring\\"$QueryValue, QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="secure" ) { ValidationString = "\\validate\\"$GameSpyValidate(QueryValue); Result = SendQueryPacket(Addr, ValidationString, QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="level_property" ) { Result = SendQueryPacket(Addr, GetLevelProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="game_property" ) { Result = SendQueryPacket(Addr, GetGameProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="player_property" ) { Result = SendQueryPacket(Addr, GetPlayerProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } return QueryRest; } function bool SendAPacket(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket) { local bool Result; ReplyData = ReplyData$"\\queryid\\"$QueryNum$"."$++PacketNum; if (bFinalPacket == 1) { ReplyData = ReplyData $ "\\final\\"; } Result = SendText(Addr, ReplyData); ReplyData = ""; return Result; } // SendQueryPacket is a wrapper for SendText that allows for packet numbering. function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, out int PacketNum, int bFinalPacket) { local bool Result; //Log("Send Query: " $ QueryNum $ "." $ PacketNum $ ":" $ bFinalPacket); result = true; if (len(ReplyData) + len(SendString) > 1000) result = SendAPacket(Addr, QueryNum, PacketNum, 0); ReplyData = ReplyData $ SendString; if (bFinalPacket == 1) result = SendAPacket(Addr, QueryNum, PacketNum, bFinalPacket); return Result; } // Return a string of basic information. function string GetBasic() { local string ResultSet; // The name of this game. ResultSet = "\\gamename\\"$GameSpyGameName(); // The version of this game. ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; // The most recent network compatible version. if( MinNetVer >= Int(Level.MinNetVersion) && MinNetVer <= Int(Level.EngineVersion) ) ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); else ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; // The regional location of this game. ResultSet = ResultSet$"\\location\\"$class'UdpGamespyUplink'.default.ServerRegion; return ResultSet; } // Return a string of important system information. function string GetInfo() { local string ResultSet; local string ServerName; local int NumPlayers; ServerName = Level.Game.GameReplicationInfo.ServerName; ReplaceText(ServerName,"\\",""); // strip \'s // The server name, i.e.: Bob's Server ResultSet = "\\hostname\\"$ServerName; // The short server name //ResultSet = ResultSet$"\\shortname\\"$Level.Game.GameReplicationInfo.ShortName; // The server port. ResultSet = ResultSet$"\\hostport\\"$Level.Game.GetServerPort(); // (optional) The server IP // if (ServerIP != "") // ResultSet = ResultSet$"\\hostip\\"$ServerIP; // The map/level title ResultSet = ResultSet$"\\maptitle\\"$Level.Title; // Map name ResultSet = ResultSet$"\\mapname\\"$Left(string(Level), InStr(string(Level), ".")); // The mod or game type ResultSet = ResultSet$"\\gametype\\"$GetItemName(string(Level.Game.Class)); // The number of players NumPlayers = Level.Game.GetNumPlayers(); if ( NumPlayers == 0 ) NumPlayers = Min(Level.Game.MultiMinPlayers(), Level.Game.MaxPlayers-1); ResultSet = ResultSet$"\\numplayers\\"$NumPlayers; // The maximum number of players ResultSet = ResultSet$"\\maxplayers\\"$Level.Game.MaxPlayers; // The game mode: openplaying ResultSet = ResultSet$"\\gamemode\\openplaying"; // The version of this game. ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; // The most recent network compatible version. if( MinNetVer >= Int(Level.MinNetVersion) && MinNetVer <= Int(Level.EngineVersion) ) ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); else ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; //ResultSet = ResultSet$Level.Game.GetInfo(); return ResultSet; } // Return a string of miscellaneous information. // Game specific information, user defined data, custom parameters for the command line. function string GetRules() { local string ResultSet; //ResultSet = Level.Game.GetRules(); // Admin's Name if( Level.Game.GameReplicationInfo.AdminName != "" ) ResultSet = ResultSet$"\\AdminName\\"$Level.Game.GameReplicationInfo.AdminName; // Admin's Email if( Level.Game.GameReplicationInfo.AdminEmail != "" ) ResultSet = ResultSet$"\\AdminEMail\\"$Level.Game.GameReplicationInfo.AdminEmail; // Whether the server is password protected. if( Level.Game.AccessControl != None && Level.Game.AccessControl.RequiresPassword() ) ResultSet = ResultSet$"\\password\\1"; else ResultSet = ResultSet$"\\password\\0"; return ResultSet; } // Return a string of information on a player. function string GetPlayer( PlayerController P, int PlayerNum ) { local string ResultSet; local string PlayerName; PlayerName = P.PlayerReplicationInfo.PlayerName; // Name ReplaceText(PlayerName,"\\",""); // strip \'s ResultSet = "\\player_"$PlayerNum$"\\"$PlayerName; // Frags ResultSet = ResultSet$"\\frags_"$PlayerNum$"\\"$int(P.PlayerReplicationInfo.Score); // Ping ResultSet = ResultSet$"\\ping_"$PlayerNum$"\\"$P.ConsoleCommand("GETPING"); // Team if(P.PlayerReplicationInfo.Team != None) ResultSet = ResultSet$"\\team_"$PlayerNum$"\\"$P.PlayerReplicationInfo.Team.TeamIndex; else ResultSet = ResultSet$"\\team_"$PlayerNum$"\\0"; return ResultSet; } // Send data for each player function bool SendPlayers(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket) { local Controller C; local int i; local bool Result, SendResult; Result = false; C = Level.ControllerList; while( i < Level.Game.NumPlayers ) { if (C == None) { if(bFinalPacket==1) SendResult = SendAPacket(Addr,QueryNum,PacketNum,bFinalPacket); Result = SendResult || Result; break; } else if (C.IsA('PlayerController') && C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator) { if( i==Level.Game.NumPlayers-1 && bFinalPacket==1) SendResult = SendQueryPacket(Addr, GetPlayer(PlayerController(C), i), QueryNum, PacketNum, 1); else SendResult = SendQueryPacket(Addr, GetPlayer(PlayerController(C), i), QueryNum, PacketNum, 0); Result = SendResult || Result; i++; } C = C.NextController; } return Result; } // Get an arbitrary property from the level object. function string GetLevelProperty( string Prop ) { local string ResultSet; ResultSet = "\\"$Prop$"\\"$Level.GetPropertyText(Prop); return ResultSet; } // Get an arbitrary property from the game object. function string GetGameProperty( string Prop ) { local string ResultSet; ResultSet = "\\"$Prop$"\\"$Level.Game.GetPropertyText(Prop); return ResultSet; } // Get an arbitrary property from the players. function string GetPlayerProperty( string Prop ) { local string ResultSet; local int i; local Controller C; foreach AllActors(class'Controller', C) { if( C.PlayerReplicationInfo!=None && !C.PlayerReplicationInfo.bBot ) { i++; ResultSet = ResultSet$ "\\"$ Prop$ "_"$ i$ "\\"$ C.GetPropertyText(Prop); } } return ResultSet; } |T8//============================================================================= // TcpLink: An Internet TCP/IP connection. //============================================================================= class TcpLink extends InternetLink native transient; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) //----------------------------------------------------------------------------- // Variables. // LinkState is only valid for TcpLink at this time. var enum ELinkState { STATE_Initialized, // Sockets is initialized STATE_Ready, // Port bound, ready for activity STATE_Listening, // Listening for connections STATE_Connecting, // Attempting to connect STATE_Connected, // Open and connected STATE_ListenClosePending,// Socket in process of closing STATE_ConnectClosePending,// Socket in process of closing STATE_ListenClosing, // Socket in process of closing STATE_ConnectClosing // Socket in process of closing } LinkState; var IpAddr RemoteAddr; // Contains address of peer connected to from a Listen() // If AcceptClass is not None, an actor of class AcceptClass will be spawned when an // incoming connecting is accepted, leaving the listener open to accept more connections. // Accepted() is called only in the child class. You can use the LostChild() and GainedChild() // events to track your children. var class AcceptClass; var const Array SendFIFO; // send fifo var const string RecvBuf; // Recveive buffer (only used with MODE_Line) //----------------------------------------------------------------------------- // natives. // BindPort: Binds a free port or optional port specified in argument one. native function int BindPort( optional int Port, optional bool bUseNextAvailable ); // Listen: Listen for connections. Can handle up to 5 simultaneous connections. // Returns false if failed to place socket in listen mode. native function bool Listen(); // Open: Open a connection to a foreign host. native function bool Open( IpAddr Addr ); // Close: Closes the current connection. native function bool Close(); // IsConnected: Returns true if connected. native function bool IsConnected(); // SendText: Sends text string. // Appends a cr/lf if LinkMode=MODE_Line. Returns number of bytes sent. native function int SendText( coerce string Str ); // SendBinary: Send data as a byte array. native function int SendBinary( int Count, byte B[255] ); // ReadText: Reads text string. // Returns number of bytes read. native function int ReadText( out string Str ); // ReadBinary: Read data as a byte array. native function int ReadBinary( int Count, out byte B[255] ); //----------------------------------------------------------------------------- // Events. // Accepted: Called during STATE_Listening when a new connection is accepted. event Accepted(); // Opened: Called when socket successfully connects. event Opened(); // Closed: Called when Close() completes or the connection is dropped. event Closed(); // ReceivedText: Called when data is received and connection mode is MODE_Text. event ReceivedText( string Text ); // ReceivedLine: Called when data is received and connection mode is MODE_Line. // \r\n is stripped from the line event ReceivedLine( string Line ); // ReceivedBinary: Called when data is received and connection mode is MODE_Binary. event ReceivedBinary( int Count, byte B[255] ); |yclass ServerQueryClient extends MasterServerLink native; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) enum EQueryInterfaceCommand { QI_Ping, QI_Rules, QI_Players, QI_RulesAndPlayers, QI_SmallPing, }; enum EPingCause { PC_Unknown, PC_Clicked, PC_AutoPing, PC_LANBroadcast, }; var bool bLANQuery; delegate OnReceivedPingInfo( int ListID, EPingCause PingCause, GameInfo.ServerResponseLine s ); delegate OnPingTimeout( int ListID, EPingCause PingCause ); native function PingServer( int ListID, EPingCause PingCause, string IP, int Port, EQueryInterfaceCommand Command, GameInfo.ServerResponseLine CurrentState ); native function CancelPings(); native function bool NetworkError(); function BroadcastPingRequest() { local GameInfo.ServerResponseLine Temp; if (class'MasterServerUplink'.default.LANServerPort >= 0) PingServer( -1, PC_LANBroadcast, "BROADCAST", class'MasterServerUplink'.default.LANServerPort, QI_Ping, Temp ); } ||Gclass MasterServerUplink extends MasterServerLink config native; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) enum EServerToMaster { STM_ClientResponse, STM_GameState, STM_Stats, STM_ClientDisconnectFailed, STM_MD5Version, STM_CheckOptionReply, }; enum EMasterToServer { MTS_ClientChallenge, MTS_ClientAuthFailed, MTS_Shutdown, MTS_MatchID, MTS_MD5Update, MTS_UpdateOption, MTS_CheckOption, MTS_ClientMD5Fail, MTS_ClientBanned, MTS_ClientDupKey, }; enum EHeartbeatType { HB_QueryInterface, HB_GamePort, HB_GamespyQueryPort, }; // MD5 data coming from the master server. struct native export MD5UpdateData { var string Guid; var string MD5; var INT Revision; }; var bool bInitialStateCached; var GameInfo.ServerResponseLine ServerState, FullCachedServerState, CachedServerState; var float CacheRefreshTime; var int CachePlayerCount; var MasterServerGameStats GameStats; var UdpLink GamespyQueryLink; var const int MatchID; var float ReconnectTime; var bool bReconnectPending; // config var globalconfig bool DoUplink; var globalconfig bool UplinkToGamespy; var globalconfig bool SendStats; var globalconfig bool ServerBehindNAT; var globalconfig bool DoLANBroadcast; const MSUPROPNUM = 2; var localized string MSUPropText[MSUPROPNUM]; var localized string MSUPropDesc[MSUPROPNUM]; // sorry, no code for you! native function Reconnect(); event BeginPlay() { local class LinkClass; if( DoUplink ) { // if we're uplinking to gamespy, also spawn the gamespy actors. if( UplinkToGamespy ) { LinkClass = class(DynamicLoadObject("IpDrv.UdpGamespyQuery", class'Class')); if ( LinkClass != None ) GamespyQueryLink = Spawn( LinkClass ); // FMasterServerUplink needs this for NAT. LinkClass = class(DynamicLoadObject("IpDrv.UdpGamespyUplink", class'Class')); if ( LinkClass != None ) Spawn( LinkClass ); } // If we're sending stats, if( SendStats ) { foreach AllActors(class'MasterServerGameStats', GameStats ) { if( GameStats.Uplink == None ) GameStats.Uplink = Self; else GameStats = None; break; } if( GameStats == None ) Log("MasterServerUplink: MasterServerGameStats not found - stats uploading disabled."); } } Reconnect(); } // Called when the connection to the master server fails or doesn't connect. event ConnectionFailed( bool bShouldReconnect ) { // This master Server Index is bad. Log("Master server connection failed"); bReconnectPending = bShouldReconnect; if (bShouldReconnect) { if (ActiveMasterServerList.Length>0 && LastMSIndex CacheRefreshTime ) ) { Level.Game.GetServerInfo(FullCachedServerState); Level.Game.GetServerDetails(FullCachedServerState); CachedServerState = FullCachedServerState; Level.Game.GetServerPlayers(FullCachedServerState); ServerState = FullCachedServerState; CacheRefreshTime = Level.TimeSeconds + 60; bInitialStateCached = false; } else if (Level.Game.NumPlayers != CachePlayerCount) { ServerState = CachedServerState; Level.Game.GetServerPlayers(ServerState); FullCachedServerState = ServerState; } else ServerState = FullCachedServerState; CachePlayerCount = Level.Game.NumPlayers; } // Call to log a stat line native event bool LogStatLine( string StatLine ); // Handle disconnection. simulated function Tick( float Delta ) { Super.Tick(Delta); if( bReconnectPending ) { ReconnectTime -= Delta; if( ReconnectTime <= 0.0 ) { Log("Attempting to reconnect to master server!"); bReconnectPending = False; Reconnect(); } } } static function FillPlayInfo(PlayInfo PlayInfo) { Super.FillPlayInfo(PlayInfo); PlayInfo.AddSetting(default.ServerGroup, "DoUplink", default.MSUPropText[0], 255, 1, "Check",,,True); } static event string GetDescriptionText(string PropName) { switch (PropName) { case "DoUplink": return default.MSUPropDesc[0]; case "SendStats": return default.MSUPropDesc[1]; } return Super.GetDescriptionText(PropName); } |Mclass MasterServerLink extends Info native transient; // (cpptext) // (cpptext) // (cpptext) // (cpptext) struct native tMasterServerEntry { var string Address; var int Port; }; var native const pointer LinkPtr; var globalconfig int LANPort; var globalconfig int LANServerPort; var globalconfig array MasterServerList; var array ActiveMasterServerList; var int LastMSIndex; // Index of the last used master server native function bool Poll( int WaitTime ); // Cheap and easy load balancing coming up here. /* event GetMasterServer( out string OutAddress, out int OutPort ) { local int Index; Index = rand(MasterServerList.Length); OutAddress = MasterServerList[Index].Address; OutPort = MasterServerList[Index].Port; } */ event GetMasterServer( out string OutAddress, out int OutPort ) { local int Index; if (ActiveMasterServerList.Length==0) { for (Index=0;Index>"$LogString$"<<"); } else if( !Uplink.LogStatLine(LogString) ) // If master server rejects stats for us, disconnect from the Uplink actor. Uplink = None; } |Wclass MasterServerClient extends ServerQueryClient native; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) enum EClientToMaster { CTM_Query, CTM_GetMOTD, CTM_QueryUpgrade, CTM_GetModMOTD, CTM_GetOwnageList }; enum EQueryType { QT_Equals, QT_NotEquals, QT_LessThan, QT_LessThanEquals, QT_GreaterThan, QT_GreaterThanEquals, QT_Disabled // if QT_Disabled, query item will not be added }; struct native export QueryData { var() string Key; var() string Value; var() EQueryType QueryType; }; enum EResponseInfo { RI_AuthenticationFailed, RI_ConnectionFailed, RI_ConnectionTimeout, RI_Success, RI_MustUpgrade, RI_DevClient, RI_BadClient, RI_BannedClient }; enum EMOTDResponse { MR_MOTD, MR_MandatoryUpgrade, MR_OptionalUpgrade, MR_NewServer, MR_IniSetting, MR_Command, }; // Internal var native const pointer MSLinkPtr; var int OwnageLevel; // The current revision for ownage maps var int ModRevLevel; // The current mod news revision level -- Both returned by a MS query var(Query) array Query; var(Query) const int ResultCount; var string OptionalResult; native function StartQuery( EClientToMaster Command ); native function Stop(); native function LaunchAutoUpdate(); delegate OnQueryFinished( EResponseInfo ResponseInfo, int Info ); delegate OnReceivedServer( GameInfo.ServerResponseLine s ); delegate OnReceivedMOTDData( EMOTDResponse Command, string Value ); delegate OnReceivedModMOTDData( string Value ); delegate OnReceivedOwnageItem(int Level, string ItemName, string ItemDesc, string ItemURL); |4class LANQueryClient extends ServerQueryClient; FCG>D֤XFx  c||F@|G@|d|C///============================================================================= // InternetLink: Parent class for Internet connection classes //============================================================================= class InternetLink extends InternetInfo native transient; // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) // (cpptext) //----------------------------------------------------------------------------- // Types & Variables. // An IP address. struct IpAddr { var int Addr; var int Port; }; // Data receive mode. // Cannot be set in default properties. var enum ELinkMode { MODE_Text, MODE_Line, MODE_Binary } LinkMode; // MODE_Line behavior, how to receive/send lines var enum ELineMode { LMODE_auto, LMODE_DOS, // CRLF LMODE_UNIX, // LF LMODE_MAC, // LFCR } InLineMode, OutLineMode; // OutLineMode: LMODE_auto == LMODE_DOS // Internal var const pointer Socket; // (sockets are 64-bit on AMD64, so use "pointer"). var const int Port; var const pointer RemoteSocket; var private native const pointer PrivateResolveInfo; var const int DataPending; // Receive mode. // If mode is MODE_Manual, received events will not be called. // This means it is your responsibility to check the DataPending // var and receive the data. // Cannot be set in default properties. var enum EReceiveMode { RMODE_Manual, RMODE_Event } ReceiveMode; //----------------------------------------------------------------------------- // Natives. // Returns true if data is pending on the socket. native function bool IsDataPending(); // Parses an Unreal URL into its component elements. // Returns false if the URL was invalid. native function bool ParseURL ( coerce string URL, out string Addr, out int Port, out string LevelName, out string EntryName ); // Resolve a domain or dotted IP. // Nonblocking operation. // Triggers Resolved event if successful. // Triggers ResolveFailed event if unsuccessful. native function Resolve( coerce string Domain ); // Returns most recent winsock error. native function int GetLastError(); // Convert an IP address to a string. native function string IpAddrToString( IpAddr Arg ); // Convert a string to an IP native function bool StringToIpAddr( string Str, out IpAddr Addr ); // Validate: Takes a challenge string and returns an encoded validation string. native function string GameSpyValidate( string ValidationString ); native function string GameSpyGameName(); native function GetLocalIP(out IpAddr Arg ); //----------------------------------------------------------------------------- // Events. // Called when domain resolution is successful. // The IpAddr struct Addr contains the valid address. event Resolved( IpAddr Addr ); // Called when domain resolution fails. event ResolveFailed(); |M@(L|@|g|T(|brEK<)r G|NALU G|PCMz G|c>//============================================================================= // BufferedTcpLink //============================================================================= class BufferedTcpLink extends TcpLink; var string InputBuffer; var string OutputBuffer; var string CRLF; var string CR; var string LF; var bool bWaiting; var float WaitTimeoutTime; var string WaitingFor; var int WaitForCountChars; // if we're waiting for X bytes var string WaitResult; var int WaitMatchData; function ResetBuffer() { InputBuffer = ""; OutputBuffer = ""; bWaiting = False; // CRLF = Chr(10)$Chr(13); CR = Chr(13); LF = Chr(10); CRLF = CR $ LF; } function WaitFor(string What, float TimeOut, int MatchData) { bWaiting = True; WaitingFor = What; WaitForCountChars = 0; WaitTimeoutTime = Level.TimeSeconds + TimeOut; WaitMatchData = MatchData; WaitResult = ""; } function WaitForCount(int Count, float TimeOut, int MatchData) { bWaiting = True; WaitingFor = ""; WaitForCountChars = Count; WaitTimeoutTime = Level.TimeSeconds + TimeOut; WaitMatchData = MatchData; WaitResult = ""; } function GotMatch(int MatchData) { // called when a match happens } function GotMatchTimeout(int MatchData) { // when a match times out } function string ParseDelimited(string Text, string Delimiter, int Count, optional bool bToEndOfLine) { local string Result; local int Found, i; local string s; Result = ""; Found = 1; for(i=0;i= Count) Result = Result $ s; } } return Result; } // Read an individual character, returns 0 if no characters waiting function int ReadChar() { local int c; if(InputBuffer == "") return 0; c = Asc(Left(InputBuffer, 1)); InputBuffer = Mid(InputBuffer, 1); return c; } // Take a look at the next waiting character, return 0 if no characters waiting function int PeekChar() { //local int c; if(InputBuffer == "") return 0; return Asc(Left(InputBuffer, 1)); } function bool ReadBufferedLine(out string Text) { /* i = InStr(InputBuffer, CR); if(i == -1) { i = InStr(InputBuffer, LF); if ( i == -1 ) return False; } Text = Left(InputBuffer, i); if(Mid(InputBuffer, i+1, 1) == LF) i++; InputBuffer = Mid(InputBuffer, i+1); */ if ( InputBuffer == "" ) return false; if ( Divide( InputBuffer, CRLF, Text, InputBuffer ) ) return true; if ( Divide( InputBuffer, CR, Text, InputBuffer) ) return true; if ( Divide(InputBuffer, LF, Text, InputBuffer) ) return true; return false; } function SendBufferedData(string Text) { OutputBuffer $= Text; } event ReceivedText(string Text) { InputBuffer $= Text; } // DoQueueIO is intended to be called from Tick(); function DoBufferQueueIO() { local int i; while(bWaiting) { if(Level.TimeSeconds > WaitTimeoutTime) { bWaiting = False; GotMatchTimeout(WaitMatchData); } if(WaitForCountChars > 0) { if(Len(InputBuffer) < WaitForCountChars) break; WaitResult = Left(InputBuffer, WaitForCountChars); InputBuffer = Mid(InputBuffer, WaitForCountChars); bWaiting = False; GotMatch(WaitMatchData); } else { i = InStr(InputBuffer, WaitingFor); if(i == -1 && WaitingFor == CR) i = InStr(InputBuffer, LF); if(i != -1) { WaitResult = Left(InputBuffer, i + Len(WaitingFor)); InputBuffer = Mid(InputBuffer, i + Len(WaitingFor)); bWaiting = False; GotMatch(WaitMatchData); } else break; } } if(IsConnected()) { if( OutputBuffer != "" ) { i = SendText(OutputBuffer); OutputBuffer = Mid(OutputBuffer, i); } } } |T|m|||X@|vcR}D:V ycK3}3}3}  W||@||\@|wFBBB>YFx  ||[|o|@||W@|L|^@||_@||||T]v|E0||S0||e0||@||g@||||`@||n@||g@||jfhv@ff)bDoUplink%i9=,$Check ' G |jhgCDh DoUplink%g 2SendStats&g h G(|c 2|@||s||x@|F|t||}@|X|r@|L|@||||q||.@||||p@||||d@D|N|||v|#|mwFxy|K||||LVDRr G|AYuS G|@@||Cz|@||||@||c ||E@||GotJ&q*************** Complete OBJ LIST:oDobj list'***************Current UdpGameSpyQuery objects:/o #}7ss}107s%No UdpGamespyQuery objects found! o'Dobj list class=udpgamespyquery'***************Tracing UdpGamespyQuery objectsv%v7strvs===================================================================pp Referencers of 't'o4Dpobj refs class=udpgamespyquery name=t'ovsrq%]q7rSr.qr*r.qr*trqrpp Referencers of 't'oADpppobj refs class=9Vqr name=t'**************************************************************************q@===================================================================vMPerforming garbage collectionoDobj garbage'***************Remaining UdpGameSpyQuery objects:o'Dobj list class=udpgamespyquery'*************** G |y@|||#|g ||@|D|M|~|O|~|R}'/ G|||^||U@||Jrr*%pTw%p*@p%&%p&px%x7p{yaBy.aBy9Wxpx[y G |@||]@|A|||Z||[@||\@||@||o@|B|K||`@||a@||b||6||\||e@|f|D||@|D|| O O N\ Nr NL NJ Nk ND Ny Xm N] NU X N[ NN Nt NX NW NT Nx Nv Xx Nj Z^ Ns NH Nc Nl LX NO NH Xv sC \B NZ \A rl uN Xa r_ Nw rS Nn NI rB Xm rn LY r; Nm rh rg Nu XR \O \N s_ \` \Z y yD LQ r r r- IG Nm \b rQ IZ No X~ NH Nm Xp \Y=UlyDvR:Sa:Fo:E~:`L:K\||:Hj>(x(F#YTvb"vqJeNv]>Jk`z||}}H}V|=4me#SRSa@o~|:ILz[2KjfSuMD||>MRGi`JSoBHM}\DjVyD_GtW|ae|ftEOCf}TQc>HrADAA(PAN^}dlePD&_SmfM|#[JHXHg<@Ro<CKAALD(ZD[jox*SgElu|KDFSEb`q|IA||>IP~^|fxldzvHEVW| #gEmJ|D`Y ah=~hvfg^#RmI|=tJF@Y|Jg*Qv|||*`E|0SU:Cc:Jq*E@*FO||*K^Smfh{|CJ>KYghXvvEXSvb[pAF|Mj[AEj\yXH<-(W}|DJMd[|Ej| SyhGpeUPc#|r#P@c #Onr@dAMQ@h`A`oAgkMt^{m|=o|TK]_|nHG9dX>Lh|9hv\E:([bi|6o{kJ|ZEZ|B$iA$M/`q0`A0EQ0F`0Ko)o~ZeM)t\||ZFk^hy^eHcfW^FnfK|dKfLZFiEx~$Godk`{ohJo`Yvoiv`xugHzdWzhgz`vygF{gT~ob~`qoAtP|_=*"m<QO=+#^GAGPF_YnE}CLe[`j`zoJGYEkiD} yNFDTEubD{ qP~hMt\`kpzLI `WEtgEsv|=Q EwOz]F{l`{gK=_ ZFa$eFb$IFmD^{^D PYD62iDz,[DhG^D*kofZ`D+@iD;riDc[f~#3LMfY#1LhftfC#)FRfX#wff]#!akDyLfE#KSf^#Ml"fyfG#VV*flcp{cqLcr\csn'sc(N#|v0fr)fAch#O-frcz&@#zf/f`cy#n2fQc,"_4fAc %O:ft6fBc#(P#h x>f`9foc:%}#Rb=ftc'(B^# Uj|@fcf#Mce#pcc#S#;YvgOc>#]Ii@c$#NKhqKd@|||||||||||bMOaP\|||_Qlgd}ghLg`[ #kbFN5#\dF^gM$#tjiWj`e>#uffX^gf^`tofD'+R\F}pfCvfR[7`sfWZde:(IufqzfT-M#+zX -e~fRSB` (bfJJBKX|JnJc(m|<RU`d=d&sfY="g<9%Ifnf|<PiJ=%sfX=`)fhOE]]EbnEg HfT=.%bfGEFU=]#d=/%Gfl=Y2zflEqzErIE!XEly=X#e=WHErbY=R{EqsJE<%}|fbJE-}p||=^mFc~a4^MGkHzxKFIZDa4lbkGWHfFKvF=4G#a4s{|ca4`8nFa4ENEa4HHS<a4Y[F`"tF_XVJa4Gna4cua4?XFGjWdAcOH]=a4O/l||({(Kj[E&i|A"OC"qa4o>SnBlSoacDFrxxqGFBgXkcPs^{o|~zMEv[<TuiD=US`bZpmEkNp]EflEhV{EgZQEj k|ft ^B`R Uc Or \C oTIb }reA}OG]G[l<EzNK RY=KiXwtGD$Uu$ys]<zl#vE`STb=VpcT#tfNft\C=ZREa=]q=PBF}#SfvJDLS#rlbcNS\Omm|MKUZViWwgHElWEkgEjwEiFEmT<uc<tt$uCXS