From: Ramakrishnan Muthukrishnan <ram@rkrishnan.org> Date: Thu, 5 Dec 2024 15:30:47 +0000 (+0530) Subject: gitignore: add .cache (generated by clangd) X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg/about/reliability?a=commitdiff_plain;h=83303637ec860f9b823730a7e21804db78ddbe7d;p=pihpsdr.git gitignore: add .cache (generated by clangd) --- diff --git a/.gitignore b/.gitignore index 3166f93..b52d011 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ pihpsdr .vscode rust/* +.cache/* \ No newline at end of file diff --git a/new_discovery.c b/new_discovery.c deleted file mode 100644 index 1d860c9..0000000 --- a/new_discovery.c +++ /dev/null @@ -1,302 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#include <gtk/gtk.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <net/if_arp.h> -#include <net/if.h> -#include <netinet/in.h> -#include <ifaddrs.h> -#include <string.h> -#include <errno.h> - -#include "discovered.h" -//#include "discovery.h" - - -static char interface_name[64]; -static struct sockaddr_in interface_addr={0}; -static struct sockaddr_in interface_netmask={0}; - -#define DISCOVERY_PORT 1024 -static int discovery_socket; - -void new_discover(struct ifaddrs* iface); - -static GThread *discover_thread_id; -gpointer new_discover_receive_thread(gpointer data); - -void print_device(int i) { - fprintf(stderr,"discovery: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", - discovered[i].protocol, - discovered[i].device, - discovered[i].software_version, - discovered[i].status, - inet_ntoa(discovered[i].info.network.address.sin_addr), - discovered[i].info.network.mac_address[0], - discovered[i].info.network.mac_address[1], - discovered[i].info.network.mac_address[2], - discovered[i].info.network.mac_address[3], - discovered[i].info.network.mac_address[4], - discovered[i].info.network.mac_address[5], - discovered[i].info.network.interface_name); -} - -void new_discovery() { - struct ifaddrs *addrs,*ifa; - getifaddrs(&addrs); - ifa = addrs; - while (ifa) { - g_main_context_iteration(NULL, 0); - if (ifa->ifa_addr) { - if(ifa->ifa_addr->sa_family == AF_INET && - (ifa->ifa_flags&IFF_UP)==IFF_UP && - (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING) { - new_discover(ifa); - } - } - ifa = ifa->ifa_next; - } - freeifaddrs(addrs); - - - fprintf(stderr, "new_discovery found %d devices\n",devices); - - int i; - for(i=0;i<devices;i++) { - print_device(i); - } -} - -void new_discover(struct ifaddrs* iface) { - int rc; - struct sockaddr_in *sa; - struct sockaddr_in *mask; - char addr[16]; - char net_mask[16]; - - strcpy(interface_name,iface->ifa_name); - fprintf(stderr,"new_discover: looking for HPSDR devices on %s\n",interface_name); - - // send a broadcast to locate metis boards on the network - discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); - if(discovery_socket<0) { - perror("new_discover: create socket failed for discovery_socket\n"); - exit(-1); - } - - int optval = 1; - setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); - - sa = (struct sockaddr_in *) iface->ifa_addr; - mask = (struct sockaddr_in *) iface->ifa_netmask; - - interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr; - - // bind to this interface and the discovery port - interface_addr.sin_family = AF_INET; - interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr; - interface_addr.sin_port = htons(0); - if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) { - perror("new_discover: bind socket failed for discovery_socket\n"); - exit(-1); - } - - strcpy(addr,inet_ntoa(sa->sin_addr)); - strcpy(net_mask,inet_ntoa(mask->sin_addr)); - - fprintf(stderr,"new_discover: bound to %s %s %s\n",interface_name,addr,net_mask); - - // allow broadcast on the socket - int on=1; - rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); - if(rc != 0) { - fprintf(stderr,"new_discover: cannot set SO_BROADCAST: rc=%d\n", rc); - exit(-1); - } - - // setup to address - struct sockaddr_in to_addr={0}; - to_addr.sin_family=AF_INET; - to_addr.sin_port=htons(DISCOVERY_PORT); - to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); - - // start a receive thread to collect discovery response packets - discover_thread_id = g_thread_new( "new discover receive", new_discover_receive_thread, NULL); - if( ! discover_thread_id ) - { - fprintf(stderr,"g_thread_new failed on new_discover_receive_thread\n"); - exit( -1 ); - } - fprintf(stderr,"new_disovery: thread_id=%p\n",discover_thread_id); - - - // send discovery packet - unsigned char buffer[60]; - buffer[0]=0x00; - buffer[1]=0x00; - buffer[2]=0x00; - buffer[3]=0x00; - buffer[4]=0x02; - int i; - for(i=5;i<60;i++) { - buffer[i]=0x00; - } - - if(sendto(discovery_socket,buffer,60,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) { - perror("new_discover: sendto socket failed for discovery_socket\n"); - return; - } - - // wait for receive thread to complete - g_thread_join(discover_thread_id); - - close(discovery_socket); - - fprintf(stderr,"new_discover: exiting discover for %s\n",iface->ifa_name); -} - -//void* new_discover_receive_thread(void* arg) { -gpointer new_discover_receive_thread(gpointer data) { - struct sockaddr_in addr; - socklen_t len; - unsigned char buffer[2048]; - int bytes_read; - struct timeval tv; - int i; - double frequency_min, frequency_max; - - tv.tv_sec = 2; - tv.tv_usec = 0; - - setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - - len=sizeof(addr); - while(1) { - bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len); - if(bytes_read<0) { - fprintf(stderr,"new_discover: bytes read %d\n", bytes_read); - perror("new_discover: recvfrom socket failed for discover_receive_thread"); - break; - } - fprintf(stderr,"new_discover: received %d bytes\n",bytes_read); - if(bytes_read==1444) { - if(devices>0) { - break; - } - } else { - if(buffer[0]==0 && buffer[1]==0 && buffer[2]==0 && buffer[3]==0) { - int status = buffer[4] & 0xFF; - if (status == 2 || status == 3) { - if(devices<MAX_DEVICES) { - discovered[devices].protocol=NEW_PROTOCOL; - discovered[devices].device=buffer[11]&0xFF; - discovered[devices].software_version=buffer[13]&0xFF; - discovered[devices].status=status; - switch(discovered[devices].device) { - case NEW_DEVICE_ATLAS: - strcpy(discovered[devices].name,"Atlas"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_HERMES: - strcpy(discovered[devices].name,"Hermes"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_HERMES2: - strcpy(discovered[devices].name,"Hermes2"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_ANGELIA: - strcpy(discovered[devices].name,"Angelia"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_ORION: - strcpy(discovered[devices].name,"Orion"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_ORION2: - strcpy(discovered[devices].name,"Orion2"); - frequency_min=0.0; - frequency_max=61440000.0; - break; - case NEW_DEVICE_HERMES_LITE: - if (discovered[devices].software_version < 40) { - strcpy(discovered[devices].name,"Hermes Lite V1"); - } else { - strcpy(discovered[devices].name,"Hermes Lite V2"); - discovered[devices].device = NEW_DEVICE_HERMES_LITE2; - } - frequency_min=0.0; - frequency_max=30720000.0; - break; - default: - strcpy(discovered[devices].name,"Unknown"); - frequency_min=0.0; - frequency_max=30720000.0; - break; - } - for(i=0;i<6;i++) { - discovered[devices].info.network.mac_address[i]=buffer[i+5]; - } - memcpy((void*)&discovered[devices].info.network.address,(void*)&addr,sizeof(addr)); - discovered[devices].info.network.address_length=sizeof(addr); - memcpy((void*)&discovered[devices].info.network.interface_address,(void*)&interface_addr,sizeof(interface_addr)); - memcpy((void*)&discovered[devices].info.network.interface_netmask,(void*)&interface_netmask,sizeof(interface_netmask)); - discovered[devices].info.network.interface_length=sizeof(interface_addr); - strcpy(discovered[devices].info.network.interface_name,interface_name); - discovered[devices].supported_receivers=2; - fprintf(stderr,"new_discover: found %d protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", - devices, - discovered[devices].protocol, - discovered[devices].device, - discovered[devices].software_version, - discovered[devices].status, - inet_ntoa(discovered[devices].info.network.address.sin_addr), - discovered[devices].info.network.mac_address[0], - discovered[devices].info.network.mac_address[1], - discovered[devices].info.network.mac_address[2], - discovered[devices].info.network.mac_address[3], - discovered[devices].info.network.mac_address[4], - discovered[devices].info.network.mac_address[5], - discovered[devices].info.network.interface_name); - discovered[devices].frequency_min=frequency_min; - discovered[devices].frequency_max=frequency_max; - devices++; - } - } - } - } - } - fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n"); - g_thread_exit(NULL); - return NULL; -} diff --git a/new_discovery.h b/new_discovery.h deleted file mode 100644 index 9851f22..0000000 --- a/new_discovery.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#ifndef _NEW_DISCOVERY_H -#define _NEW_DISCOVERY_H - -void new_discovery(void); - -#endif diff --git a/old_discovery.c b/old_discovery.c deleted file mode 100644 index 8c8cfc0..0000000 --- a/old_discovery.c +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#include <gtk/gtk.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <net/if_arp.h> -#include <net/if.h> -#include <ifaddrs.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/select.h> - -#include "discovered.h" -#include "discovery.h" -#include "old_discovery.h" -#include "log.h" - -static char interface_name[64]; -static struct sockaddr_in interface_addr={0}; -static struct sockaddr_in interface_netmask={0}; - -#define DISCOVERY_PORT 1024 -static int discovery_socket; - -static GThread *discover_thread_id; -static gpointer discover_receive_thread(gpointer data); - -static void discover(struct ifaddrs* iface) { - int rc; - struct sockaddr_in *sa; - struct sockaddr_in *mask; - struct sockaddr_in to_addr={0}; - int flags; - struct timeval tv; - int optval; - socklen_t optlen; - fd_set fds; - unsigned char buffer[1032]; - int i, len; - - if (iface == NULL) { - // - // This indicates that we want to connect to an SDR which - // cannot be reached by (UDP) broadcast packets, but that - // we know its fixed IP address - // Therefore we try to send a METIS detection packet via TCP - // to a "fixed" ip address. - // - log_trace("Trying to detect at TCP addr %s", ipaddr_tcp); - memset(&to_addr, 0, sizeof(to_addr)); - to_addr.sin_family = AF_INET; - if (inet_aton(ipaddr_tcp, &to_addr.sin_addr) == 0) { - log_error("discover: TCP addr %s is invalid!",ipaddr_tcp); - return; - } - to_addr.sin_port=htons(DISCOVERY_PORT); - - discovery_socket=socket(AF_INET, SOCK_STREAM, 0); - if(discovery_socket<0) { - perror("discover: create socket failed for TCP discovery_socket\n"); - return; - } - // - // Here I tried a bullet-proof approach to connect() such that the program - // does not "hang" under any circumstances. - // - First, one makes the socket non-blocking. Then, the connect() will - // immediately return with error EINPROGRESS. - // - Then, one uses select() to look for *writeability* and check - // the socket error if everything went right. Since one calls select() - // with a time-out, one either succeed within this time or gives up. - // - Do not forget to make the socket blocking again. - // - // Step 1. Make socket non-blocking and connect() - flags=fcntl(discovery_socket, F_GETFL, 0); - fcntl(discovery_socket, F_SETFL, flags | O_NONBLOCK); - rc=connect(discovery_socket, (const struct sockaddr *)&to_addr, sizeof(to_addr)); - if ((errno != EINPROGRESS) && (rc < 0)) { - perror("discover: connect() failed for TCP discovery_socket:"); - close(discovery_socket); - return; - } - // Step 2. Use select to wait for the connection - tv.tv_sec=3; - tv.tv_usec=0; - FD_ZERO(&fds); - FD_SET(discovery_socket, &fds); - rc=select(discovery_socket+1, NULL, &fds, NULL, &tv); - if (rc < 0) { - perror("discover: select() failed on TCP discovery_socket:"); - close(discovery_socket); - return; - } - // If no connection occured, return - if (rc == 0) { - // select timed out - log_error("discover: select() timed out on TCP discovery socket"); - close(discovery_socket); - return; - } - // Step 3. select() succeeded. Check success of connect() - optlen=sizeof(int); - rc=getsockopt(discovery_socket, SOL_SOCKET, SO_ERROR, &optval, &optlen); - if (rc < 0) { - // this should very rarely happen - perror("discover: getsockopt() failed on TCP discovery_socket:"); - close(discovery_socket); - return; - } - if (optval != 0) { - // connect did not succeed - log_error("discover: connect() on TCP socket did not succeed"); - close(discovery_socket); - return; - } - // Step 4. reset the socket to normal (blocking) mode - fcntl(discovery_socket, F_SETFL, flags & ~O_NONBLOCK); - } else { - - strcpy(interface_name,iface->ifa_name); - log_trace("discover: looking for HPSDR devices on %s", interface_name); - - // send a broadcast to locate hpsdr boards on the network - discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); - if(discovery_socket<0) { - perror("discover: create socket failed for discovery_socket:"); - exit(-1); - } - - sa = (struct sockaddr_in *) iface->ifa_addr; - mask = (struct sockaddr_in *) iface->ifa_netmask; - interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr; - - // bind to this interface and the discovery port - interface_addr.sin_family = AF_INET; - interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr; - //interface_addr.sin_port = htons(DISCOVERY_PORT*2); - interface_addr.sin_port = htons(0); // system assigned port - if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) { - perror("discover: bind socket failed for discovery_socket:"); - return; - } - - log_trace("discover: bound to %s",interface_name); - - // allow broadcast on the socket - int on=1; - rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); - if(rc != 0) { - log_error("discover: cannot set SO_BROADCAST: rc=%d", rc); - exit(-1); - } - - // setup to address - to_addr.sin_family=AF_INET; - to_addr.sin_port=htons(DISCOVERY_PORT); - to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); - } - optval = 1; - setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); - - rc=devices; - // start a receive thread to collect discovery response packets - discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL); - if( ! discover_thread_id ) - { - log_error("g_thread_new failed on discover_receive_thread"); - exit(-1); - } - - - - // send discovery packet - // If this is a TCP connection, send a "long" packet - len=63; - if (iface == NULL) len=1032; - buffer[0]=0xEF; - buffer[1]=0xFE; - buffer[2]=0x02; - for(i=3;i<len;i++) { - buffer[i]=0x00; - } - - if(sendto(discovery_socket,buffer,len,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) { - perror("discover: sendto socket failed for discovery_socket:"); - return; - } - - // wait for receive thread to complete - g_thread_join(discover_thread_id); - - close(discovery_socket); - - if (iface == NULL) { - log_trace("discover: exiting TCP discover for %s",ipaddr_tcp); - if (devices == rc+1) { - // - // We have exactly found one TCP device - // and have to patch the TCP addr into the device field - // and set the "use TCP" flag. - // - memcpy((void*)&discovered[rc].info.network.address,(void*)&to_addr,sizeof(to_addr)); - discovered[rc].info.network.address_length=sizeof(to_addr); - memcpy((void*)&discovered[rc].info.network.interface_address,(void*)&to_addr,sizeof(to_addr)); - memcpy((void*)&discovered[rc].info.network.interface_netmask,(void*)&to_addr,sizeof(to_addr)); - discovered[rc].info.network.interface_length=sizeof(to_addr); - strcpy(discovered[rc].info.network.interface_name,"TCP"); - discovered[rc].use_tcp=1; - } - } else { - log_trace("discover: exiting discover for %s",iface->ifa_name); - } - -} - - -//static void *discover_receive_thread(void* arg) { -static gpointer discover_receive_thread(gpointer data) { - struct sockaddr_in addr; - socklen_t len; - unsigned char buffer[2048]; - int bytes_read; - struct timeval tv; - int i; - - tv.tv_sec = 2; - tv.tv_usec = 0; - setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - - len=sizeof(addr); - while(1) { - bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),1032,(struct sockaddr*)&addr,&len); - if(bytes_read<0) { - log_debug("discovery: bytes read %d", bytes_read); - log_error("old_discovery: recvfrom socket failed for discover_receive_thread: %s", strerror(errno)); - break; - } - if (bytes_read == 0) break; - log_trace("old_discovery: received %d bytes",bytes_read); - if ((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) { - int status = buffer[2] & 0xFF; - if (status == 2 || status == 3) { - if(devices<MAX_DEVICES) { - discovered[devices].protocol=ORIGINAL_PROTOCOL; - discovered[devices].device=buffer[10]&0xFF; - discovered[devices].software_version=buffer[9]&0xFF; - switch(discovered[devices].device) { - case DEVICE_METIS: - strcpy(discovered[devices].name,"Metis"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - case DEVICE_HERMES: - strcpy(discovered[devices].name,"Hermes"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - case DEVICE_GRIFFIN: - strcpy(discovered[devices].name,"Griffin"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - case DEVICE_ANGELIA: - strcpy(discovered[devices].name,"Angelia"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - case DEVICE_ORION: - strcpy(discovered[devices].name,"Orion"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - case DEVICE_HERMES_LITE: - // - // It seems that some HermesLite V2 boards use - // DEVICE_HERMES_LITE as the ID and a software version - // that is larger or equal to 40, while the original - // (V1) HermesLite boards have software versions up to 31. - // Therefore this is possibly a HL2 board! - if (discovered[devices].software_version < 40) { - strcpy(discovered[devices].name,"HermesLite V1"); - } else { - strcpy(discovered[devices].name,"HermesLite V2"); - discovered[devices].device = DEVICE_HERMES_LITE2; - log_trace("discovered HL2: Gateware Major Version=%d Minor Version=%d",buffer[9],buffer[15]); - } - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=30720000.0; - break; - case DEVICE_HERMES_LITE2: - strcpy(discovered[devices].name,"HermesLite V2"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=30720000.0; - break; - case DEVICE_ORION2: - strcpy(discovered[devices].name,"Orion2"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - default: - strcpy(discovered[devices].name,"Unknown"); - discovered[devices].frequency_min=0.0; - discovered[devices].frequency_max=61440000.0; - break; - } - log_trace("old_discovery: name=%s min=%f max=%f",discovered[devices].name, discovered[devices].frequency_min, discovered[devices].frequency_max); - for(i=0;i<6;i++) { - discovered[devices].info.network.mac_address[i]=buffer[i+3]; - } - discovered[devices].status=status; - memcpy((void*)&discovered[devices].info.network.address,(void*)&addr,sizeof(addr)); - discovered[devices].info.network.address_length=sizeof(addr); - memcpy((void*)&discovered[devices].info.network.interface_address,(void*)&interface_addr,sizeof(interface_addr)); - memcpy((void*)&discovered[devices].info.network.interface_netmask,(void*)&interface_netmask,sizeof(interface_netmask)); - discovered[devices].info.network.interface_length=sizeof(interface_addr); - strcpy(discovered[devices].info.network.interface_name,interface_name); - discovered[devices].use_tcp=0; - discovered[devices].supported_receivers=2; - log_trace("old_discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s min=%f max=%f", - discovered[devices].device, - discovered[devices].software_version, - discovered[devices].status, - inet_ntoa(discovered[devices].info.network.address.sin_addr), - discovered[devices].info.network.mac_address[0], - discovered[devices].info.network.mac_address[1], - discovered[devices].info.network.mac_address[2], - discovered[devices].info.network.mac_address[3], - discovered[devices].info.network.mac_address[4], - discovered[devices].info.network.mac_address[5], - discovered[devices].info.network.interface_name, - discovered[devices].frequency_min, - discovered[devices].frequency_max); - devices++; - } - } - } - - } - log_trace("discovery: exiting discover_receive_thread"); - g_thread_exit(NULL); - return NULL; -} - -void old_discovery() { - struct ifaddrs *addrs,*ifa; - - getifaddrs(&addrs); - ifa = addrs; - while (ifa) { - g_main_context_iteration(NULL, 0); - if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { - if((ifa->ifa_flags&IFF_UP)==IFF_UP - && (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING) { - // && (ifa->ifa_flags&IFF_LOOPBACK)==IFF_LOOPBACK) { - discover(ifa); - } - } - ifa = ifa->ifa_next; - } - freeifaddrs(addrs); - - // Do one additional "discover" for a fixed TCP address - discover(NULL); - - log_trace("discovery found %d devices",devices); - - for(size_t i = 0; i < devices; i++) { - log_trace("discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s", - discovered[i].device, - discovered[i].software_version, - discovered[i].status, - inet_ntoa(discovered[i].info.network.address.sin_addr), - discovered[i].info.network.mac_address[0], - discovered[i].info.network.mac_address[1], - discovered[i].info.network.mac_address[2], - discovered[i].info.network.mac_address[3], - discovered[i].info.network.mac_address[4], - discovered[i].info.network.mac_address[5], - discovered[i].info.network.interface_name); - } -} - diff --git a/old_discovery.h b/old_discovery.h deleted file mode 100644 index fb3a2f5..0000000 --- a/old_discovery.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#ifndef _OLD_DISCOVERY_H -#define _OLD_DISCOVERY_H - -void old_discovery(void); - -#endif diff --git a/p1_discovery.c b/p1_discovery.c new file mode 100644 index 0000000..8c8cfc0 --- /dev/null +++ b/p1_discovery.c @@ -0,0 +1,406 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include <gtk/gtk.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <net/if_arp.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/select.h> + +#include "discovered.h" +#include "discovery.h" +#include "old_discovery.h" +#include "log.h" + +static char interface_name[64]; +static struct sockaddr_in interface_addr={0}; +static struct sockaddr_in interface_netmask={0}; + +#define DISCOVERY_PORT 1024 +static int discovery_socket; + +static GThread *discover_thread_id; +static gpointer discover_receive_thread(gpointer data); + +static void discover(struct ifaddrs* iface) { + int rc; + struct sockaddr_in *sa; + struct sockaddr_in *mask; + struct sockaddr_in to_addr={0}; + int flags; + struct timeval tv; + int optval; + socklen_t optlen; + fd_set fds; + unsigned char buffer[1032]; + int i, len; + + if (iface == NULL) { + // + // This indicates that we want to connect to an SDR which + // cannot be reached by (UDP) broadcast packets, but that + // we know its fixed IP address + // Therefore we try to send a METIS detection packet via TCP + // to a "fixed" ip address. + // + log_trace("Trying to detect at TCP addr %s", ipaddr_tcp); + memset(&to_addr, 0, sizeof(to_addr)); + to_addr.sin_family = AF_INET; + if (inet_aton(ipaddr_tcp, &to_addr.sin_addr) == 0) { + log_error("discover: TCP addr %s is invalid!",ipaddr_tcp); + return; + } + to_addr.sin_port=htons(DISCOVERY_PORT); + + discovery_socket=socket(AF_INET, SOCK_STREAM, 0); + if(discovery_socket<0) { + perror("discover: create socket failed for TCP discovery_socket\n"); + return; + } + // + // Here I tried a bullet-proof approach to connect() such that the program + // does not "hang" under any circumstances. + // - First, one makes the socket non-blocking. Then, the connect() will + // immediately return with error EINPROGRESS. + // - Then, one uses select() to look for *writeability* and check + // the socket error if everything went right. Since one calls select() + // with a time-out, one either succeed within this time or gives up. + // - Do not forget to make the socket blocking again. + // + // Step 1. Make socket non-blocking and connect() + flags=fcntl(discovery_socket, F_GETFL, 0); + fcntl(discovery_socket, F_SETFL, flags | O_NONBLOCK); + rc=connect(discovery_socket, (const struct sockaddr *)&to_addr, sizeof(to_addr)); + if ((errno != EINPROGRESS) && (rc < 0)) { + perror("discover: connect() failed for TCP discovery_socket:"); + close(discovery_socket); + return; + } + // Step 2. Use select to wait for the connection + tv.tv_sec=3; + tv.tv_usec=0; + FD_ZERO(&fds); + FD_SET(discovery_socket, &fds); + rc=select(discovery_socket+1, NULL, &fds, NULL, &tv); + if (rc < 0) { + perror("discover: select() failed on TCP discovery_socket:"); + close(discovery_socket); + return; + } + // If no connection occured, return + if (rc == 0) { + // select timed out + log_error("discover: select() timed out on TCP discovery socket"); + close(discovery_socket); + return; + } + // Step 3. select() succeeded. Check success of connect() + optlen=sizeof(int); + rc=getsockopt(discovery_socket, SOL_SOCKET, SO_ERROR, &optval, &optlen); + if (rc < 0) { + // this should very rarely happen + perror("discover: getsockopt() failed on TCP discovery_socket:"); + close(discovery_socket); + return; + } + if (optval != 0) { + // connect did not succeed + log_error("discover: connect() on TCP socket did not succeed"); + close(discovery_socket); + return; + } + // Step 4. reset the socket to normal (blocking) mode + fcntl(discovery_socket, F_SETFL, flags & ~O_NONBLOCK); + } else { + + strcpy(interface_name,iface->ifa_name); + log_trace("discover: looking for HPSDR devices on %s", interface_name); + + // send a broadcast to locate hpsdr boards on the network + discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); + if(discovery_socket<0) { + perror("discover: create socket failed for discovery_socket:"); + exit(-1); + } + + sa = (struct sockaddr_in *) iface->ifa_addr; + mask = (struct sockaddr_in *) iface->ifa_netmask; + interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr; + + // bind to this interface and the discovery port + interface_addr.sin_family = AF_INET; + interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr; + //interface_addr.sin_port = htons(DISCOVERY_PORT*2); + interface_addr.sin_port = htons(0); // system assigned port + if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) { + perror("discover: bind socket failed for discovery_socket:"); + return; + } + + log_trace("discover: bound to %s",interface_name); + + // allow broadcast on the socket + int on=1; + rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); + if(rc != 0) { + log_error("discover: cannot set SO_BROADCAST: rc=%d", rc); + exit(-1); + } + + // setup to address + to_addr.sin_family=AF_INET; + to_addr.sin_port=htons(DISCOVERY_PORT); + to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); + } + optval = 1; + setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); + + rc=devices; + // start a receive thread to collect discovery response packets + discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL); + if( ! discover_thread_id ) + { + log_error("g_thread_new failed on discover_receive_thread"); + exit(-1); + } + + + + // send discovery packet + // If this is a TCP connection, send a "long" packet + len=63; + if (iface == NULL) len=1032; + buffer[0]=0xEF; + buffer[1]=0xFE; + buffer[2]=0x02; + for(i=3;i<len;i++) { + buffer[i]=0x00; + } + + if(sendto(discovery_socket,buffer,len,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) { + perror("discover: sendto socket failed for discovery_socket:"); + return; + } + + // wait for receive thread to complete + g_thread_join(discover_thread_id); + + close(discovery_socket); + + if (iface == NULL) { + log_trace("discover: exiting TCP discover for %s",ipaddr_tcp); + if (devices == rc+1) { + // + // We have exactly found one TCP device + // and have to patch the TCP addr into the device field + // and set the "use TCP" flag. + // + memcpy((void*)&discovered[rc].info.network.address,(void*)&to_addr,sizeof(to_addr)); + discovered[rc].info.network.address_length=sizeof(to_addr); + memcpy((void*)&discovered[rc].info.network.interface_address,(void*)&to_addr,sizeof(to_addr)); + memcpy((void*)&discovered[rc].info.network.interface_netmask,(void*)&to_addr,sizeof(to_addr)); + discovered[rc].info.network.interface_length=sizeof(to_addr); + strcpy(discovered[rc].info.network.interface_name,"TCP"); + discovered[rc].use_tcp=1; + } + } else { + log_trace("discover: exiting discover for %s",iface->ifa_name); + } + +} + + +//static void *discover_receive_thread(void* arg) { +static gpointer discover_receive_thread(gpointer data) { + struct sockaddr_in addr; + socklen_t len; + unsigned char buffer[2048]; + int bytes_read; + struct timeval tv; + int i; + + tv.tv_sec = 2; + tv.tv_usec = 0; + setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + + len=sizeof(addr); + while(1) { + bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),1032,(struct sockaddr*)&addr,&len); + if(bytes_read<0) { + log_debug("discovery: bytes read %d", bytes_read); + log_error("old_discovery: recvfrom socket failed for discover_receive_thread: %s", strerror(errno)); + break; + } + if (bytes_read == 0) break; + log_trace("old_discovery: received %d bytes",bytes_read); + if ((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) { + int status = buffer[2] & 0xFF; + if (status == 2 || status == 3) { + if(devices<MAX_DEVICES) { + discovered[devices].protocol=ORIGINAL_PROTOCOL; + discovered[devices].device=buffer[10]&0xFF; + discovered[devices].software_version=buffer[9]&0xFF; + switch(discovered[devices].device) { + case DEVICE_METIS: + strcpy(discovered[devices].name,"Metis"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + case DEVICE_HERMES: + strcpy(discovered[devices].name,"Hermes"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + case DEVICE_GRIFFIN: + strcpy(discovered[devices].name,"Griffin"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + case DEVICE_ANGELIA: + strcpy(discovered[devices].name,"Angelia"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + case DEVICE_ORION: + strcpy(discovered[devices].name,"Orion"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + case DEVICE_HERMES_LITE: + // + // It seems that some HermesLite V2 boards use + // DEVICE_HERMES_LITE as the ID and a software version + // that is larger or equal to 40, while the original + // (V1) HermesLite boards have software versions up to 31. + // Therefore this is possibly a HL2 board! + if (discovered[devices].software_version < 40) { + strcpy(discovered[devices].name,"HermesLite V1"); + } else { + strcpy(discovered[devices].name,"HermesLite V2"); + discovered[devices].device = DEVICE_HERMES_LITE2; + log_trace("discovered HL2: Gateware Major Version=%d Minor Version=%d",buffer[9],buffer[15]); + } + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=30720000.0; + break; + case DEVICE_HERMES_LITE2: + strcpy(discovered[devices].name,"HermesLite V2"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=30720000.0; + break; + case DEVICE_ORION2: + strcpy(discovered[devices].name,"Orion2"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + default: + strcpy(discovered[devices].name,"Unknown"); + discovered[devices].frequency_min=0.0; + discovered[devices].frequency_max=61440000.0; + break; + } + log_trace("old_discovery: name=%s min=%f max=%f",discovered[devices].name, discovered[devices].frequency_min, discovered[devices].frequency_max); + for(i=0;i<6;i++) { + discovered[devices].info.network.mac_address[i]=buffer[i+3]; + } + discovered[devices].status=status; + memcpy((void*)&discovered[devices].info.network.address,(void*)&addr,sizeof(addr)); + discovered[devices].info.network.address_length=sizeof(addr); + memcpy((void*)&discovered[devices].info.network.interface_address,(void*)&interface_addr,sizeof(interface_addr)); + memcpy((void*)&discovered[devices].info.network.interface_netmask,(void*)&interface_netmask,sizeof(interface_netmask)); + discovered[devices].info.network.interface_length=sizeof(interface_addr); + strcpy(discovered[devices].info.network.interface_name,interface_name); + discovered[devices].use_tcp=0; + discovered[devices].supported_receivers=2; + log_trace("old_discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s min=%f max=%f", + discovered[devices].device, + discovered[devices].software_version, + discovered[devices].status, + inet_ntoa(discovered[devices].info.network.address.sin_addr), + discovered[devices].info.network.mac_address[0], + discovered[devices].info.network.mac_address[1], + discovered[devices].info.network.mac_address[2], + discovered[devices].info.network.mac_address[3], + discovered[devices].info.network.mac_address[4], + discovered[devices].info.network.mac_address[5], + discovered[devices].info.network.interface_name, + discovered[devices].frequency_min, + discovered[devices].frequency_max); + devices++; + } + } + } + + } + log_trace("discovery: exiting discover_receive_thread"); + g_thread_exit(NULL); + return NULL; +} + +void old_discovery() { + struct ifaddrs *addrs,*ifa; + + getifaddrs(&addrs); + ifa = addrs; + while (ifa) { + g_main_context_iteration(NULL, 0); + if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { + if((ifa->ifa_flags&IFF_UP)==IFF_UP + && (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING) { + // && (ifa->ifa_flags&IFF_LOOPBACK)==IFF_LOOPBACK) { + discover(ifa); + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(addrs); + + // Do one additional "discover" for a fixed TCP address + discover(NULL); + + log_trace("discovery found %d devices",devices); + + for(size_t i = 0; i < devices; i++) { + log_trace("discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s", + discovered[i].device, + discovered[i].software_version, + discovered[i].status, + inet_ntoa(discovered[i].info.network.address.sin_addr), + discovered[i].info.network.mac_address[0], + discovered[i].info.network.mac_address[1], + discovered[i].info.network.mac_address[2], + discovered[i].info.network.mac_address[3], + discovered[i].info.network.mac_address[4], + discovered[i].info.network.mac_address[5], + discovered[i].info.network.interface_name); + } +} + diff --git a/p1_discovery.h b/p1_discovery.h new file mode 100644 index 0000000..fb3a2f5 --- /dev/null +++ b/p1_discovery.h @@ -0,0 +1,25 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _OLD_DISCOVERY_H +#define _OLD_DISCOVERY_H + +void old_discovery(void); + +#endif diff --git a/p2_discovery.c b/p2_discovery.c new file mode 100644 index 0000000..1d860c9 --- /dev/null +++ b/p2_discovery.c @@ -0,0 +1,302 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include <gtk/gtk.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <net/if_arp.h> +#include <net/if.h> +#include <netinet/in.h> +#include <ifaddrs.h> +#include <string.h> +#include <errno.h> + +#include "discovered.h" +//#include "discovery.h" + + +static char interface_name[64]; +static struct sockaddr_in interface_addr={0}; +static struct sockaddr_in interface_netmask={0}; + +#define DISCOVERY_PORT 1024 +static int discovery_socket; + +void new_discover(struct ifaddrs* iface); + +static GThread *discover_thread_id; +gpointer new_discover_receive_thread(gpointer data); + +void print_device(int i) { + fprintf(stderr,"discovery: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", + discovered[i].protocol, + discovered[i].device, + discovered[i].software_version, + discovered[i].status, + inet_ntoa(discovered[i].info.network.address.sin_addr), + discovered[i].info.network.mac_address[0], + discovered[i].info.network.mac_address[1], + discovered[i].info.network.mac_address[2], + discovered[i].info.network.mac_address[3], + discovered[i].info.network.mac_address[4], + discovered[i].info.network.mac_address[5], + discovered[i].info.network.interface_name); +} + +void new_discovery() { + struct ifaddrs *addrs,*ifa; + getifaddrs(&addrs); + ifa = addrs; + while (ifa) { + g_main_context_iteration(NULL, 0); + if (ifa->ifa_addr) { + if(ifa->ifa_addr->sa_family == AF_INET && + (ifa->ifa_flags&IFF_UP)==IFF_UP && + (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING) { + new_discover(ifa); + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(addrs); + + + fprintf(stderr, "new_discovery found %d devices\n",devices); + + int i; + for(i=0;i<devices;i++) { + print_device(i); + } +} + +void new_discover(struct ifaddrs* iface) { + int rc; + struct sockaddr_in *sa; + struct sockaddr_in *mask; + char addr[16]; + char net_mask[16]; + + strcpy(interface_name,iface->ifa_name); + fprintf(stderr,"new_discover: looking for HPSDR devices on %s\n",interface_name); + + // send a broadcast to locate metis boards on the network + discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); + if(discovery_socket<0) { + perror("new_discover: create socket failed for discovery_socket\n"); + exit(-1); + } + + int optval = 1; + setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); + + sa = (struct sockaddr_in *) iface->ifa_addr; + mask = (struct sockaddr_in *) iface->ifa_netmask; + + interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr; + + // bind to this interface and the discovery port + interface_addr.sin_family = AF_INET; + interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr; + interface_addr.sin_port = htons(0); + if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) { + perror("new_discover: bind socket failed for discovery_socket\n"); + exit(-1); + } + + strcpy(addr,inet_ntoa(sa->sin_addr)); + strcpy(net_mask,inet_ntoa(mask->sin_addr)); + + fprintf(stderr,"new_discover: bound to %s %s %s\n",interface_name,addr,net_mask); + + // allow broadcast on the socket + int on=1; + rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); + if(rc != 0) { + fprintf(stderr,"new_discover: cannot set SO_BROADCAST: rc=%d\n", rc); + exit(-1); + } + + // setup to address + struct sockaddr_in to_addr={0}; + to_addr.sin_family=AF_INET; + to_addr.sin_port=htons(DISCOVERY_PORT); + to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); + + // start a receive thread to collect discovery response packets + discover_thread_id = g_thread_new( "new discover receive", new_discover_receive_thread, NULL); + if( ! discover_thread_id ) + { + fprintf(stderr,"g_thread_new failed on new_discover_receive_thread\n"); + exit( -1 ); + } + fprintf(stderr,"new_disovery: thread_id=%p\n",discover_thread_id); + + + // send discovery packet + unsigned char buffer[60]; + buffer[0]=0x00; + buffer[1]=0x00; + buffer[2]=0x00; + buffer[3]=0x00; + buffer[4]=0x02; + int i; + for(i=5;i<60;i++) { + buffer[i]=0x00; + } + + if(sendto(discovery_socket,buffer,60,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) { + perror("new_discover: sendto socket failed for discovery_socket\n"); + return; + } + + // wait for receive thread to complete + g_thread_join(discover_thread_id); + + close(discovery_socket); + + fprintf(stderr,"new_discover: exiting discover for %s\n",iface->ifa_name); +} + +//void* new_discover_receive_thread(void* arg) { +gpointer new_discover_receive_thread(gpointer data) { + struct sockaddr_in addr; + socklen_t len; + unsigned char buffer[2048]; + int bytes_read; + struct timeval tv; + int i; + double frequency_min, frequency_max; + + tv.tv_sec = 2; + tv.tv_usec = 0; + + setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + + len=sizeof(addr); + while(1) { + bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len); + if(bytes_read<0) { + fprintf(stderr,"new_discover: bytes read %d\n", bytes_read); + perror("new_discover: recvfrom socket failed for discover_receive_thread"); + break; + } + fprintf(stderr,"new_discover: received %d bytes\n",bytes_read); + if(bytes_read==1444) { + if(devices>0) { + break; + } + } else { + if(buffer[0]==0 && buffer[1]==0 && buffer[2]==0 && buffer[3]==0) { + int status = buffer[4] & 0xFF; + if (status == 2 || status == 3) { + if(devices<MAX_DEVICES) { + discovered[devices].protocol=NEW_PROTOCOL; + discovered[devices].device=buffer[11]&0xFF; + discovered[devices].software_version=buffer[13]&0xFF; + discovered[devices].status=status; + switch(discovered[devices].device) { + case NEW_DEVICE_ATLAS: + strcpy(discovered[devices].name,"Atlas"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_HERMES: + strcpy(discovered[devices].name,"Hermes"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_HERMES2: + strcpy(discovered[devices].name,"Hermes2"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_ANGELIA: + strcpy(discovered[devices].name,"Angelia"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_ORION: + strcpy(discovered[devices].name,"Orion"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_ORION2: + strcpy(discovered[devices].name,"Orion2"); + frequency_min=0.0; + frequency_max=61440000.0; + break; + case NEW_DEVICE_HERMES_LITE: + if (discovered[devices].software_version < 40) { + strcpy(discovered[devices].name,"Hermes Lite V1"); + } else { + strcpy(discovered[devices].name,"Hermes Lite V2"); + discovered[devices].device = NEW_DEVICE_HERMES_LITE2; + } + frequency_min=0.0; + frequency_max=30720000.0; + break; + default: + strcpy(discovered[devices].name,"Unknown"); + frequency_min=0.0; + frequency_max=30720000.0; + break; + } + for(i=0;i<6;i++) { + discovered[devices].info.network.mac_address[i]=buffer[i+5]; + } + memcpy((void*)&discovered[devices].info.network.address,(void*)&addr,sizeof(addr)); + discovered[devices].info.network.address_length=sizeof(addr); + memcpy((void*)&discovered[devices].info.network.interface_address,(void*)&interface_addr,sizeof(interface_addr)); + memcpy((void*)&discovered[devices].info.network.interface_netmask,(void*)&interface_netmask,sizeof(interface_netmask)); + discovered[devices].info.network.interface_length=sizeof(interface_addr); + strcpy(discovered[devices].info.network.interface_name,interface_name); + discovered[devices].supported_receivers=2; + fprintf(stderr,"new_discover: found %d protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", + devices, + discovered[devices].protocol, + discovered[devices].device, + discovered[devices].software_version, + discovered[devices].status, + inet_ntoa(discovered[devices].info.network.address.sin_addr), + discovered[devices].info.network.mac_address[0], + discovered[devices].info.network.mac_address[1], + discovered[devices].info.network.mac_address[2], + discovered[devices].info.network.mac_address[3], + discovered[devices].info.network.mac_address[4], + discovered[devices].info.network.mac_address[5], + discovered[devices].info.network.interface_name); + discovered[devices].frequency_min=frequency_min; + discovered[devices].frequency_max=frequency_max; + devices++; + } + } + } + } + } + fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n"); + g_thread_exit(NULL); + return NULL; +} diff --git a/p2_discovery.h b/p2_discovery.h new file mode 100644 index 0000000..9851f22 --- /dev/null +++ b/p2_discovery.h @@ -0,0 +1,25 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _NEW_DISCOVERY_H +#define _NEW_DISCOVERY_H + +void new_discovery(void); + +#endif