RawRead freezez

Topics: Admin Tool, Developers
Feb 27, 2012 at 7:13 PM
Edited Feb 27, 2012 at 7:50 PM

Hi,

I'm trying to use the lib in a winform program.

If I use the RawRead, the app freezes.

Here's my tiny test code...

Private WithEvents rcon As New System.Net.Battlefield3.RconClient


Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    rcon.Address = "173.xx.xx.xx"
    rcon.Port = 25xxx
    rcon.Connect()
End Sub


Private Sub rcon_Connected(sender As Object, e As System.EventArgs) Handles rcon.Connected
    rcon.LogOn("xxxx")
End Sub

Private Sub rcon_RawRead(sender As Object, e As System.Net.Battlefield3.RawReadEventArgs) Handles rcon.RawRead
    ' Just having this sub with nothing in it freezez the program
End Sub

If I remove the rcon_RawRead sub, then program works fine. In my test, I have no code at all in the rcon_RawRead sub.

Is it some kind of locking problem?

Thanks

Mojo

Coordinator
Feb 28, 2012 at 3:24 PM

What would actually happen is a long pause, not a total freeze, whether or not anything was in the RawRead event handler. This also caused another problem when trying to login synchronously, where it would basically fail.

Luckily, the solution to all of this is to login asynchronously using RconClient.LogOn("pass", True). If you need to do any post-logon routines, you can use the LoggedOn event.

Since you're working with a WinForms application, I should tell you about a feature I forgot to put into the documentation (except for 1 property with a weird name most people would probably ignore). Normally, when working with multiple threads, you would have to use InvokeRequired and Invoke to be able to modify any form or control in order to do everything on the main (UI) thread. This ability is built into the library so you don't have to write all of that extra code.

If you ever need to disable it, though, you can set DisableSynchronizeChecking to true.

Feb 28, 2012 at 4:11 PM

Something is definately wrong here.

If I use the ... rcon.LogOn("x", True) ... then RConClient is dealy silent .. if I remove the ... ,True ... then everything is fine - except...

If I listen to the RawRead Event, then I get this:

RawRead: OK
RawRead: LogInRequired
RawRead: LogInRequired
RawRead: UnknownCommand
RawRead: UnknownCommand

... and nothing else happens. RConClient is dead silent. If I comment out the RawRead event, then everything works fine again (except I get no messages like PunkBuster etc.).

Just crete a new VB.Net project, link to your lib and enter this code (you have credentials for my server)...

Public Class Form1

    Private WithEvents rcon As New System.Net.Battlefield3.RconClient

	
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        rcon.Address = "x.x.x.x"
        rcon.Port = x
        rcon.Connect()
    End Sub


    Private Sub rcon_Connected(sender As Object, e As System.EventArgs) Handles rcon.Connected
        rcon.LogOn("x")
    End Sub


    Private Sub rcon_LoggedOn(sender As Object, e As System.EventArgs) Handles rcon.LoggedOn
        rcon.DisableSynchronizeChecking = False
    End Sub


    Private Sub rcon_PlayerKilled(sender As Object, e As System.Net.Battlefield3.PlayerKilledEventArgs) Handles rcon.PlayerKilled
        Console.WriteLine("Killed: " + If(e.Attacker IsNot Nothing, e.Attacker.Name, ""))
    End Sub


    Private Sub rcon_PlayerSpawned(sender As Object, e As System.Net.Battlefield3.PlayerEventArgs) Handles rcon.PlayerSpawned
        Console.WriteLine("Spawned: " + If(e.Player IsNot Nothing, e.Player.Name, ""))
    End Sub


    Private Sub rcon_RawRead(sender As Object, e As System.Net.Battlefield3.RawReadEventArgs) Handles rcon.RawRead
        Console.WriteLine("RawRead: " + e.Packet.Words(0))
    End Sub

End Class

 

Yes I'm aware that I need to use InvokeRequired, but in the test sample above it's not necessary.


Any idea what is wrong here?

Thanks :)

Mojo

Coordinator
Feb 28, 2012 at 4:41 PM

After I changed rcon.LogOn("x") to rcon.LogOn("x", True), it worked fine for me.

You also don't need to set  DisableSynchronizeChecking to false anymore since it defaults to that.

And, as long as DisableSynchronizeChecking is false, you don't need to use InvokeRequired.

Feb 28, 2012 at 4:48 PM
Edited Feb 28, 2012 at 4:49 PM

If I put ... ,True ... on my sample above, then I get this:

RawRead: OK
RawRead: OK
RawRead: UnknownCommand
RawRead: UnknownCommand
RawRead: UnknownCommand 

... but now I don't get any events like joining, killing, spawning etc and I don't get any other rawread info like PunkBuster etc.

I don't get it - my sample is trimmed to only the code above and you get a different result than I do .. strange.

:)

Don't know if it's a firewall problem since the code runs behind a Microsoft TMG. I will test on another Pc.

Coordinator
Feb 28, 2012 at 4:50 PM
Edited Feb 28, 2012 at 4:54 PM

Well here's the code I'm using, which includes a multiline textbox

 

Imports System.Text

