I'm looking for some help to try and run an e1.31 receiving process on the same box as the QLC+ application.
I am trying to integrate a custom USB device (DMX output) into a QLC+ installation. Options are to write a custom plugin, or to try and use an existing application that can receive E1.31 and talk to the USB device to create an E1.31 to DMX bridge. I am running QLC+ version 4.12.2 GIT atop of an UBUNTU 16.04 stock image, configuring the first Universe to output E1.31 as a MULTICAST target. On the same host that is running QLC+, I am trying to also run the multicast receiver, that would then convert the output to data sent to the USB device.
The problem:
If I run this application on a second device on the network, everything works fine. If I run this application on the same host as the QLC+ instance, the packets are never seen by the application. Executing tcpdump -i eth0 port 5568 sees the outgoing packets from QLC+ as expected.
I have tried updating the QAbstractSocket::MulticastLoopbackOption to 'true' in plugins/E1.31/e131controller.cpp, but still I am unable to receive the udp packets in my demo sniffer application.
Any pointers/assistance greatly appreciated..
LabRat
---
Sample code for the Multicast listener...
Code: Select all
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
#include <strings.h>
#include "sacn.h"
#include <unistd.h> // sleep/usleep
// Retrieve MAC address
#include <sys/ioctl.h>
#include <linux/if.h>
#define EXAMPLE_PORT 5568
#define EXAMPLE_GROUP "239.255.0.1"
void sacn_dump ( tSACN_PACKET *buf ) {
int i;
// ROOT
printf("ROOT\n");
printf("\tpreamble_size:\t0x%4.4x\n",ntohs(buf->preamble_size));
printf("\tpostable_size:\t0x%4.4x\n",ntohs(buf->postamble_size));
printf("\tacn_id:\t\t%s\n",buf->acn_id);
printf("\tflag_n_length:\t0x%2.2x [%d]\n",ntohs(buf->root_flag_n_length), (uint16_t)(ntohs(buf->root_flag_n_length))&0x0FFF);
printf("\troot_vector:\t%8.8x\n",ntohs(buf->root_vector));
// pulling the MAC address to populate the CID field
printf("\tcid:\t\t");
for (i=0;i<16;i++) { printf("%2.2x",buf->cid[i]); }
printf("\n");
// FRAME
printf("FRAME\n");
printf("\tflag_n_length:\t0x%2.2x [%d]\n",ntohs(buf->frame_flag_n_length), ntohs(buf->frame_flag_n_length) & 0x0FFF);
printf("\tframe_vector:\t0x%8.8x\n",ntohl(buf->frame_vector));
printf("\tsource_name:\t%s\n",buf->source_name);
printf("\tpriority:\t0x%2.2x\n",buf->priority);
printf("\treserved:\t0x%4.4x\n",buf->reserved);
printf("\tsequence:\t0x%2.2x\n",buf->sequence);
printf("\toptions:\t0x%2.2x\n",buf->options);
printf("\tuniverse:\t0x%2.2x\n",ntohs(buf->universe));
// DMP
printf("DMP\n");
printf("\tflag_n_length:\t0x%2.2x [%d]\n",ntohs(buf->dmp_flag_n_length), ntohs(buf->dmp_flag_n_length)& 0x0FFF);
printf("\tdmp_vector:\t\t0x%2.2x\n",buf->dmp_vector);
printf("\taddress_type:\t\t0x%2.2x\n",buf->address_type);
printf("\tfirst_property_addr:\t0x%4.4x\n",ntohs(buf->first_property_addr));
printf("\taddress_increment:\t0x%4.4x\n",ntohs(buf->address_increment));
printf("\tproperty_value_count:\t0x%4.4x\n",ntohs(buf->property_value_count));
printf("\tproperty_start:\t\t0x%2.2x",buf->property_start);
printf("\tproperty_values\t\t");
{
for (i=0; i<9; i++) {
printf("%2.2x ",buf->property_values[i]);
}
printf("\n");
}
if (buf->property_start != 00) exit(0);
}
int main(int argc)
{
struct sockaddr_in addr;
int addrlen, sock, cnt;
struct ip_mreq mreq;
char message[50];
tSACN_PACKET sacn_buffer;
/* set up socket */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
bzero((char *)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(EXAMPLE_PORT);
addrlen = sizeof(addr);
{ // Allow for re-use
int trueValue = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &trueValue, sizeof(trueValue));
}
/* receive */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
perror("setsockopt mreq");
exit(1);
}
while (1) {
cnt = recvfrom(sock, &sacn_buffer, sizeof(sacn_buffer), 0,
(struct sockaddr *) &addr, &addrlen);
if (cnt < 0) {
perror("recvfrom");
exit(1);
} else if (cnt == 0) {
break;
}
printf("%s: %d bytes\n", inet_ntoa(addr.sin_addr),cnt);
sacn_dump(&sacn_buffer);
}
}