lwip netconn_recv netbuf overwritten from browser broadcast message - tcp

I have a project on a STM32H7 board with lwip 2.1.2 and freeRTOS V10.3.1 with a custom tcp server application running. So far I assumed that, when using netconn_recv(), the netbuf data are valid until the next netconn_recv() command. But sometimes it happens that an incoming BROWSER protocol broadcast message overwrites my rxbuffer and my application ends up with an error message, due to the corrupt data in the rxbuffer.
The error dos not occur, when I have wireshark running on the PC. But I can see artifacts of the broadcast message in the rx buffer when inspecting with the debugger.
My server loop is quite simple
while (running) {
errRet = netconn_recv(current_conn, &rxbuf);
if (errRet != ERR_OK) {
break;
}
do {
netbuf_data(rxbuf, (void*) &rxdata, &rxlen);
if (netconn_receive (current_conn, rxdata, rxlen) != ERR_OK)
break;
} while (netbuf_next(rxbuf) >= 0);
}
I enabled the stack and heap overflow hook function, but there seems all ok.

I found it out. I forgot to mention that my project is based on this STMCubeH7 repository application. So far I've been working with version 1.9.1, but now there's a newer version, v1.10.0. I did an update and it seems to work now.
By the way, I found the repository log message: "Full rework of Ethernet HAL driver".

Related

Proper way of notifying the application that DPDK received messages

currently, I'am using dpdk by sending and receiving the packets in to the rte-rings. I'am having difficulty of finding the proper way of to notify the application that the DPDK received incoming messages.
In order to check the whether the rte_ring has received the data or not, I run a busy loop on the rte_ring.
here is the example below
while (1) {
if (rte_ring_dequeue(rx_ring, &_msg) < 0) {
usleep(5);
} else {
recv_msg = (char *) _msg;
if (chara_debug) printf("[%d] Server merge data::[%.24s...]__length::[%ld]\n", batched_packets, recv_msg, strlen(recv_msg));
collect_packets++;
if (collect_packets > MERGE_PACKETS) break;
}
}
However, my fellow developers say that this is not a efficient way nor the proper way of checking received messages. Busy polling should be only done in the DPDK API and not in the application.
Is there a way for DPDK to send a signal to the application so that the application can only check the rte_ring only when there is a received message?
Well, direct answer is to use DPDK event library: http://doc.dpdk.org/guides/prog_guide/eventdev.html
But it is not that smooth. Unless you have a hardware which directly supports the event model, you still need at least one RX core to poll (i.e. do the busy loop) as shown on this picture:
http://doc.dpdk.org/guides/prog_guide/eventdev.html#api-walk-through

Qt: Detect a QTcpSocket disconnection in a console app when the user closes it

My question title should be enough. I already tried (without success):
Using a C-style destructor in a function: __attribute__((destructor)):
void sendToServerAtExit() __attribute__((destructor)) {
mySocket->write("$%BYE_CODE%$");
}
The application destructor is called, but the socket is already disconnected and I can't write to the server.
Using the standard C function atexit(), but the TCP connection is already lost so I can't send anything to the server.
atexit(sendToServerAtExit); // is the same function of point 1
The solution I found is check every second if all connected sockets are still connected, but I don't want to do so inefficient thing. It's only a temporary solution. Also, I want that others apps (even web ones) can join the chat room of my console app, and I don't want to request data every second.
What should I do?
Handle the below signal (QTcpSocket is inherited from QAbstractSocket)
void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
Inside the slot called, check if socketState is QAbstractSocket::ClosingState.
QAbstractSocket::ClosingState indicates the socket is about to close.
http://doc.qt.io/qt-5/qabstractsocket.html#SocketState-enum
You can connect a slot to the disconnect signal.
connect(m_socket, &QTcpSocket::disconnected, this, &Class::clientDisconnected);
Check the documentation.
You can also know which user has been disconnected using a slot like this:
void Class::clientDisconnected
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());
if(client)
{
// Do something
client->deleteLater();
}
else
{
// Handle error
}
}
This method is usefull if you have a connections pool. You can use it as well if you have a single connection, but do not forget nullptr after client->deleteLater().
If I understand you question correctly, you want to send data over TCP to notify the remote computer that you are closing the socket.
Technically this can be done in Qt by listenning to the QIODevice::aboutToClose() or QAbstractSocket::stateChanged() signals.
However, if you graciously exit your program and close the QTcpSocket by sending a FIN packet to the remote computer. This means that on the remote computer,
the running program will be notified that the TCP connection finished. For instance, if the remote program is also using QTcpSocket, the QAbstractSocket::disconnected()
signal will be emitted.
The real issues arise when one of the program does not graciously exit (crash, hardware issue, cable unplugged, etc.). In this case, the TCP FIN packet will
not be sent and the remote computer will never get notified that the other side of the TCP connection is disconnected. The TCP connection will just time-out after a few minutes.
However, in this case you cannot send your final piece of data to the server either.
In the end the only solution is to send a "I am here" packet every now and then. Even though you claim it is ineficient, it is a widely used technique and it also has the advantage that it works.

