freeDiameter based server cannot read received buffer - c++

I have tried to set up a server with a specific IP address and Port number by freeDiameter libraries. In other side, there is a client that sends a string message via freeDiameter libraries successfully; I checked it out in Wireshark.
So, here is the problem; when I start listening from the server side, it has no problem until a client sends a connection request; if you look at the below code, "fd_cnx_serv_accept(listener)" is listening to a socket named "listener" which is bind to a specific IP address and Port number.
uint8_t * rcv_buf;
size_t rcv_size;
struct cnxctx * listener_side = NULL;
int ret;
listener_side = fd_cnx_serv_accept(listener);
ret = fd_cnx_start_clear(listener_side, 0);
if(ret != 0){
std::cout<<side<<" is unable to accept connections."<<std::endl;
return -1;
}
ret = fd_cnx_receive(listener_side, NULL, &rcv_buf, &rcv_size);
if(ret == 0){
std::cout<<"Message received."<<std::endl;
listener_side = NULL;
free(rcv_buf);
}
The program works fine until it gets a client request; when "fd_cnx_serv_accept" accept the client side, the program tries to receive the message by "fd_cnx_receive"; but the program stops and shows the error "Segmentation fault (core dumped)". Then, I test the program by gdb and it shows that it is something wrong with the line 309 of "hook.c". Here is the image of the error which is shown by gdb.
Error Screenshot
transcript
multi-thre Thread 0x7fffff72a77 In: fd_hook_call
[New Thread 0x7fffff72a7700 (LWP 1612914)
Thread 2 "server" received signal SIGSEGEV, Segmentation Fault
[Switching to Thread 0x7fffff72a7700 (LWP 1612914)
--Type <RET> for more, q to quit, c to continue without paging --c
0x00007ffff7f2cefc in fd_hook_call (type=HOOD_DATA_RECEIVED, msg=0x0, peer=0x0, other=0x7ffff72a6be0, pmdl=0x7ffff0000ba8 at /root/projects/start_cnx_free/third-party/libfdcore/hooks.c:309
It is good to mention that I am trying to write a c++ program.
How can I solve this problem ?

I solved this problem myself. I forgot to use fd_hooks_init() at the begining of my program to initialize necessary libraries and objects.
Here is the modified code:
/* Initialize the library -- must come first since it initializes the debug facility */
int ret = fd_libproto_init();
if (ret != 0) {
fprintf(stderr, "Unable to initialize libfdproto: %s\n", strerror(ret));
return ret;
}
ret = fd_hooks_init();
if(ret != 0){
std::cout<<"Unable to initialize the hooks."<<std::endl;
return ret;
}
/* Initialize the config with default values */
memset(&g_conf, 0, sizeof(struct fd_config));
fd_g_config = &g_conf;
ret = fd_conf_init();
if (ret != 0) {
printf("Unable to initialize the config with default values.");
return ret;
}
/* Add definitions of the base protocol */
ret = fd_dict_base_protocol(fd_g_config->cnf_dict);
if (ret != 0) {
printf("Unable to add definitions of the base protocol.");
return ret;
}

Related

poll() method not working in Linux but working in Mac

I am using C++ code snippet for port forwarding. The requirement is to do the hand shake between two ports. It should be two way communication. That is to forward what ever iscoming on the source port to destination port. And then to forward the response of the destination port to the source port.
This piece of code is working as expected on my mac system. But when I am running this code on Linux system I am facing one issue.
Issue:
The C++ code that I am using is having 3 parts:
establish_connection_to_source();
open_connection_to_destination();
processconnetion();
On Linux: establish_connection_to_source(); and open_connection_to_destination(); is working perfectly fine. But processconnetion(); is havng one issue.
Following is the process connection method:
void processconnetion()
{
buffer *todest = new buffer(socket_list[e_source].fd,socket_list[e_dest].fd);
buffer *tosrc = new buffer(socket_list[e_dest].fd,socket_list[e_source].fd);
if (todest == NULL || tosrc == NULL){
fprintf(stderr,"out of mememory\n");
exit(-1);
}
unsigned int loopcnt;
profilecommuncation srcprofile(COMM_BUFSIZE);
profilecommuncation destprofile(COMM_BUFSIZE);
while (true) {
int withevent = poll(socket_list, 2, -1);
loopcnt++;
fprintf(stderr,"loopcnt %d socketswith events = %d source:0x%x dest:0x%x\n", loopcnt, withevent, socket_list[e_source].revents, socket_list[e_dest].revents);
if ((socket_list[e_source].revents | socket_list[e_dest].revents) & (POLLHUP | POLLERR)) {
// one of the connections has a problem or has Hungup
fprintf(stderr,"socket_list[e_source].revents= 0x%X\n", socket_list[e_source].revents);
fprintf(stderr,"socket_list[e_dest].revents= 0x%X\n", socket_list[e_dest].revents);
fprintf(stderr,"POLLHUP= 0x%X\n", POLLHUP);
fprintf(stderr,"POLLERR= 0x%X\n", POLLERR);
int result;
socklen_t result_len = sizeof(result);
getsockopt(socket_list[e_dest].fd, SOL_SOCKET, SO_ERROR, &result, &result_len);
fprintf(stderr, "result = %d\n", result);
fprintf(stderr,"exiting as one connection had an issue\n");
break;
}
if (socket_list[e_source].revents & POLLIN) {
srcprofile.increment_size(todest->copydata());
}
if (socket_list[e_dest].revents & POLLIN) {
destprofile.increment_size(tosrc->copydata());
}
}
delete todest;
delete tosrc;
close(socket_list[e_source].fd);
close(socket_list[e_dest].fd);
srcprofile.dumpseensizes("source");
destprofile.dumpseensizes("destination");
}
Here it is giving error - exiting as one connection had an issue that means that if ((socket_list[e_source].revents | socket_list[e_dest].revents) & (POLLHUP | POLLERR)) is returning true. The issue is with the destination port and not in case of source.
Note:
Variales used in the processconnetion(); method:
socket_list is a structure of type pollfd. Following is the description:
struct pollfd {
int fd;
short events;
short revents;
};
pollfd socket_list[3];
#define e_source 0
#define e_dest 1
#define e_listen 2
Following is the output at the time for exit:
connecting to destination: destination IP / 32001.
connected...
loopcnt 1 socketswith events = 1 source:0x0 dest:0x10
socket_list[e_source].revents= 0x0
socket_list[e_dest].revents= 0x10
POLLHUP= 0x10
POLLERR= 0x8
result = 0
exiting as one connection had an issue
int withevent = poll(socket_list, 2, -1); here the withevent value returned is 1
Socket List Initialisation:
guard( (socket_list[e_listen].fd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )), "Failed to create socket listen, error: %s\n", "created listen socket");
void guard(int n, char *msg, char *success)
{
if (n < 0) {
fprintf(stderr, msg, strerror(errno) );
exit(-1);
}
fprintf(stderr,"n = %d %s\n",n, success);
}
I am not able to figure out the issue as it is working fine in mac. Any leads why this behaviour in Linux is highly appreciated. Thanks in advance.

QSerialPort is in use before application starts

I am developing an application for Apalis iMX6 with Qt C++ in Linux and I've added this application into the startup by means of profile.d
this code must set ttymxc1 into RS485 mode like below:
int enableRS485(){
struct serial_rs485 rs485conf;
int fd = open ("/dev/ttymxc1", O_RDWR);
if (fd < 0) {
printf("Error: Can't open: /dev/ttymxc1 %d\n",fd);
return fd;
}
rs485conf.flags |= SER_RS485_ENABLED;
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
rs485conf.flags |= SER_RS485_RX_DURING_TX;
err = ioctl (fd, TIOCSRS485, &rs485conf);
if (err < 0) {
printf("Error: TIOCSRS485 ioctl not supported.\n");
return err;
}
err = close (fd);
if (err < 0) {
printf("Error: Can't close: /dev/ttyLP1 %d\n",err);
return err;
}
return 0;
}
this function is working as well and has no problem. but when I try to open the serial port sometimes during startup application couldn't get this serial port and QSerialPortInfo shows me ttymxc1 is in use. my initiation of the serial port is like below:
void SerialClass::initSerial()
{
m_serialPort = new QSerialPort();
enableRS485();
sleep(1);
m_serialPort->setPortName("/dev/ttymxc1");
m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
m_serialPort->setBaudRate(9600);
m_serialPort->setRequestToSend(false);
bool res = m_serialPort->open(QIODevice::ReadWrite);
}
"QSerialPort::errorOccured" signal will emit with value "PermissionError"
but mysteriously "ls -l /proc/[0-9]/fd/ |grep /dev/ttymxc1" shows me ttymxc1 is in used by my application.
there is no application that works with serial port and my application is just for one time run.
Is there any idea?
Thanks
You need to call close() on m_serialPort when you close your application. Otherwise your serial port will keep in-use state.
I've found a new remedy, so I want to share it here.
in SerialClass constructor I've added initSerial(), in this way application at the beginning of starting, will open the ttymxc1.
There is no more problem with such a solution.
I don't have such an issue with Raspberry Pi (Raspberry Pi3 + Qt 5.6 + Raspbian). But Toradex Apalis is in another way.
Would you please tell me why?

Simplest IPC from one Linux app to another in C++ on raspberry pi

I need the simplest most reliable IPC method from one C++ app running on the RPi to another app.
All I'm trying to do is send a string message of 40 characters from one app to another
The first app is running as a service on boot, the other app is started at a later time and is frequently exited and restarted for debugging
The frequent debugging for the second app is whats causing problems with the IPCs I've tried so far
I've tried about 3 different methods and here is where they failed:
File FIFO, the problem is one program hangs while the other program is writing to the file
Shared memory: cannot initialize on one thread and read from another thread. Also frequent exiting while debugging causing GDB crashes with the following GDB command is taking too long to complete -stack-list-frames --thread 1
UDP socket with localhost - same issue as above, plus improper exits block the socket, forcing me to reboot device
Non blocking pipe - not getting any messages on the receiving process
What else can I try? I dont want to get the DBus library, seems too complex for this application.
Any simple server and client code or a link to it would be helpful
Here is my non-blockign pipe code, that doesnt work for me,
I assume its because I dont have a reference to the pipe from one app to the other
Code sourced from here: https://www.geeksforgeeks.org/non-blocking-io-with-pipes-in-c/
char* msg1 = "hello";
char* msg2 = "bye !!";
int p[2], i;
bool InitClient()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Read
int nread;
char buf[MSGSIZE];
// write link
close(p[1]);
while (1) {
// read call if return -1 then pipe is
// empty because of fcntl
nread = read(p[0], buf, MSGSIZE);
switch (nread) {
case -1:
// case -1 means pipe is empty and errono
// set EAGAIN
if(errno == EAGAIN) {
printf("(pipe empty)\n");
sleep(1);
break;
}
default:
// text read
// by default return no. of bytes
// which read call read at that time
printf("MSG = % s\n", buf);
}
}
return true;
}
bool InitServer()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Write
// read link
close(p[0]);
// write 3 times "hello" in 3 second interval
for(i = 0 ; i < 3000000000 ; i++) {
write(p[0], msg1, MSGSIZE);
sleep(3);
}
// write "bye" one times
write(p[0], msg2, MSGSIZE);
return true;
}
Please consider ZeroMQ
https://zeromq.org/
It is lightweight and has wrapper for all major programming languages.

