Why are the messages sent over WebRTC received in a different order sometimes? - webrtc

I use ordered set to true, however when many (1000 or more) messages are sent in a short period of time (< 1 second) the messages received are not all received in the same order.
rtcPeerConnection.createDataChannel("app", {
ordered: true,
maxPacketLifeTime: 3000
});
I could provide a minimal example to reproduce this strange behavior if necessary.
I also use bufferedAmountLowThreshold and the associated event to delay when the send buffered amount is too big. I chose 2000 but I don't know what the optimal number is. The reason I have so many messages in a short period of time is because I don't want to overflow the maximum amount of data sent at once. So I split the data into 800 Bytes packs and send those. Again I don't know what the maximum size 1 message can be.
const SEND_BUFFERED_AMOUNT_LOW_THRESHOLD = 2000; //Bytes
rtcSendDataChannel.bufferedAmountLowThreshold = SEND_BUFFERED_AMOUNT_LOW_THRESHOLD;
const MAX_MESSAGE_SIZE = 800;
Everything works fine for small data that is not split into too many messages. The error occurs randomly for big files only.

In 2016/11/01 , there is a bug that lets the dataChannel.bufferedAmount value change during the event loop task execution. Relying on this value can thus cause unexpected results. It is possible to manually cache dataChannel.bufferedAmount, and to use that to prevent this issue.
See https://bugs.chromium.org/p/webrtc/issues/detail?id=6628

Related

Are there alternatives to Redis when buffering is undesired and unacceptable?

I want to stream real-time sensor data(webcam, laser point cloud, etc.) from one robot to multiple observers.
In this use case, only the newest data is useful. For example, when a new frame of point cloud arrives, the older ones will be useless.
Redis has nice publisher/consumer support, but it has buffers according to (Redis Pubsub and Message Queueing).
So are there better alternatives? Something like ROS's publishers/subscribers. They have a message queue size parameter.
/**
* The subscribe() call is how you tell ROS that you want to receive messages
* on a given topic.
*
* The second parameter to the subscribe() function is the size of the message
* queue. If messages are arriving faster than they are being processed, this
* is the number of messages that will be buffered up before beginning to throw
* away the oldest ones.
*/
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
Maybe you can use redis list data structure for your purpose, like a queue. The list data structure in redis is made with linked list and adding a new item is O(1). Whenever your robot produces data it can put it in a list with LPUSH command, and when you want to get the latest item from the list use LRANGE "key-name" 0 0. This command will retrive the latest pushed item. Also if you want to not accumulate the data in queue, you may try to use LTRIM before LRANGE to maintain the latest records. For example LTRIM "key-name" 0 10 will keep the records of last 10 elements. This trim interval should be set according to your observer processing speeds. ref: https://redis.io/docs/data-types/lists/

Akka.net scheduler sends just first value and doesn't update it, How fix it

I can't find the answer to an interesting moment.
in akka.net I have the scheduler. It will work in actor which are sort out a number.
here a simple implementation
_statusScheduler = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(
TimeSpan.FromSeconds(_shedulerInterval),
TimeSpan.FromSeconds(_shedulerInterval),
_reporterActor,
new ProgressReport(requestId, _testedQuantity),
Self);
where
_shedulerInterval - 5-second interval,
_testedQuantity - quantity of tested number all time updated.
and after 5 seconds it is sent 0; always, not a changed number. And here is a question: is it possible to send updated quantity?
I can't send the message to the updating quantity from Recieve<> methods, because my actor is handled the counting message and it is counted the quantity all the time and updated it(when it finished it will receive next message). But all five seconds I should generate a report by a scheduler. Is it possible to fix it?
I think now I need to send all logic because it works fine, and the stone of my problem is scheduler behavior.
The issue you have here is that the message you pass into the scheduler, new ProgressReport(requestId, _testedQuantity), is what is going to be sent each time. Since you're passing in those integer values by value, the object is going to have the original values for those fields at the time you created the message and therefore the message will never update.
If you want to be able to change the content that is sent in the recurring scheduler, do this instead:
var self = Self; // need a closure here, since ActorContext won't be available
_statusScheduler = Context.System.Scheduler.Advanced.ScheduleRepeatedlyCancelable(interval, interval, () => {
_reporterActor.Tell(new ProgressReport(requestId, _testedQuantity), self);
});
This usage of the scheduler will generate a new message each time when it invokes the lambda function and thus you'll be able to include the updated integer values inside your object.

What is the unit for SoftLayer_Virtual_Guest:getBandwidthDataByDate

