Skip to content

Commit

Permalink
Re-worked TCP support.
Browse files Browse the repository at this point in the history
  • Loading branch information
c vw committed Feb 9, 2019
1 parent 4fa7ca7 commit 0399b9a
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 165 deletions.
2 changes: 2 additions & 0 deletions discovered.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
struct _DISCOVERED {
int protocol;
int device;
int can_tcp; // Radio can do UDP but is able to switch to TCP
int only_tcp; // Radio can only be reached via TCP, UDP does not work
char name[64];
int software_version;
int status;
Expand Down
22 changes: 13 additions & 9 deletions discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,18 @@ fprintf(stderr,"start_cb: %p\n",data);
const int device_id = radio - discovered;
int ret;
ret=stemlab_start_app(gtk_combo_box_get_active_id(GTK_COMBO_BOX(apps_combobox[device_id])));
#ifdef NO_AVAHI
// We only have started the app, but not queried e.g. the MAC address.
// Therefore, we have to clean up and re-start the discovery process.
stemlab_cleanup();
gtk_widget_destroy(discovery_dialog);
g_idle_add(ext_discovery,NULL);
return TRUE;
#endif
//
// We have started the SDR app on the RedPitaya, but may need to fill
// in information necessary for starting the radio, including the
// MAC address and the interface listening to. Even when using AVAHI,
// we miss some information (can_tcp, METIS vs. HERMES, etc).
// To get all required info, we do a "fake" discovery on the RedPitaya IP address.
// Here we also try TCP if UDP does not work, such that we can work with STEMlabs
// in remote subnets.
//
if (ret == 0) {
ret=stemlab_get_info(device_id);
}
// At this point, if stemlab_start_app failed, we cannot recover
if (ret != 0) exit(-1);
}
Expand Down Expand Up @@ -252,7 +256,7 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
#ifdef STEMLAB_DISCOVERY
case STEMLAB_PROTOCOL:
#ifdef NO_AVAHI
sprintf(text,"Choose App from %s and re-Discover:",inet_ntoa(d->info.network.address.sin_addr));
sprintf(text,"Choose RedPitaya App from %s and start radio:",inet_ntoa(d->info.network.address.sin_addr));
#else
sprintf(text, "STEMlab (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
d->info.network.mac_address[0],
Expand Down
149 changes: 146 additions & 3 deletions old_discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,138 @@ static void discover(struct ifaddrs* iface) {

}

#ifdef STEMLAB_DISCOVERY
//
// We have just started the SDR app on the RedPitaya without using AVAHI.
// Therefore we must send a discovery packet and analyze its response
// to have all information to start the radio.
// Since this essentially what happens in the original discovery process,
// we put this function HERE and not into stemlab_discovery.c
//
int stemlab_get_info(int id) {
int ret;
unsigned char buffer[1032];
int optval,i;

// Allow RP app to come up
sleep(2);

devices=id;

discovery_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (discovery_socket < 0) return(1);

optval = 1;
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));

memset(&discovery_addr, 0, sizeof(discovery_addr));
discovery_addr.sin_family=AF_INET;
discovery_addr.sin_addr.s_addr=htonl(INADDR_ANY);
discovery_addr.sin_port=htons(DISCOVERY_PORT);
ret=bind(discovery_socket, (struct sockaddr *)&discovery_addr, sizeof(discovery_addr));
if (ret < 0) {
perror("BIND FAILED:");
return 1;
}

// 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 )
{
fprintf(stderr,"g_thread_new failed on discover_receive_thread\n");
return 1;
}

// send discovery packet
buffer[0]=0xEF;
buffer[1]=0xFE;
buffer[2]=0x02;
for(i=3;i<63;i++) {
buffer[i]=0x00;
}

ret=sendto(discovery_socket,buffer,63,0,
(struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 63) {
perror("SEND DISCOVERY PACKET:");
return -1;
}

// wait for receive thread to complete
g_thread_join(discover_thread_id);

close(discovery_socket);

// if all went well, we have now filled in data for exactly
// one device.
if (devices == id+1) return 0;

if (devices > id+1) return 1;

// If we have not received an answer, then possibly the STEMlab is located
// on a different subnet and UDP packets are not correctly routed through.
// In this case, we try to open a connection using TCP.

discovery_socket = socket(AF_INET, SOCK_STREAM, 0);
if (discovery_socket < 0) {
perror("TCP socket:");
return 1;
}

optval = 1;
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
ret=connect(discovery_socket, (struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 0) {
perror("TCP connect:");
return 1;
}

// send discovery packet
buffer[0]=0xEF;
buffer[1]=0xFE;
buffer[2]=0x02;
for(i=3;i<1032;i++) {
buffer[i]=0x00;
}

// 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 )
{
fprintf(stderr,"g_thread_new failed on discover_receive_thread\n");
return 1;
}

ret=sendto(discovery_socket,buffer,1032,0,
(struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 1032) {
perror("SEND DISCOVERY PACKET:");
return -1;
}

// wait for receive thread to complete
g_thread_join(discover_thread_id);

close(discovery_socket);

// if all went well, we have now filled in data for exactly
// one device. We must set a flag that this one can ONLY do
// TCP
if (devices == id+1) {
fprintf(stderr,"UDP did not work, but TCP does!\n");
discovered[id].only_tcp=1;
discovered[id].can_tcp=0;
return 0;
}
return 1;
}
#endif

//static void *discover_receive_thread(void* arg) {
static gpointer discover_receive_thread(gpointer data) {
struct sockaddr_in addr;
Expand All @@ -149,12 +281,13 @@ fprintf(stderr,"discover_receive_thread\n");

len=sizeof(addr);
while(1) {
bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len);
bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),1032,(struct sockaddr*)&addr,&len);
if(bytes_read<0) {
fprintf(stderr,"discovery: bytes read %d\n", bytes_read);
perror("discovery: recvfrom socket failed for discover_receive_thread");
break;
}
if (bytes_read == 0) break;
fprintf(stderr,"Old Protocol discovered: received %d bytes\n",bytes_read);
if ((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) {
int status = buffer[2] & 0xFF;
Expand Down Expand Up @@ -190,7 +323,8 @@ fprintf(stderr,"discover_receive_thread\n");
strcpy(discovered[devices].name,"Orion 2");
break;
case DEVICE_STEMLAB:
// In most respects similar to HERMES, but this indicates TCP capability
// This is in principle the same as HERMES so pretend a HERMES
discovered[devices].device = DEVICE_HERMES;
strcpy(discovered[devices].name,"STEMlab");
break;
default:
Expand All @@ -208,8 +342,17 @@ fprintf(stderr,"discover_receive_thread\n");
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);
fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
//
// some devices report TCP capability here
//
discovered[devices].only_tcp=0;
discovered[devices].can_tcp=0;
if (buffer[11] == 'T' && buffer[12] == 'C' && buffer[13]=='P') {
discovered[devices].can_tcp=1;
}
fprintf(stderr,"discovery: found device=%d CanTCP=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
discovered[devices].device,
discovered[devices].can_tcp,
discovered[devices].software_version,
discovered[devices].status,
inet_ntoa(discovered[devices].info.network.address.sin_addr),
Expand Down
3 changes: 3 additions & 0 deletions old_discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@
#define _OLD_DISCOVERY_H

void old_discovery(void);
#ifdef STEMLAB_DISCOVERY
int stemlab_get_info(int id);
#endif

#endif
Loading

0 comments on commit 0399b9a

Please sign in to comment.