Page 1 of 3

RCON Protocol on PB

Posted: Sun Jun 28, 2009 7:25 pm
by registrymechanic22
Hello.
At once I apologise for my English, I Russian.
Prompt how to realise please this "RCON Protocol" on PB.
Has searched all Internet of anything except examples in other languages has not found ((.
I can not understand has washed off as with what it is required to send and what to receive.
More low I give the reference where the format "RCON Protocol" is described:
http://developer.valvesoftware.com/wiki ... N_Protocol

...In the bottom of this page there are examples on C #, C ++, Ruby, Java, Python, VisualBasic and PHP, The algorithm can from them it will turn out to copy.

In advance thanks

Posted: Sun Jun 28, 2009 9:19 pm
by SFSxOI
I dont find anything at the link you posted. Do you have a good link?

I'd like to see the visual basic code.

Posted: Sun Jun 28, 2009 9:22 pm
by helpy

Posted: Sun Jun 28, 2009 9:24 pm
by SFSxOI
Yep, just figured that out :)

I wanted to look at the VB source but the link for the VB source isn't any good.

Posted: Sun Jun 28, 2009 10:13 pm
by registrymechanic22
SFSxOI wrote:I dont find anything at the link you posted. Do you have a good link?
I'd like to see the visual basic code.
Simply at many forums direct references on other resources of the Internet are forbidden, therefore I have put the bottom blank before the reference, but it was all the same defined as the reference to Internet page :)

Once again I write, but already a direct reference on a format "RCON_Protocol":
http://developer.valvesoftware.com/wiki ... N_Protocol

Posted: Tue Jun 30, 2009 10:20 pm
by registrymechanic22
The question is still actual...
help please

Posted: Fri Jul 03, 2009 8:33 am
by infratec
Hi registrymechanic22,

I wrote something for you.
But it is not tested :!:

You have to compile it for 'console' and use it in a DOS-Box.

Code: Select all

;
; RCon
;
; idea from a C sourcecode at http://developer.valvesoftware.com/wiki/Source_RCON_Protocol
;
; V1.00 first try
; V1.01 second try
; V1.02 now RConSend() is working
; V1.03 fixed a typo in RConReceive(), added mor verbose output (I can not test this)
; V1.04 now the received data can come in pieces, better hex output (-v -v)
;       also multiple answers are accepted now. (hope so)
;       New parameter -i to set the ID
; V1.05 It should work now! Several changes. Tested with an emulator.
; V1.06 Now also a multipacket receive is handled correct
; V1.07 Long answer strings should be handled correct now
; V1.08 changed all string stuff to UTF8

EnableExplicit

#SERVERDATA_AUTH = 3
#SERVERDATA_AUTH_RESPONSE = 2
#SERVERDATA_EXECCOMMAND = 2
#SERVERDATA_RESPONSE_VALUE = 0


Structure RCONPacketHeaderStructure
  Size.l
  ID.l
  Type.l
EndStructure


Global Verbose.i




Procedure HexListing(*Buffer, Length)
  
  Protected i.i, Hex$, Byte.a, Ascii$
    
  For i = 0 To Length - 1
    Byte = PeekA(*Buffer + i)
    
    Hex$ + RSet(Hex(Byte), 2, "0") + " "
    
    If Byte > 31
      Ascii$ + Chr(Byte)
    Else
      Ascii$ + "."
    EndIf
    
    If (i + 1) % 16 = 0
      PrintN(Hex$ + " " + Ascii$)
      Hex$ = ""
      Ascii$ = ""
    ElseIf (i + 1) % 8 = 0
      Hex$ + "- "
    EndIf
    
  Next i
  
  If Length % 16 <> 0
    PrintN(LSet(Hex$, 50) + " " + Ascii$)
  EndIf
  
EndProcedure




