drop in replacement for nonfunctioning "discover_netsdr"

dale ranta daleranta at icloud.com
Mon Mar 5 17:02:18 UTC 2018


The module “discover_netsdr” in “rfspace_source_c.cc” failed everywhere that I tried it, except for MacOS 10.6. Here is a drop in replacement that was tested and found to work on 10.6, 10.11, 10.12, 10.13 and ubuntu 16.04 LTS.




#include <net/if.h>
#include <ifaddrs.h>

class interfaceInformation{

public:
	std::string name;
	std::string address;
	std::string broadcast;
};

std::vector<interfaceInformation> interfaceList();


static std::vector < unit_t > discover_netsdr()
{
	std::vector < unit_t > units;
	  
  	std::vector<interfaceInformation> list=interfaceList();
  	
  	for(int pass=0;pass<2;++pass){
		for(size_t n=0;n<list.size();++n){
			if(pass == 1){
				list[n].broadcast="255.255.255.255";
			}
			//std::cout << "name " <<  list[n].name << std::endl;
			//std::cout << "address " <<  list[n].address << std::endl;
			//std::cout << "broadcast " <<  list[n].broadcast << std::endl;

			int sockTx;
			int sockRx;
  

		  if ( (sockTx = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
			continue;
	
		  if ( (sockRx = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
			close(sockTx);	  
			continue;
		   }
	   
		  int sockoptval = 1;
		  setsockopt(sockTx, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int));
		  sockoptval = 1;
		  setsockopt(sockTx, SOL_SOCKET, SO_BROADCAST, &sockoptval, sizeof(int));


		  struct sockaddr_in host_sa; /* local address */
		  struct sockaddr_in peer_sa; /* remote address */
		  struct sockaddr_in peer_sa2; /* remote address */

		  /* fill in the server's address and data */
		  memset((char*)&peer_sa, 0, sizeof(peer_sa));
		  peer_sa.sin_family = AF_INET;
		  peer_sa.sin_addr.s_addr = htonl(inet_network(list[n].address.c_str()));
		  peer_sa.sin_port = htons(DISCOVER_SERVER_PORT);
  
  
		  /* fill in the server's address and data */
		  memset((char*)&peer_sa2, 0, sizeof(peer_sa2));
		  peer_sa2.sin_family = AF_INET;
		  peer_sa2.sin_addr.s_addr = htonl(inet_network(list[n].broadcast.c_str()));
		  peer_sa2.sin_port = htons(DISCOVER_SERVER_PORT);
  
  

		  /* fill in the hosts's address and data */
		  memset(&host_sa, 0, sizeof(host_sa));
		  host_sa.sin_family = AF_INET;
		  host_sa.sin_addr.s_addr = htonl(INADDR_ANY);
		  host_sa.sin_port = htons(DISCOVER_CLIENT_PORT);
  
  
		   if ( bind(sockTx, (struct sockaddr *)&peer_sa, sizeof(peer_sa)) < 0 )
		  {
			close(sockTx);
			close(sockRx);
			continue;
		  }

		   if ( bind(sockRx, (struct sockaddr *)&host_sa, sizeof(host_sa)) < 0 )
		  {
			perror("binding datagram sock2");
			printf("errno %d DISCOVER_SERVER_PORT %d\n",errno,DISCOVER_SERVER_PORT);
			close(sockTx);
			close(sockRx);
			continue;
		  }

		  struct timeval tv;

		  tv.tv_sec = 0;
		  tv.tv_usec = 100000;
		  if ( setsockopt(sockRx, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 )
		  {
			close(sockRx);
			close(sockTx);
			continue;
		  }

		  discover_common_msg_t tx_msg;
		  memset( (void *)&tx_msg, 0, sizeof(discover_common_msg_t) );

		  tx_msg.length[0] = sizeof(discover_common_msg_t);
		  tx_msg.length[1] = sizeof(discover_common_msg_t) >> 8;
		  tx_msg.key[0] = KEY0;
		  tx_msg.key[1] = KEY1;
		  tx_msg.op = MSG_REQ;
 
		  sendto(sockTx, &tx_msg, sizeof(tx_msg), 0, (struct sockaddr *)&peer_sa, sizeof(peer_sa));
		  sendto(sockTx, &tx_msg, sizeof(tx_msg), 0, (struct sockaddr *)&peer_sa2, sizeof(peer_sa2));
  
		  while ( 1 )
		  {
				size_t rx_bytes = 0;
				unsigned char data[1024*2];

				socklen_t addrlen = sizeof(host_sa);  /* length of addresses */
		
				int nbytes = recvfrom(sockRx, data, sizeof(data), 0, (struct sockaddr *)&host_sa, &addrlen);
		
				if ( nbytes <= 0 )
					break;
				rx_bytes = nbytes;
		
		
				if ( rx_bytes >= sizeof(discover_common_msg_t) )
				{
					discover_common_msg_t *rx_msg = (discover_common_msg_t *)data;

					if ( KEY0 == rx_msg->key[0] && KEY1 == rx_msg->key[1]  &&
					   MSG_RESP == rx_msg->op )
					{					
					
						void *temp = rx_msg->port;
						uint16_t port = *((uint16_t *)temp);
					
						std::stringstream buffer;
					
						buffer << int(rx_msg->ipaddr[3]) << "."
							   << int(rx_msg->ipaddr[2]) << "."
							   << int(rx_msg->ipaddr[1]) << "."
							   << int(rx_msg->ipaddr[0]);
						   
						   
						std::string addr=buffer.str();
						   
						//std::cout << "addr " << addr << std::endl;

						unit_t unit;

						unit.name = rx_msg->name;
						unit.sn = rx_msg->sn;
						unit.addr = addr;
						unit.port = port;

						units.push_back( unit );
					
					}
				}
		
			}
		
			close(sockTx);
			close(sockRx);
	  }
	}
	return units;
}


std::vector<interfaceInformation> interfaceList()
{
	std::vector<interfaceInformation> list;
	interfaceInformation c1;
	
	struct ifaddrs *addrs,*iloop; 
	char buf[64],buf2[64];
	struct sockaddr_in *s4;
	
	getifaddrs(&addrs);
	for (iloop = addrs; iloop != NULL; iloop = iloop->ifa_next)
	{
		s4 = (struct sockaddr_in *)(iloop->ifa_addr);
		buf[0]=0;
		if(s4){
			inet_ntop(iloop->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf));
		}else{
			continue;
		}
		
		s4 = (struct sockaddr_in *)(iloop->ifa_dstaddr);
		buf2[0]=0;
		if(s4){
			inet_ntop(iloop->ifa_dstaddr->sa_family, (void *)&(s4->sin_addr), buf2, sizeof(buf2));
		}else{
			continue;
		}
			
		if(!(iloop->ifa_flags & IFF_UP) || !(iloop->ifa_flags & IFF_BROADCAST))continue;		
		
		c1.name = iloop->ifa_name;
		
		c1.address = buf;
		
		c1.broadcast = buf2;
		
		list.push_back(c1);
		
	}  
	
	freeifaddrs(addrs);
	
	return list;
}







More information about the osmocom-sdr mailing list