kopia lustrzana https://github.com/Hamlib/Hamlib
rodzic
1d96a84b44
commit
7835329e32
339
src/multicast.c
339
src/multicast.c
|
@ -327,198 +327,191 @@ void *multicast_thread(void *vrig)
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static char *GetWinsockLastError(char *errorBuffer, DWORD errorBufferSize)
|
static char *GetWinsockLastError(char *errorBuffer, DWORD errorBufferSize)
|
||||||
{
|
{
|
||||||
void GetWinsockErrorString(char *errorBuffer, DWORD errorBufferSize)
|
int errorCode = WSAGetLastError();
|
||||||
{
|
|
||||||
int errorCode = WSAGetLastError();
|
|
||||||
DWORD charsWritten;
|
|
||||||
|
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
NULL,
|
NULL,
|
||||||
errorCode,
|
errorCode,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
errorBuffer,
|
errorBuffer,
|
||||||
errorBufferSize,
|
errorBufferSize,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
return errorBuffer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int multicast_init(RIG *rig, char *addr, int port)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSADATA wsaData;
|
||||||
|
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||||
|
{
|
||||||
|
char errorMessage[1024];
|
||||||
|
fprintf(stderr, "WSAStartup failed: %s\n", GetWinsockLastError(errorMessage,
|
||||||
|
sizeof(errorMessage)));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int multicast_init(RIG * rig, char *addr, int port)
|
if (rig->state.multicast == NULL)
|
||||||
|
{
|
||||||
|
rig->state.multicast = calloc(1, sizeof(struct multicast_s));
|
||||||
|
}
|
||||||
|
else if (rig->state.multicast->multicast_running) { return RIG_OK; } // we only need one port
|
||||||
|
|
||||||
|
//rig->state.multicast->mreq = {0};
|
||||||
|
|
||||||
|
if (addr == NULL) { addr = RIG_MULTICAST_ADDR; }
|
||||||
|
|
||||||
|
if (port == 0) { port = RIG_MULTICAST_PORT; }
|
||||||
|
|
||||||
|
// Create a UDP socket
|
||||||
|
rig->state.multicast->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
|
||||||
|
if (rig->state.multicast->sock < 0)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA wsaData;
|
int err = WSAGetLastError();
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: socket: WSAGetLastError=%d\n", __func__, err);
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
|
||||||
{
|
|
||||||
char errorMessage[1024];
|
|
||||||
fprintf(stderr, "WSAStartup failed: %s\n", GetWinsockLastError(errorMessage,
|
|
||||||
sizeof(errorMessage)));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (rig->state.multicast == NULL)
|
|
||||||
{
|
|
||||||
rig->state.multicast = calloc(1, sizeof(struct multicast_s));
|
|
||||||
}
|
|
||||||
else if (rig->state.multicast->multicast_running) { return RIG_OK; } // we only need one port
|
|
||||||
|
|
||||||
//rig->state.multicast->mreq = {0};
|
|
||||||
|
|
||||||
if (addr == NULL) { addr = RIG_MULTICAST_ADDR; }
|
|
||||||
|
|
||||||
if (port == 0) { port = RIG_MULTICAST_PORT; }
|
|
||||||
|
|
||||||
// Create a UDP socket
|
|
||||||
rig->state.multicast->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
|
|
||||||
if (rig->state.multicast->sock < 0)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
int err = WSAGetLastError();
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: socket: WSAGetLastError=%d\n", __func__, err);
|
|
||||||
#else
|
#else
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: socket: %s\n", __func__, strerror(errno));
|
rig_debug(RIG_DEBUG_ERR, "%s: socket: %s\n", __func__, strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
return -RIG_EIO;
|
return -RIG_EIO;
|
||||||
}
|
|
||||||
|
|
||||||
// Set the SO_REUSEADDR option to allow multiple processes to use the same address
|
|
||||||
int optval = 1;
|
|
||||||
|
|
||||||
if (setsockopt(rig->state.multicast->sock, SOL_SOCKET, SO_REUSEADDR,
|
|
||||||
(char *)&optval,
|
|
||||||
sizeof(optval)) < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
|
||||||
return -RIG_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind the socket to any available local address and the specified port
|
|
||||||
struct sockaddr_in saddr = {0};
|
|
||||||
saddr.sin_family = AF_INET;
|
|
||||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
saddr.sin_port = htons(port);
|
|
||||||
|
|
||||||
if (bind(rig->state.multicast->sock, (struct sockaddr *)&saddr,
|
|
||||||
sizeof(saddr)) < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: bind: %s\n", __func__, strerror(errno));
|
|
||||||
return -RIG_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the multicast group address
|
|
||||||
// struct ip_mreq mreq = {0};
|
|
||||||
rig->state.multicast->mreq.imr_multiaddr.s_addr = inet_addr(addr);
|
|
||||||
rig->state.multicast->mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
||||||
|
|
||||||
// Set the multicast TTL (time-to-live) to limit the scope of the packets
|
|
||||||
char ttl = 1;
|
|
||||||
|
|
||||||
if (setsockopt(rig->state.multicast->sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
|
|
||||||
sizeof(ttl)) < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
|
||||||
return -RIG_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join the multicast group
|
|
||||||
if (setsockopt(rig->state.multicast->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
||||||
(char *)&rig->state.multicast->mreq, sizeof(rig->state.multicast->mreq)) < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
|
||||||
return -RIG_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prime the dest_addr for the send routine
|
|
||||||
rig->state.multicast->dest_addr.sin_family = AF_INET;
|
|
||||||
rig->state.multicast->dest_addr.sin_addr.s_addr = inet_addr(addr);
|
|
||||||
rig->state.multicast->dest_addr.sin_port = htons(port);
|
|
||||||
|
|
||||||
printf("starting thread\n");
|
|
||||||
|
|
||||||
rig->state.multicast->runflag = 1;
|
|
||||||
pthread_create(&rig->state.multicast->threadid, NULL, multicast_thread,
|
|
||||||
(void *)rig);
|
|
||||||
//printf("threadid=%ld\n", rig->state.multicast->threadid);
|
|
||||||
rig->state.multicast->multicast_running = 1;
|
|
||||||
return RIG_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void multicast_close(RIG * rig)
|
// Set the SO_REUSEADDR option to allow multiple processes to use the same address
|
||||||
|
int optval = 1;
|
||||||
|
|
||||||
|
if (setsockopt(rig->state.multicast->sock, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char *)&optval,
|
||||||
|
sizeof(optval)) < 0)
|
||||||
{
|
{
|
||||||
int retval;
|
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
||||||
|
return -RIG_EIO;
|
||||||
// Leave the multicast group
|
|
||||||
if ((retval = setsockopt(rig->state.multicast->sock, IPPROTO_IP,
|
|
||||||
IP_DROP_MEMBERSHIP, (char *)&rig->state.multicast->mreq,
|
|
||||||
sizeof(rig->state.multicast->mreq))) < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the socket
|
|
||||||
if ((retval = close(rig->state.multicast->sock)))
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: close: %s\n", __func__, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind the socket to any available local address and the specified port
|
||||||
|
struct sockaddr_in saddr = {0};
|
||||||
|
saddr.sin_family = AF_INET;
|
||||||
|
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
saddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
if (bind(rig->state.multicast->sock, (struct sockaddr *)&saddr,
|
||||||
|
sizeof(saddr)) < 0)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: bind: %s\n", __func__, strerror(errno));
|
||||||
|
return -RIG_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the multicast group address
|
||||||
|
// struct ip_mreq mreq = {0};
|
||||||
|
rig->state.multicast->mreq.imr_multiaddr.s_addr = inet_addr(addr);
|
||||||
|
rig->state.multicast->mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
// Set the multicast TTL (time-to-live) to limit the scope of the packets
|
||||||
|
char ttl = 1;
|
||||||
|
|
||||||
|
if (setsockopt(rig->state.multicast->sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
|
||||||
|
sizeof(ttl)) < 0)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
||||||
|
return -RIG_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join the multicast group
|
||||||
|
if (setsockopt(rig->state.multicast->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
|
(char *)&rig->state.multicast->mreq, sizeof(rig->state.multicast->mreq)) < 0)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
||||||
|
return -RIG_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prime the dest_addr for the send routine
|
||||||
|
rig->state.multicast->dest_addr.sin_family = AF_INET;
|
||||||
|
rig->state.multicast->dest_addr.sin_addr.s_addr = inet_addr(addr);
|
||||||
|
rig->state.multicast->dest_addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
printf("starting thread\n");
|
||||||
|
|
||||||
|
rig->state.multicast->runflag = 1;
|
||||||
|
pthread_create(&rig->state.multicast->threadid, NULL, multicast_thread,
|
||||||
|
(void *)rig);
|
||||||
|
//printf("threadid=%ld\n", rig->state.multicast->threadid);
|
||||||
|
rig->state.multicast->multicast_running = 1;
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void multicast_close(RIG *rig)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
// Leave the multicast group
|
||||||
|
if ((retval = setsockopt(rig->state.multicast->sock, IPPROTO_IP,
|
||||||
|
IP_DROP_MEMBERSHIP, (char *)&rig->state.multicast->mreq,
|
||||||
|
sizeof(rig->state.multicast->mreq))) < 0)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: setsockopt: %s\n", __func__, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the socket
|
||||||
|
if ((retval = close(rig->state.multicast->sock)))
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_ERR, "%s: close: %s\n", __func__, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if msglen=0 msg is assumed to be a string
|
// if msglen=0 msg is assumed to be a string
|
||||||
int multicast_send(RIG * rig, const char *msg, int msglen)
|
int multicast_send(RIG *rig, const char *msg, int msglen)
|
||||||
|
{
|
||||||
|
// Construct the message to send
|
||||||
|
if (msglen == 0) { msglen = strlen((char *)msg); }
|
||||||
|
|
||||||
|
// Send the message to the multicast group
|
||||||
|
ssize_t num_bytes = sendto(rig->state.multicast->sock, msg, msglen, 0,
|
||||||
|
(struct sockaddr *)&rig->state.multicast->dest_addr,
|
||||||
|
sizeof(rig->state.multicast->dest_addr));
|
||||||
|
|
||||||
|
if (num_bytes < 0)
|
||||||
{
|
{
|
||||||
// Construct the message to send
|
rig_debug(RIG_DEBUG_ERR, "%s: sendto: %s\n", __func__, strerror(errno));
|
||||||
if (msglen == 0) { msglen = strlen((char *)msg); }
|
return -RIG_EIO;
|
||||||
|
|
||||||
// Send the message to the multicast group
|
|
||||||
ssize_t num_bytes = sendto(rig->state.multicast->sock, msg, msglen, 0,
|
|
||||||
(struct sockaddr *)&rig->state.multicast->dest_addr,
|
|
||||||
sizeof(rig->state.multicast->dest_addr));
|
|
||||||
|
|
||||||
if (num_bytes < 0)
|
|
||||||
{
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s: sendto: %s\n", __func__, strerror(errno));
|
|
||||||
return -RIG_EIO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// printf("Sent %zd bytes to multicast group %s:%d\n", num_bytes, MULTICAST_ADDR,
|
|
||||||
// PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return num_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
//#define TEST
|
//#define TEST
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
RIG *rig;
|
||||||
|
rig_model_t myrig_model;
|
||||||
|
rig_set_debug_level(RIG_DEBUG_NONE);
|
||||||
|
|
||||||
|
if (argc > 1) { myrig_model = atoi(argv[1]); }
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RIG *rig;
|
myrig_model = 1035;
|
||||||
rig_model_t myrig_model;
|
|
||||||
rig_set_debug_level(RIG_DEBUG_NONE);
|
|
||||||
|
|
||||||
if (argc > 1) { myrig_model = atoi(argv[1]); }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
myrig_model = 1035;
|
|
||||||
}
|
|
||||||
|
|
||||||
rig = rig_init(myrig_model);
|
|
||||||
|
|
||||||
if (rig == NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(rig->state.rigport.pathname, "/dev/ttyUSB0", HAMLIB_FILPATHLEN - 1);
|
|
||||||
rig->state.rigport.parm.serial.rate = 38400;
|
|
||||||
rig_open(rig);
|
|
||||||
multicast_init(rig, "224.0.0.1", 4532);
|
|
||||||
pthread_join(rig->state.multicast->threadid, NULL);
|
|
||||||
pthread_exit(NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rig = rig_init(myrig_model);
|
||||||
|
|
||||||
|
if (rig == NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(rig->state.rigport.pathname, "/dev/ttyUSB0", HAMLIB_FILPATHLEN - 1);
|
||||||
|
rig->state.rigport.parm.serial.rate = 38400;
|
||||||
|
rig_open(rig);
|
||||||
|
multicast_init(rig, "224.0.0.1", 4532);
|
||||||
|
pthread_join(rig->state.multicast->threadid, NULL);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Ładowanie…
Reference in New Issue