Procedure.i RConSend(Con, ID.l, Type.l, Str1$, Str2$="")
  
  Protected Result.i, PacketSize.l, *Buffer.RCONPacketHeaderStructure
  
  If Verbose > 1
    PrintN("RConSend")
  EndIf
  
  PacketSize = SizeOf(RCONPacketHeaderStructure) + StringByteLength(Str1$, #PB_Ascii) + 1 + StringByteLength(Str2$, #PB_Ascii) + 1 ; + 1s for the terminating 0s
  
  *Buffer = AllocateMemory(PacketSize)
  If *Buffer
    *Buffer\Size = PacketSize - SizeOf(Long)
    *Buffer\ID = ID
    *Buffer\Type = Type
    PokeS(*Buffer + SizeOf(RCONPacketHeaderStructure), Str1$, -1, #PB_Ascii)
    PokeS(*Buffer + SizeOf(RCONPacketHeaderStructure) + StringByteLength(Str1$, #PB_Ascii) + 1, Str2$, -1, #PB_Ascii) ; + 1 for the terminating 0 of Str1$
    
    If Verbose > 1
      PrintN("Sending:")
      HexListing(*Buffer, PacketSize)
      PrintN("")
    EndIf
    
    Result = SendNetworkData(Con, *Buffer, PacketSize)
    
    FreeMemory(*Buffer)
    
  EndIf
  
  ProcedureReturn Result
  
EndProcedure




Procedure.i RConReceive(Con, *ID, *CommandResponse, *Str1, *Str2, MaxWait)
  
  Protected.i Result, *Buffer.RCONPacketHeaderStructure, Answer.i, BuffPtr.i, Received.i, Length.i
  
  
  If Verbose > 1
    PrintN("RConReceive")
  EndIf
  
  *Buffer = AllocateMemory(8192)
  If *Buffer
    
    Answer = #False
    
    Repeat
      
      Select NetworkClientEvent(Con)
        Case #PB_NetworkEvent_None
          Delay(10)
          MaxWait - 10
          
        Case #PB_NetworkEvent_Data
          
          Length = ReceiveNetworkData(Con, *Buffer + BuffPtr, 8192 - BuffPtr)    
          
          If Length > 0
            
            Received + Length
            
            If Verbose > 1
              PrintN("Received:")
              HexListing(*Buffer + BuffPtr, Length)
              PrintN("")
            EndIf     
            
            If Not Result And Length > 3
              Result = *Buffer\Size
            EndIf
            
            If Received >= Result + 4
              
              PokeL(*ID, *Buffer\ID)
              PokeL(*CommandResponse, *Buffer\Type)
              PokeS(*Str1, PeekS(*Buffer + SizeOf(RCONPacketHeaderStructure), -1, #PB_Ascii), -1, #PB_Ascii)
              PokeS(*Str2, PeekS(*Buffer + SizeOf(RCONPacketHeaderStructure) + StringByteLength(PeekS(*Buffer + 12, -1, #PB_Ascii), #PB_Ascii) + 1), -1, #PB_Ascii)
              
              Answer = #True
              
            EndIf
            
            BuffPtr + Length
            
          EndIf
        
        Case #PB_NetworkEvent_Disconnect
          If Verbose
            PrintN("Receive disconnect!")
          EndIf
          Break
        
      EndSelect
      
    Until MaxWait <= 0 Or Answer
    
    FreeMemory(*Buffer)
    
    If Verbose
      If MaxWait < 0
        PrintN("Receive timeout!")
      EndIf
    EndIf
    
    If Not Answer
      Result = 0
    EndIf
    
  EndIf
  
  ProcedureReturn Result
  
EndProcedure




Procedure RConProcessResponse(Con, OurID, CommandExpectedAnswer)
  
  Protected Result.i, ID.l, CommandResponse.l, *Str1, *Str2
  
  Result = -1
  
  *Str1 = AllocateMemory(4096)
  If *Str1
    *Str2 = AllocateMemory(4096)
    If *Str2
      If Verbose > 1
        PrintN("RConProcessResponse")
      EndIf
      
      While RConReceive(Con, @ID, @CommandResponse, *Str1, *Str2, 1000) > 0
        
        If Verbose
          PrintN("Received something")
        EndIf
        
        If CommandResponse = CommandExpectedAnswer
          
          Select CommandResponse
            
            Case #SERVERDATA_AUTH_RESPONSE
              If ID = OurID
                Result = 1
              ElseIf ID = -1
                PrintN("Password refused")
              Else
                PrintN("Bad Auth Response ID: " + Str(ID))
              EndIf
              
            Case #SERVERDATA_RESPONSE_VALUE
              PrintN("RCon answer:")
              PrintN(PeekS(*Str1, -1, #PB_Ascii))
              Result = 2
              
            Default
              PrintN("Unexpected command response: " + Str(CommandResponse))
              
          EndSelect
          
          Break
          
        EndIf
        
      Wend
      
      FreeMemory(*Str2)
    EndIf
    FreeMemory(*Str1)
  EndIf
  
  ProcedureReturn Result
  
EndProcedure




Procedure Usage()

 PrintN("")
 PrintN("RCon V1.08 (c) Infratec")
 PrintN("")
 PrintN("usage: RCon -s server -p password command [-i ID][-P port][-h][-v]")
 PrintN("")
 PrintN(" -s server   : the name or the IP address of the server")
 PrintN(" -p password : the password for authentication")
 PrintN(" command     : what you want to send")
 PrintN(" -i ID       : the ID you want to use (default is 0)")
 PrintN(" -P port     : the port you want to use (default is 27015)")
 PrintN(" -h          : shows this help")
 PrintN(" -v          : increase verbosity")
 PrintN("")
 
 End
 
EndProcedure




Define Port.i, Passwd$, Server$, Command$, OurID.i, i.i,Parameter$, Con.i


Port = 27015
Server$ = "127.0.0.1"

If OpenConsole()
  
  If InitNetwork()
  
    For i = 0 To CountProgramParameters() - 1
      
      Parameter$ = ProgramParameter(i)
      
      If FindString(Parameter$, "-h", 1)
        Usage()
      ElseIf FindString(Parameter$, "-v", 1)
        Verbose + 1
      ElseIf FindString(Parameter$, "-s", 1)
        i + 1
        Server$ = ProgramParameter(i)
      ElseIf FindString(Parameter$, "-p", 1)
        i + 1
        Passwd$ = ProgramParameter(i)
      ElseIf FindString(Parameter$, "-i", 1)
        i + 1
        OurID = Val(ProgramParameter(i))
      ElseIf FindString(Parameter$, "-P", 1)
        i + 1
        Port = Val(ProgramParameter(i))
      Else
        Command$ = Parameter$
      EndIf
      
    Next i
    
    
    If Verbose > 0
      PrintN("")
      PrintN("Server  : " + Server$)
      PrintN("Port    : " + Str(Port))
      PrintN("Password: " + Passwd$)
      PrintN("Command : " + Command$)
      PrintN("ID      : " + Str(OurID))
      PrintN("Verbose : " + Str(Verbose))
      PrintN("")
    EndIf
    
    
    Con = OpenNetworkConnection(Server$, Port, #PB_Network_TCP)
    If Con
      
      If RconSend(Con, OurID, #SERVERDATA_AUTH, Passwd$) > 0
        If RConProcessResponse(Con, OurID, #SERVERDATA_AUTH_RESPONSE) = 1
          PrintN("Password accepted")
          If RConSend(Con, OurID, #SERVERDATA_EXECCOMMAND, Command$) > 0
            If RConProcessResponse(Con, OurID, #SERVERDATA_RESPONSE_VALUE) <> 2
              PrintN("No answer received for: " + Command$)
            EndIf
          Else
            PrintN("Was not possible to send: " + Command$)
          EndIf
        Else
          PrintN("Authentication failed")
        EndIf
      Else
        PrintN("Send failed")
      EndIf
      
      CloseNetworkConnection(Con)
      
    Else
      PrintN("Was not able to establish a connection to " + Server$ + " at port " + Str(Port))
    EndIf
    
  EndIf
  
  CloseConsole()
  
EndIf
Good luck!


And if you have to modify something, that it works, than please
put the working result here in the forum.

Best regards,

Bernd

Posted: Fri Jul 03, 2009 1:40 pm
by registrymechanic22
infratec wrote:Hi registrymechanic22,
hi infratec.
many thanks for the work
(((... but
result of the program: "Authentication failed" (
and closing of the console)...
because it does not pass the condition: "If NetworkClientEvent(Con) = #PB_NetworkEvent_Data"


P.S.: After several runs of this code, a game server denies access (Ban) used by IP (127.0.0.1:27015 ), the use of an incorrect rcon_password.

Posted: Fri Jul 03, 2009 3:02 pm
by infratec
Hi registrymechanic22,

I made a fault by typing:

Code: Select all

Until MaxWait > 0 Or Answer
should be

Code: Select all

Until MaxWait < 0 Or Answer

I also forgot to set

Code: Select all

Answer = #True
after the last PokeS().

Try it.
(I changed tho code above)


And I don't know what ID is.
At the moment it is fixed to 20.

Bernd

Posted: Fri Jul 03, 2009 4:20 pm
by registrymechanic22
infratec wrote:

Code: Select all

Until MaxWait > 0 Or Answer
should be

Code: Select all

Until MaxWait < 0 Or Answer
I also forgot to set

Code: Select all

Answer = #True
after the last PokeS().
Try it.
(I changed tho code above)
Bernd

: (
sorry, not working
as RConProcessResponse(Con) is not equal to 1, writes "Authentication failed"

Posted: Fri Jul 03, 2009 6:40 pm
by infratec
Hi,

hm, it looks that the Server is not responding during 100ms.

So I increased the timeout value.

Please use the new code and start it with -v as parameter.

Bernd

Posted: Fri Jul 03, 2009 7:24 pm
by registrymechanic22
infratec wrote:Hi,
hm, it looks that the Server is not responding during 100ms.
So I increased the timeout value.
Please use the new code and start it with -v as parameter.
Bernd
I can not do something
console closes immediately after launch
only through the Delay (), I can see the "Authentication failed"

please explain where to prescribe the parameters?? or they need to write when running code (program)??

Posted: Fri Jul 03, 2009 8:52 pm
by infratec
Hi,

so, you are below 20 years old, and you have no idea what a command shell is, and you don't read what someone wrote :D
You have to compile it for 'console' and use it in a DOS-Box.
What do you think what this means?

I'll explain it for you:

:!: IT IS NOT A WINDOWS PROGRAM :!:


1. In PureBASIC goto 'Compiler'->'Compiler options' and change the executable format to console.
2. Goto 'Compiler'->'create executable' and generate a executable file.
3. Than click on your windows 'Start' and select something like 'execute'
(sorry I don't know which language your version of windows has)
4. Than enter 'cmd' in the field.
5. Now a 'DOS-Box' will open.
6. Change the directory to the place were you have stored the executable
(use the 'cd' command for that. 'cd \bla\bla\bla' and press 'enter')
7. Enter the programname and add '-h' as parameter, than you can see what you can do and what you should do.

Best regards,

Bernd

Posted: Fri Jul 03, 2009 9:36 pm
by infratec
Hi registrymechanic22,

I just added more debug messages and tested the program against a webserver.

So I found a few more bugs in my code.

I changed it in the code above.

The RConSend() should work now as expected.
(sorry , but I code this stuff without a possibility to test something)

Use -v -v as additional parameters, than you can see which bytes are transmitted.


Best regards,

Bernd

Posted: Fri Jul 03, 2009 11:18 pm
by registrymechanic22
infratec wrote:Hi,
:!: IT IS NOT A WINDOWS PROGRAM :!:
1. In PureBASIC goto 'Compiler'->'Compiler options' and change the executable format to console.
2. Goto 'Compiler'->'create executable' and generate a executable file.
3. Than click on your windows 'Start' and select something like 'execute'
(sorry I don't know which language your version of windows has)
4. Than enter 'cmd' in the field.
5. Now a 'DOS-Box' will open.
6. Change the directory to the place were you have stored the executable
(use the 'cd' command for that. 'cd \bla\bla\bla' and press 'enter')
7. Enter the programname and add '-h' as parameter, than you can see what you can do and what you should do.
hello infratec.

from 2 to 6 points I know, a seventh is usually specified in the properties of the label (the program).
i am LOL :oops:
I thought it all the harder, and turned ordinary))
**************************************************
RConSend () works fine, BUT:
PB gives the error on:
Length = ReceiveNetworkData(Con, *Bufffer, 8192)
error: The specified buffer is 0.
..................

I am much grateful to you for your help!!!