Unable to send data using QSerialPort

I am trying to write a QT application that will be able to communicate with my embedded system using serial port. For now I am testing the config with Null Modem emulator as I don't have the embedded system ready yet.
The emulator works fine as I have tested it in other software like Terraterm, RealTerm or Putty. My problem is that my example code doesn't work - it doesn't send the string to another com port.
This is my code:
void CSettingsDialog::on_pbSerialCheck_clicked()
{
QSerialPort serial;
serial.setPortName(ui->cbSerialPort->currentText());
if (!serial.open(QIODevice::ReadWrite))
{
QMessageBox::warning(this, tr("Serial port"),
tr("Serial port %1 is busy!")
.arg(ui->cbSerialPort->currentText()));
}
else
{
serial.setBaudRate(QSerialPort::Baud115200);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.write("TEST\n");
serial.close();
}
}
I am certain that I have everything set correctly looking at the QT examples.
I am certain that I have everything set correctly looking at the QT
examples. I would aprichiate all help!
When reading flush documentation, it seems that calling "write" buffers, with writes possible finishing asynchronously.
Also see "Certain subclasses of...are asynchronous", with comments on waitForBytesWritten

DDP between two servers doesn't reconnect

I have two meteor applications connected via DDP on different servers and server A send data to server B. This is the way they work.
Server A
Items = new Meteor.Collection('items');
Items.insert({name: 'item 1'});
if (Meteor.isServer) {
Meteor.publish('items', function() {
return Items.find();
});
}
Server B
var remote = DDP.connect('http://server-a/');
Items = new Meteor.Collection('items', remote);
remote.subscribe('items');
Items.find().observe({
added: function(item) {
console.log(item);
}
});
Every time I call Items.insert(something) on server A, on Server B I got a log on the console with the object I saved on Server A. But if Server B lost Internet connection, the data inserted on Server A doesn't appear anymore on Server B when it reconnect to Internet.
Server B is connected to Internet through a router. This problem only happen when I disconnect and reconnect the router, not when I disconnect and reconnect the server from the router. Both servers are on different networks and connect via Internet.
I created a timer on Server B that call remote.status() but always get { status: 'connected', connected: true, retryCount: 0 } when connected or disconnected from Internet.
Update: steps to reproduce
I created a project on github with the testing code https://github.com/camilosw/ddp-servers-test. Server A is installed on http://ddpserverstest-9592.onmodulus.net/
My computer is connected to Internet through a wireless cable modem.
Run mrt on server-b folder
Go to http://ddpserverstest-9592.onmodulus.net/ and click the link Insert (you can click delete to remove all previous inserts). You must see a message on your local console with the added item.
Turn off the wireless on the computer and click the insert link again. (You will need to click on another computer with Internet access, I used an smartphone to click the link)
Turn on the wireless on the computer. You must see a message on your local console with the second item.
Now, turn off the cable modem and click the insert link again.
Turn on the cable modem. This time, the new item doesn't appear on the console.
I also did it with an android smartphone using the option to share Internet to my computer via wireless. First I turned off and on the wireless on my computer and worked right. Then I turned off and on the Internet connection on the smartphone and I got the same problem.
Update 2
I have two wireless router on my office. I found that the same problem happen if I move between routers.
Emily Stark, from the Meteor Team, confirmed that this is due to a missing feature on the current implementation (version 0.7.0.1 at the moment I write this answer). Their answer is here https://github.com/meteor/meteor/issues/1543. Below is their answer and a workaround she suggest:
The server-to-server connection is not reconnecting because Meteor currently doesn't do any heartbeating on server-to-server DDP connections. Just as in any other TCP connection, once you switch to a different router, no data can be sent or received on the connection, but the client will not notice unless it attempts to send some data and times out. This differs from browser-to-server DDP connections, which run over SockJS. SockJS does its own heartbeating that we can use to detect dead connections.
To see this in action, here is some code that I added to server-b in your example:
var heartbeatOutstanding = false;
Meteor.setInterval(function () {
if (! heartbeatOutstanding) {
console.log("Sending heartbeat");
remote.call("heartbeat", function () {
console.log("Heartbeat returned");
heartbeatOutstanding = false;
});
heartbeatOutstanding = true;
}
}, 3000);
remote.onReconnect = function () {
console.log("RECONNECTING REMOTE");
};
With this code added in there, server-b will reconnect after a long enough time goes by without an ACK from server-a for the TCP segments that are delivering the heartbeat method call. On my machine, this is just a couple minutes, and I get an ETIMEDOUT followed by a reconnect.
I've opened a separate task for us to think about implementing heartbeating on server-to-server DDP connections during our next bug week. In the meantime, you can always implement heartbeating in your application to ensure that a DDP reconnection happens if the client can no longer talk to the server.
I think you are not passing DDP connection object to the Collection correctly, try:
var remote = DDP.connect('http://server-a/');
Items = new Meteor.Collection('items', { connection: remote });
It might be useful for debugging to try all these connection games from the browser console first, since Meteor provides the same API of connection/collections on the client (except for the control flow). Just open any Meteor application and try this lines from the console.
I revised a sample of communication between two ddp server, based on camilosw's code.
Server A as Cloud Data Center. Server B as Data Source, if some data changed, should be send to Server A.
You can find the code from https://github.com/iascchen/ddp-servers-test