Do you know what is the unit for SoftLayer_Virtual_Guest:getBandwidthDataByDate?
Bit, byte or Octect?
I found some mismatching between the return value from API and portal.
Thanks.
The method that you are using will return an "average: bandwith usage, but the portal uses another method which returns a "sum" value. So the values will not be the same, but they will nearly.
Another thing to point out is that the API does not return bytes/per second, it returns the bytes used by the interface in a peiod of time. what I can see in your result of the api is that period of time is 5 minutes.
so let's convert the data with that information:
646793.0 bytes in 5 minutes
converting to bytes per second (5 minutes = 300 seconds)
646793.0/300 = 2155.976 bytes/second
converting to bits
2155.976 * 8 = 17247.808
converting to kilo bits (note we are not using 1024 )
17247.808 / 1000 = 17.247 KB/s
As I told you the value is closer, but not the same due to the method used if you are looking the exact value you have to use the getSummaryData method. here an example in java Getting bandWidth data in SL
Regards
If I'm not wrong, it is in bytes per second.
Here I added an example for April's question.
Portal Bandwidth Graph
I got the datas by SoftLayer_Virtual_Guest:getBandwidthDataByDate.
getBandwidthDataByDate's output
It showed that 'counter': 646793.0, if the "unit" is bytes per sec, 646793.0Bps*8/1024 != 16.62Kbps

How does ActiveMQPrefetchPolicy work? What does queueBrowserPrefetch mean?

I'm trying to use ActiveMQPrefetchPolicy but cannot quite understand how to use it.
I'm using queue, there are 3 params that I can define for PrefetchPolicy:
queuePrefetch, queueBrowserPrefetch, inputStreamPrefetch
Actually I don't get the meaning of queueBrowserPrefetch and inputStreamPrefetch so I do not know how to use it.
I assume that you have seen the ActiveMQ page on prefetch limits.
queueBrowserPrefetch sets the maximum number of messages sent to a
ActiveMQQueueBrowser until acks are received.
inputStreamPrefetch sets the maximum number of messages sent
through a jms-stream until acks are received
Both queue-browser and jms-stream are specialized consumers. You can read more about each one of them but if you are not using them it won't matter what you assign to their prefetch limits.

AsyncSocket: getting merged two packets instead of separate two packets

I'm executing 4 startup commands and also expecting to receive 4 responses. The server is already implemented and another dev who is developing android, is able to receive those 4 separate responses, however, I'm getting 2 good responses (separate) and then 3rd and 4th responses come as one response. I'v placed NSLog of NSData result in completeCurrentRead, and it outputs me merged packet "0106000000000b0600000000" instead of separate packets "010600000000" and "0b0600000000". I'v also tested those 3rd and 4th commands separatedly (only one at a time) and everything is OK with the server, it sends them separately, however there occurs merge (with 3rd and 4th) if all four commands are executed in a line. Any ideas?
UPDATE: I think I'v traced to the problem roots. There's a call that reads packet data from a stream in doBytesAvailable method:
CFIndex result = [self readIntoBuffer:subBuffer maxLength:bytesToRead];
And in readIntoBuffer:maxLength, there's a call (length == 256) :
return CFReadStreamRead(theReadStream, (UInt8 *)buffer, length);
So, CFReadStreamRead returns incorrect length of packet - it return length of 12 (instead of 6), and also grabs merged data. Hm, what might causing CFReadStreamRead to read two packets into one, instead of reading them separately...
UPDATE2: I'm using onSocket:didReadData:withTag: delegate method and expecting to receive response data with the tag of request I performed. I have realized recently, streams are streams, not packets but how I can solve that? Server responses does not have terminating chars at start and end of response, just response size, that comes as 2 - 5 bytes. I can cut the first part of response (first packet) and ignore the second part but how AsyncSocket will make another callback with the second part of the response (second packet)? If I will cut only the first parts and ignore the second then IMHO the second "packet" will be lost...
How to cut the first part of response and tell AsyncSocket to make another callback with tag and the second part of response as separate callback?
UPDATE3: In onSocket:didReadData:withTag:, I manually cut merged response, handle the first part (first packet) and then at the end, throwing a call to onSocket:didReadData:withTag: again:
if (isMergedPacket) {
...
[self onSocket:sock didReadData:restPartOfTheResponse withTag:myCommandTag];
}
However, it looks like AsyncSocket itself pairs every request packet with its response packet (via AsyncReadPacket class) using tags. So, my manual cutting works, but AsyncSocket does not know that I already handled both packets, and it still tries to read the second packet. So, I'm getting sock:shouldTimeoutReadWithTag:... callback which is called when a read operation has reached its timeout without completing.
Found solution. It's not necessary to change and dig into AsyncSocket. You just need to define the length of each response - how much bytes are you interested in reading and getting your callback. More info you can on other post here