Public Class Form2

    Private WithEvents rcon As New System.Net.Battlefield3.RconClient


    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        rcon.Address = "lol"
        rcon.Port = 1337
        rcon.Connect()
    End Sub


    Private Sub rcon_Connected(ByVal sender As Object, ByVal e As System.EventArgs) Handles rcon.Connected
        rcon.LogOn("urmom", True)
    End Sub

    Private Sub rcon_PlayerKilled(ByVal sender As Object, ByVal e As System.Net.Battlefield3.PlayerKilledEventArgs) Handles rcon.PlayerKilled
        TextBox1.AppendText("Killed: " + If(e.Attacker IsNot Nothing, e.Attacker.Name, ""))
        TextBox1.AppendText(vbCrLf)
    End Sub


    Private Sub rcon_PlayerSpawned(ByVal sender As Object, ByVal e As System.Net.Battlefield3.PlayerEventArgs) Handles rcon.PlayerSpawned
        TextBox1.AppendText("Spawned: " + If(e.Player IsNot Nothing, e.Player.Name, ""))
        TextBox1.AppendText(vbCrLf)
    End Sub


    Private Sub rcon_RawRead(ByVal sender As Object, ByVal e As System.Net.Battlefield3.RawReadEventArgs) Handles rcon.RawRead
        TextBox1.AppendText(PacketToString(e.Packet))
    End Sub
    Shared Function PacketToString(ByVal p As Packet) As String
        Dim sb As New StringBuilder()
        sb.AppendFormat("RawRead: {0} {1} S={2}", p.IsResponse, p.IsFromServer, p.Sequence)
        For Each s As String In p.Words
            sb.AppendFormat(":: {0} ", s)
        Next
        sb.AppendLine()
        Return sb.ToString()
    End Function
End Class

Feb 28, 2012 at 5:42 PM
Edited Feb 28, 2012 at 5:45 PM

I pasted in your exact code (changed IP, port and psw) and here's my result after letting it run for 4 minutes:

Free Filehosting At image upload

I tried running it from outside the company network with same result.

This is really strange.

I used the latest version of your source.

Coordinator
Feb 28, 2012 at 6:44 PM
Edited Feb 28, 2012 at 6:47 PM

It's kind of hard to find the problem since I can't debug your code. Walking through the code in my head, I haven't found anything that would cause that problem.

Since the logon packets show up in the RawRead, receiving data doesn't appear to be the problem. So, to not be able to receive events, which would be enabled after the RawRead of that second packet, some code is blocking sometime before line 1095. The only part of the code between the RawRead (line 1038) and line 1095 that could block other reads is the lock on the SynchronousReadTracker; however, none of the code in the lock statement should block.

So, the way to be sure that the problem is with enabling events is to see if IsLoggedOn is true after the second packet is received. Can you check that value a few seconds after you receive that packet for me?

To test whether or not the lock is the problem, you can do a synchronous read a few seconds after you receive that second packet. If SendRequest returns null, then that part would be part of the problem.

Feb 28, 2012 at 7:33 PM

I understand. Most funny thing is, that I just copy paste exactly your code.

IsLoggodOn is true all the time.

This ...

Dim p As Packet = rcon.SendRequest("listPlayers")

.. results in a p = nothing.

Is that any help?

Coordinator
Feb 28, 2012 at 8:01 PM

To try and get more information about the problem, I made a small change to the code that may or may not help. Also, you could try stepping through HandlePacketReceive to try and find the problem.

Feb 28, 2012 at 8:02 PM

Ok will test it now .. in the sendrequest, here's where it hangs...

if (!state.ManualResetEvent.Wait(SynchronousReadTimeout * 1000, state.Cancel.Token)) return null;

Coordinator
Feb 28, 2012 at 8:12 PM

Well I know it pauses for 10 seconds there. I'm wondering where in HandlePacketReceive the problem is.

Feb 28, 2012 at 8:13 PM

Ok .. If I run with your new update, then when I send the ... Dim p As Packet = rcon.SendRequest("listPlayers", "all") ... then program freezes for about 10 seconds and return p = nothing ... but now RawRead gets the playerList (so a little progress).

I still don't recieve any other events like PlayerKilled etc.

Coordinator
Feb 28, 2012 at 8:15 PM

Also, since you probably won't see this post until after you look at HandlePacketReceive, the packet I'm looking for is the one with a sequence number of 1.

Feb 28, 2012 at 8:22 PM

It's bed time now :) .. if you want, I (tomorrow) can set up a virtual machine with VS2010 and install teamviewer ... then you can log in and test it?

Coordinator
Feb 28, 2012 at 8:23 PM

Sure :D

Feb 29, 2012 at 6:00 PM

Ok I'm ready - tell we when you're ready - so i will send you ID and code :)

Feb 29, 2012 at 6:37 PM

Hold your horses!!! .. I just tried again - downloaded the latest source code and ... vupti ... it works!!! COOOL!!! Dunno if you made any changes, but something changed.

When downloading your source, which folder should I use ... branches/dev  ... or ... trunk/BF3Rcon?

Thanks for all your help!! :)

 

Coordinator
Feb 29, 2012 at 7:18 PM

dev branch

and at least it's working now ftw