boost shared pointer custom deleter example

I'm using the libmodbus library. i need to pass instances of the modbus_t pointer between threads. I am having difficulty with just raw pointers and I think i can solve the problem with using boost_shared_ptr with custom deleter.
i don't get any compiler issues but when i run the program it crashes.
i was hoping if someone can give me a usage example of boost shared pointer with custom deleter.
the program crashes at line where m_mb.reset() is called the first time in the OpenModBusConnection() function.
m_mb = boost::shared_ptr<modbus_t>( modbus_new_rtu(m_heatercomport.c_str(),9600,'N',8,1), freemodbus);
void freemodbus(modbus_t *mb)
{
if(mb != NULL)
{
modbus_close(mb);
modbus_free(mb);
}
}
void OpenModBusConnection()
{
if(m_mb.get() != NULL)
{
wxString msg("Closing port \"");
msg.append(m_heatercomport);
msg.append("\" modbus port ");
wxLogMessage(msg);
readoutput->AppendText("Modbus Connection Closed\n");
m_mb.reset();
}
// open modbus connection
m_mb.reset();
modbus_set_slave(m_mb.get(),1);
if(modbus_connect(m_mb.get()) == -1)
{
wxString msg("Failed to open port \"");
msg.append(m_heatercomport);
msg.append("\" modbus port ");
wxLogMessage(msg);
readoutput->AppendText("Modbus Connection Failed\n");
return false;
}
else
{
wxString msg("Opening port \"");
msg.append(m_heatercomport);
msg.append("\" modbus port ");
wxLogMessage(msg);
readoutput->AppendText("Modbus Connection Established\n");
return true;
}
}
error message i get is
First-chance exception at 0x7717bb47 in test.exe: 0xC0000008: An invalid handle was specified.
m_mb.reset();
modbus_set_slave(m_mb.get(),1);
if(modbus_connect(m_mb.get()) == -1)
This is effectively the same as
m_mb.reset();
modbus_set_slave(nullptr,1);
if(modbus_connect(nullptr) == -1)
If you want to free and reset the m_mb back to a fresh modbus handle you need to do
m_mb = boost::shared_ptr<modbus_t>( modbus_new_rtu(m_heatercomport.c_str(),9600,'N',8,1), freemodbus);
again expliticly.

