RCON Protocol on PB

Just starting out? Need help? Post your questions and find answers here.
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

RCON Protocol on PB

Post 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
Last edited by registrymechanic22 on Mon Jun 29, 2009 6:50 pm, edited 2 times in total.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post 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.
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Post by helpy »

Windows 10 / Windows 7
PB Last Final / Last Beta Testing
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post 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.
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post 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
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post by registrymechanic22 »

The question is still actual...
help please
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post 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
Last edited by infratec on Wed Dec 23, 2015 6:49 pm, edited 15 times in total.
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post 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.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post 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
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post 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"
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post 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
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post 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)??
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post 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
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post 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
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Post 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!!!
Post Reply