danikf / tik4net

Manage mikrotik routers with .NET C# code via ADO.NET like API or enjoy O/R mapper like highlevel api.
Apache License 2.0
177 stars 94 forks source link

Cancel command is not fully implemented #35

Closed AsafMag closed 6 years ago

AsafMag commented 6 years ago

I was able to find the reason cancel command cancels simultaneous sniff commands:

https://wiki.mikrotik.com/wiki/Manual:API#.2Fcancel.2C_simultaneous_commands

It looks like you don't add the tag of the specific command correctly, and don't add a tag for the cancel command itself.

Let a sniff command use tag=5, for example, and a tag for cancel itself be 17.

It looks like you send: /cancel.=.tag=5. where . is a placeholder for (0x07, 0x07, ., 0x00) instead of: /cancel.=tag=5..tag=17. where . is a placeholder for (0x07, 0x06, 0x06, ., 0x00)

Note the dot before the first tag, it is even written in remarks in CancelInternal.

From the link: optional argument: =tag=tag of command to cancel, without it cancels all running commands

So I tried adding a new property to TikSpecialProperties: private const string CancelTag = "=tag"; and add it as a second parameter to CancelInternal, something like this:

int tag = Interlocked.Increment(ref _tagCounter);

ApiCommand cancelCommand = new ApiCommand(_connection, "/cancel",
    new ApiCommandParameter(TikSpecialProperties.CancelTag, _runningTag.ToString()),
    new ApiCommandParameter(TikSpecialProperties.tag, tag.ToString()));

But now I'm stuck with: /cancel.=tag=5.=.tag=17. The third = shouldn't be there. It works perfectly if it isn't there - I can simultaneously sniff with 2 different interfaces and send a hard coded cancellation to one of them and the other keeps sniffing!

danikf commented 6 years ago

Hi, thank you for investigating this issue. It was (hopefully) fixed by last commit.

Sample code:

            var cmdWlan = Connection.CreateCommandAndParameters("/interface/monitor-traffic", "interface", "wlan1");
            List<ITikReSentence> responsesWlan = new List<ITikReSentence>();
            cmdWlan.ExecuteAsync(re => responsesWlan.Add(re));

            var cmdEth = Connection.CreateCommandAndParameters("/interface/monitor-traffic", "interface", "ether1");
            List<ITikReSentence> responsesEth = new List<ITikReSentence>();
            cmdEth.ExecuteAsync(re => responsesEth.Add(re));

            Thread.Sleep(1000);
            cmdWlan.CancelAndJoin();
            var cnt = responsesEth.Count;

            Thread.Sleep(1000);
            Assert.IsTrue(cmdEth.IsRunning);
            cmdEth.CancelAndJoin();

            Assert.IsTrue(responsesEth.Count > cnt);

And communication:

> /interface/monitor-traffic
> =interface=wlan1
> .tag=1

> /interface/monitor-traffic
> =interface=ether1
> .tag=2

< !re
< =name=ether1
< =rx-packets-per-second=0
< =rx-drops-per-second=0
< =rx-errors-per-second=0
< =rx-bits-per-second=208
< =tx-packets-per-second=0
< =tx-drops-per-second=0
< =tx-errors-per-second=0
< =tx-bits-per-second=0
< .tag=2

< !re
< =name=wlan1
< =rx-packets-per-second=0
< =rx-drops-per-second=0
< =rx-errors-per-second=0
< =rx-bits-per-second=0
< =tx-packets-per-second=0
< =tx-drops-per-second=0
< =tx-errors-per-second=0
< =tx-bits-per-second=0
< .tag=1

...

> /cancel
> =tag=1
> .tag=c_1

< !trap
< =category=2
< =message=interrupted
< .tag=1

< !done
< .tag=c_1

< !done
< .tag=1

...

> /cancel
> =tag=2
> .tag=c_2

< !trap
< =category=2
< =message=interrupted
< .tag=2

< !done
< .tag=c_2

< !done
< .tag=2

D