why shutdown on udp socket blocks?

I'm writing a UDP server application for windows desktop/server.
My code uses the WSA API suggested by windows the following way (This is my simplified receivePacket method):
struct Packet
{
unsigned int size;
char buffer[MAX_SIZE(1024)];
}
bool receivePacket(Packet packet)
{
WSABUFFER wsa_buffer[2];
wsa_buffer[0].buf = &packet.size;
wsa_buffer[0].len = sizeof(packet.size);
wsa_buffer[1].buf = packet.buffer;
wsa_buffer[1].len = MAX_SIZE;
bool retval = false;
int flags = 0;
int recv_bytes = 0;
inet_addr client_addr;
int client_addr_len = sizeof(client_addr);
if(WSARecvFrom(_socket, wsa_buffer, sizeof(wsa_buffer)/sizeof(wsa_buffer[0]), &bytes_recv, &flags, (sockaddr *)&client_addr, &client_addr_len, NULL, NULL) == 0)
{
//Packet received successfully
}
else
{
//Report
}
}
Now, when I'm trying to close my application gracefully, not network-wise, but rather application-wise (going through all the d'tors and stuff), i'm trying to unblock this call.
To do this, I call the shutdown(_socket, SD_BOTH) method. Unfortunately, the call to shutdown itself BLOCKS!
After reading every possible page in the MSDN, I didn't find any reference to why this happens, other ways of attacking the problem or any way out.
Another thing I checked was using the SO_RCVTIMEO. Surprisingly, this sockopt didn't work as expected as well.
Is there any problem with my code/approach?
Did you run shutdown on duplicated handle? Shutdown on the same handle will wait any active operation on this handle to complete.