diff --git a/src/multicast.c b/src/multicast.c index 9b290ba34..801fa1164 100644 --- a/src/multicast.c +++ b/src/multicast.c @@ -327,198 +327,191 @@ void *multicast_thread(void *vrig) #ifdef WIN32 static char *GetWinsockLastError(char *errorBuffer, DWORD errorBufferSize) { - void GetWinsockErrorString(char *errorBuffer, DWORD errorBufferSize) - { - int errorCode = WSAGetLastError(); - DWORD charsWritten; + int errorCode = WSAGetLastError(); - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - errorBuffer, - errorBufferSize, - NULL - ); + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorBuffer, + errorBufferSize, + 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 - 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 - 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 - - 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); + int err = WSAGetLastError(); + rig_debug(RIG_DEBUG_ERR, "%s: socket: WSAGetLastError=%d\n", __func__, err); #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 - 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; + return -RIG_EIO; } - 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; - - // 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)); - } + 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) +{ + 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 - 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 - 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) - { - 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; + rig_debug(RIG_DEBUG_ERR, "%s: sendto: %s\n", __func__, strerror(errno)); + return -RIG_EIO; } + return num_bytes; +} + //#define 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; - 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; + 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; +} #endif