Re-opening Closed Serial Port

i have an application that detects a USB 3G Dongle that will be used for sending SMS. My application queries the Dongle via AT Commands to determine if it is the RIGHT dongle, this means that that certain dongle can only be used in my application (even if the Dongle is of the same model). Sending and receiving is fine, no problems or whatsoever. If the 3G Dongle is removed from the USB port, the system detects this and executes the proper procedures.
Here's my problem. When the 3G Dongle is re-inserted, say on the same port (COM5), my application detects this and executes some AT Command to determine that the re-inserted dongle is the RIGHT dongle. But an error occurs stating:
THE RESOURCE IS IN USE
The application must be terminated or closed to be able to use the same port (say COM5). Then I encountered an application, almost with the same function, but is able to use the dongle when re-inserted.
BTW, my dongle is ZTE MF190, and the application I saw is from Huawei. I am using C#. Is there any work around on this? or better, is there a better logic on this? say using a service, etc..
EDIT:
every query done to the Dongle is done in a separate thread so as to be able to use my application while sending and receiving..
Thanks!
I too had a similar issue with the windows serial port component. There appears to be bugs in the C# code.
Long story short, I managed to get around this by closing the port in a background thread.
Here is my code, note that you may need to modify to fit your application:
private bool ClosePort()
{
_Closing = true;
_SerialPort.DiscardInBuffer();
_SerialPort.DiscardOutBuffer();
if (!_SerialPort.IsOpen) return true;
//We run this in a new thread to avoid issue when opening and closing
//The .NET serial port sucks apparently - and has issues such as hanging and random exceptions
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoClosePort));
t.Start();
//here we wait until is **SHOULD*** be closed - note the better way is to fire an internal event when its finished
//We may need to tinker with this wait time
System.Threading.Thread.Sleep(500);
return _SerialPort.IsOpen;
}
private void DoClosePort()
{
try
{
//System.Threading.Thread.Sleep(500);
_SerialPort.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error closing " + _SerialPort.PortName + ". Error Message: " + ex.Message + "\r\n");
}
}
Note that if you try sending/receiving while you are closing, check the _Closing class variable before you attempt the send.
Hope this helps anyone.

Resources