FORUM CTRLX AUTOMATION
ctrlX World Partner Apps for ctrlX AUTOMATION
03-01-2024 05:39 PM - edited 03-01-2024 05:43 PM
Hello Everyone,
I'm reaching out to seek assistance with an issue I'm facing regarding socket binding in a snap application, along with an AppArmor denial error.
Problem Description:
I've developed a C++ program that acts as a Unix socket server, serving as a middleware between the licensing manager API and another application. The program creates a directory and listens for incoming connections via a Unix domain socket. When I run the C++ executable locally on my Ubuntu 20.04 development machine, the socket is bound successfully, and the server listens for incoming connections without any issues.
However, after building a snap of the program and installing it on my CtrlX Core Virtual device (version 1.20.12), I encounter the following errors (Diagnostics ->Logbook):
Additional Information:
Build Environment: Ubuntu 20.04
Snap Base: core20
CtrlX Core Virtual Version: 1.20.12
CtrlX Works Version: 1.20.5
Here is my snapcraft.yaml file:
name: licensing
version: "0.0.1"
grade: stable
base: core20
confinement: strict
apps:
licensing:
command: check-license
plugs:
- network
- network-bind
- content
- system-files
daemon: simple
passthrough:
restart-condition: on-failure
restart-delay: 10s
parts:
licensing:
plugin: dump
source: ./generated/build
stage-packages:
- libasn1-8-heimdal
- libbrotli1
- libcurl4
- libgssapi3-heimdal
- libhcrypto4-heimdal
- libheimbase1-heimdal
- libheimntlm0-heimdal
- libhx509-5-heimdal
- libkrb5-26-heimdal
- libldap-2.4-2
- libnghttp2-14
- libpsl5
- libroken18-heimdal
- librtmp1
- libsasl2-2
- libssh-4
- libwind0-heimdal
And also my main.cpp:
#include <iostream>
#include <fstream>
#include <filesystem>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "helper/helper.h"
#include "third_party/nlohmann/json.hpp"
#include "licensing-service/licenseClient.h"
#include "constants.h"
// Use the nlohmann namespace for JSON parsing
using json = nlohmann::json;
// Use the std namespace for standard C++ functions
using namespace std;
int main()
{
Helper installer; // Create an instance of the class that contains helper functions for the installer
LicenseClient licenseClient; // Create an instance of the class that contains functions to access the License Manager API
const string snapCommonPath = installer.getEnvVar("SNAP_COMMON");
string licensingSocketPath = snapCommonPath + "/sockets";
const char* socket_path = (licensingSocketPath + "/licensing.sock").c_str();
const int nIncomingConnections = 5;
const int backlog = 5; // Maximum number of pending connections in the queue
bool doDirectoriesExcist = filesystem::exists(licensingSocketPath);
if (!doDirectoriesExcist)
{
// Create the directories
filesystem::create_directories(licensingSocketPath);
cout << "Directories created successfully" << endl;
}
// Create socket
//create server side
int s = 0;
int s2 = 0;
struct sockaddr_un local, remote;
int len = 0;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if( -1 == s )
{
printf("Error on socket() call \n");
return 1;
}
local.sun_family = AF_UNIX;
strcpy( local.sun_path, socket_path );
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if( bind(s, (struct sockaddr*)&local, len) != 0)
{
printf("Error on binding socket \n");
return 1;
}
if( listen(s, nIncomingConnections) != 0 )
{
printf("Error on listen call \n");
}
bool bWaiting = true;
while (bWaiting)
{
unsigned int sock_len = 0;
printf("Waiting for connection.... \n");
if( (s2 = accept(s, (struct sockaddr*)&remote, &sock_len)) == -1 )
{
printf("Error on accept() call \n");
return 1;
}
printf("Server connected \n");
int data_recv = 0;
char recv_buf[100];
char send_buf[200];
do{
memset(recv_buf, 0, 100*sizeof(char));
memset(send_buf, 0, 200*sizeof(char));
data_recv = recv(s2, recv_buf, 100, 0);
if(data_recv > 0)
{
printf("Data received: %d : %s \n", data_recv, recv_buf);
strcpy(send_buf, "Got message: ");
strcat(send_buf, recv_buf);
if(strstr(recv_buf, "quit")!=0)
{
printf("Exit command received -> quitting \n");
bWaiting = false;
break;
}
if( send(s2, send_buf, strlen(send_buf)*sizeof(char), 0) == -1 )
{
printf("Error on send() call \n");
}
}
else
{
printf("Error on recv() call \n");
}
}while(data_recv > 0);
close(s2);
}
return 0;
}
Your assistance and insights on this matter would be greatly appreciated. Please let me know if you require any further information or if there are any specific details I should provide.
Thank you in advance!
Solved! Go to Solution.
03-04-2024 08:01 AM
03-06-2024 10:04 AM
Hello @MauroRiboniMX ,
Thank you all for your insights regarding the issue.
After further investigation and experimentation, I tried installing the snap as devmode in Ubuntu 20.04 and discovered that indeed there is an issue with the socket creation. It seems that certain permissions or configurations are missing within the snap environment, causing these problems to occur.
In light of these difficulties and to avoid further complications with sockets, I have decided to change my approach for Inter-Process Communication (IPC). Instead of utilizing sockets, I will be transitioning to using shared memory.
Shared memory offers a robust and efficient means of communication between processes, and it circumvents some of the challenges encountered with socket permissions and configurations within the snap environment.
Once again, I appreciate all the support!
P.S. I will be closing the ticket now.