2016-05-23 07:46:32 +00:00
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <ctype.h>
2016-09-03 06:32:10 +00:00
# include <stdio.h> // Standard input/output definitions
# include <string.h> // String function definitions
# include <fcntl.h> // File control definitions
2016-09-14 08:13:11 +00:00
# include <unistd.h> // UNIX standard function definitions
2016-09-03 06:32:10 +00:00
# include <errno.h> // Error number definitions
# include <termios.h> // POSIX terminal control definitions
2016-05-23 07:46:32 +00:00
# include <stdint.h>
# include <stdlib.h>
# include <dirent.h>
# include <math.h>
# include <pthread.h>
2016-09-14 08:13:11 +00:00
# include <wiringPi.h>
2016-05-23 07:46:32 +00:00
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include "server.h"
2016-09-14 08:13:11 +00:00
# include "config.h"
2016-05-23 07:46:32 +00:00
# include "global.h"
2018-04-10 23:18:23 +00:00
# include "gateway.h"
2016-05-23 07:46:32 +00:00
extern bool run ;
2017-08-28 13:15:38 +00:00
void EncryptMessage ( char * Code , char * Message )
{
int i , Len ;
Len = strlen ( Code ) ;
if ( Len > 0 )
{
i = 0 ;
while ( * Message )
{
* Message = ( * Message ^ Code [ i ] ) | 0x80 ;
Message + + ;
i = ( i + 1 ) % Len ;
}
}
}
2019-02-27 09:36:18 +00:00
void ProcessChatClientLine ( int connfd , char * line )
{
line [ strcspn ( line , " \r \n " ) ] = ' \0 ' ; // Get rid of CR LF
// LogMessage("Received '%s' from CHAT client\n", line);
if ( strchr ( line , ' : ' ) ! = NULL )
{
// Command with parameters
char * command , * value , * saveptr = NULL ;
command = strtok_r ( line , " : " , & saveptr ) ;
value = strtok_r ( NULL , " \n " , & saveptr ) ;
if ( strcasecmp ( command , " send " ) = = 0 )
{
int channel ;
channel = * value ! = ' 0 ' ;
value + + ;
LogMessage ( " LoRa[%d]: To send '%s' \n " , channel , value ) ;
if ( * Config . UplinkCode )
{
EncryptMessage ( Config . UplinkCode , value ) ;
}
// sprintf(Config.LoRaDevices[channel].UplinkMessage, "!%s,%s", Config.LoRaDevices[channel].ChatPayloadID, value);
if ( Config . LoRaDevices [ channel ] . ChatMode )
{
// Format is [message_id],[message]
sscanf ( value , " %d,%[^ \n ] " , & ( Config . LoRaDevices [ channel ] . TxMessageID ) , Config . LoRaDevices [ channel ] . TxChatMessage ) ;
LogMessage ( " Uplink to payload [%s], message ID [%d], message [%s] \n " , Config . LoRaDevices [ channel ] . ChatPayloadID , Config . LoRaDevices [ channel ] . TxMessageID , Config . LoRaDevices [ channel ] . TxChatMessage ) ;
LogMessage ( " Uplink message is %s \n " , Config . LoRaDevices [ channel ] . UplinkMessage ) ;
}
}
else if ( strcasecmp ( command , " poll " ) = = 0 )
{
char Line [ 300 ] ;
int channel ;
channel = * value ! = ' 0 ' ;
// TxMessageID, Len(TxMessage), RxMessageID, RxMessage
sprintf ( Line , " %d,%d,%d,%s " , Config . LoRaDevices [ channel ] . TxMessageID , strlen ( Config . LoRaDevices [ channel ] . TxChatMessage ) ,
Config . LoRaDevices [ channel ] . RxMessageID , Config . LoRaDevices [ channel ] . RxChatMessage ) ;
send ( connfd , Line , strlen ( Line ) , MSG_NOSIGNAL ) ;
}
}
else
{
// single-word request
}
}
2016-09-27 19:23:41 +00:00
void ProcessJSONClientLine ( int connfd , char * line )
2016-09-14 08:13:11 +00:00
{
line [ strcspn ( line , " \r \n " ) ] = ' \0 ' ; // Get rid of CR LF
2017-08-28 13:15:38 +00:00
LogMessage ( " Received '%s' from JSON client \n " , line ) ;
if ( strchr ( line , ' = ' ) ! = NULL )
{
// Setting
2018-05-01 21:34:14 +00:00
char * setting , * value , * saveptr = NULL ;
2016-09-14 08:13:11 +00:00
2017-08-28 13:15:38 +00:00
setting = strtok_r ( line , " = " , & saveptr ) ;
value = strtok_r ( NULL , " \n " , & saveptr ) ;
SetConfigValue ( setting , value ) ;
2020-06-05 16:24:03 +00:00
if ( strstr ( line , " frequency_0 " ) ! = NULL )
{
Config . LoRaDevices [ 0 ] . FrequencyOffset = 0 ;
}
else if ( strstr ( line , " frequency_1 " ) ! = NULL )
{
Config . LoRaDevices [ 1 ] . FrequencyOffset = 0 ;
}
2017-08-28 13:15:38 +00:00
}
else if ( strchr ( line , ' : ' ) ! = NULL )
{
// Command with parameters
2018-05-01 21:34:14 +00:00
char * command , * value , * saveptr = NULL ;
2017-08-28 13:15:38 +00:00
command = strtok_r ( line , " : " , & saveptr ) ;
value = strtok_r ( NULL , " \n " , & saveptr ) ;
if ( strcasecmp ( command , " send " ) = = 0 )
{
2017-10-01 10:07:54 +00:00
int channel ;
channel = * value ! = ' 0 ' ;
value + + ;
LogMessage ( " LoRa[%d]: To send '%s' \n " , channel , value ) ;
2017-08-28 13:15:38 +00:00
2018-11-21 11:03:31 +00:00
if ( * Config . UplinkCode )
{
2022-02-02 11:34:09 +00:00
EncryptMessage ( Config . UplinkCode , value + 1 ) ;
2018-11-21 11:03:31 +00:00
}
2017-08-28 13:15:38 +00:00
2017-10-01 10:07:54 +00:00
strcpy ( Config . LoRaDevices [ channel ] . UplinkMessage , value ) ;
2017-08-28 13:15:38 +00:00
}
}
else
2016-09-14 08:13:11 +00:00
{
2017-08-28 13:15:38 +00:00
// single-word request
2018-04-10 16:54:46 +00:00
2016-09-14 08:13:11 +00:00
if ( strcasecmp ( line , " settings " ) = = 0 )
{
int Index ;
char SettingName [ 64 ] , SettingValue [ 256 ] , packet [ 4096 ] ;
LogMessage ( " Responding to settings request \n " ) ;
Index = 0 ;
packet [ 0 ] = ' \0 ' ;
while ( SettingAsString ( Index , SettingName , sizeof ( SettingName ) , SettingValue , sizeof ( SettingValue ) ) )
{
char temp [ 300 ] ;
sprintf ( temp , " { \" class \" : \" SET \" , \" set \" : \" %s \" , \" val \" :%s} \r \n " , SettingName , SettingValue ) ;
if ( ( strlen ( temp ) + strlen ( packet ) ) < sizeof ( packet ) )
{
strcat ( packet , temp ) ;
}
Index + + ;
}
send ( connfd , packet , strlen ( packet ) , MSG_NOSIGNAL ) ;
}
2019-02-27 09:36:18 +00:00
else if ( strcasecmp ( line , " poll " ) = = 0 )
{
char Line [ 300 ] ;
sprintf ( Line , " 1/ " ) ;
send ( connfd , Line , strlen ( Line ) , MSG_NOSIGNAL ) ;
}
2016-09-14 08:13:11 +00:00
else if ( strcasecmp ( line , " save " ) = = 0 )
{
LogMessage ( " Saving Settings \n " ) ;
SaveConfigFile ( ) ;
}
}
}
2016-09-27 19:23:41 +00:00
int SendJSON ( int connfd )
{
2018-04-10 23:18:23 +00:00
int Channel , PayloadIndex , port_closed ;
char sendBuff [ 4000 ] , line [ 400 ] ;
2016-09-27 19:23:41 +00:00
port_closed = 0 ;
2018-04-10 23:18:23 +00:00
sendBuff [ 0 ] = ' \0 ' ;
2016-09-27 19:23:41 +00:00
2018-04-10 23:18:23 +00:00
// Send any packets that we've not sent yet
2016-10-16 16:05:37 +00:00
for ( PayloadIndex = 0 ; PayloadIndex < MAX_PAYLOADS ; PayloadIndex + + )
2019-05-09 11:16:20 +00:00
{
2018-04-10 16:54:46 +00:00
if ( Config . Payloads [ PayloadIndex ] . InUse & & Config . Payloads [ PayloadIndex ] . SendToClients )
2016-09-27 19:23:41 +00:00
{
2019-05-09 11:16:20 +00:00
2018-04-10 23:18:23 +00:00
Channel = Config . Payloads [ PayloadIndex ] . Channel ;
sprintf ( line , " { \" class \" : \" POSN \" , \" index \" :%d, \" channel \" :%d, \" payload \" : \" %s \" , \" time \" : \" %s \" , \" lat \" :%.5lf, \" lon \" :%.5lf, \" alt \" :%d, \" rate \" :%.1lf, \" snr \" :%d, \" rssi \" :%d, \" ferr \" :%.1lf, \" sentence \" : \" %s \" } \r \n " ,
2016-10-16 16:05:37 +00:00
PayloadIndex ,
2018-04-10 23:18:23 +00:00
Channel ,
2016-10-16 16:05:37 +00:00
Config . Payloads [ PayloadIndex ] . Payload ,
Config . Payloads [ PayloadIndex ] . Time ,
Config . Payloads [ PayloadIndex ] . Latitude ,
Config . Payloads [ PayloadIndex ] . Longitude ,
Config . Payloads [ PayloadIndex ] . Altitude ,
2017-08-28 13:15:38 +00:00
Config . Payloads [ PayloadIndex ] . AscentRate ,
2018-04-10 23:18:23 +00:00
Config . LoRaDevices [ Channel ] . PacketSNR ,
Config . LoRaDevices [ Channel ] . PacketRSSI ,
Config . LoRaDevices [ Channel ] . FrequencyError ,
2017-08-28 13:15:38 +00:00
Config . Payloads [ PayloadIndex ] . Telemetry ) ;
2016-09-27 19:23:41 +00:00
2018-04-10 23:18:23 +00:00
strcat ( sendBuff , line ) ;
Config . Payloads [ PayloadIndex ] . SendToClients = 0 ;
}
}
// Send Channel Status (RSSI only at present)
for ( Channel = 0 ; Channel < = 1 ; Channel + + )
{
if ( Config . LoRaDevices [ Channel ] . InUse )
{
2020-06-05 18:37:32 +00:00
sprintf ( line , " { \" class \" : \" STATS \" , \" index \" :%d, \" rssi \" :%d, \" freq \" :%.4lf} \r \n " ,
2018-04-10 23:18:23 +00:00
Channel ,
2020-06-05 18:37:32 +00:00
Config . LoRaDevices [ Channel ] . CurrentRSSI ,
Config . LoRaDevices [ Channel ] . Frequency + Config . LoRaDevices [ Channel ] . FrequencyOffset ) ;
2018-04-10 23:18:23 +00:00
strcat ( sendBuff , line ) ;
}
}
if ( ! run )
{
port_closed = 1 ;
}
else if ( sendBuff [ 0 ] )
{
if ( send ( connfd , sendBuff , strlen ( sendBuff ) , MSG_NOSIGNAL ) < = 0 )
{
LogMessage ( " Disconnected from client \n " ) ;
port_closed = 1 ;
2016-09-27 19:23:41 +00:00
}
}
return port_closed ;
}
2016-10-16 16:09:46 +00:00
2016-09-03 06:32:10 +00:00
void * ServerLoop ( void * some_void_ptr )
2016-05-23 07:46:32 +00:00
{
2019-02-27 09:36:18 +00:00
static char * ChannelName [ 4 ] = { " JSON " , " HAB " , " DATA " , " CHAT " } ;
2016-09-03 06:32:10 +00:00
struct sockaddr_in serv_addr ;
2016-09-27 19:23:41 +00:00
struct TServerInfo * ServerInfo ;
ServerInfo = ( struct TServerInfo * ) some_void_ptr ;
2016-05-23 07:46:32 +00:00
2016-09-27 19:23:41 +00:00
ServerInfo - > sockfd = socket ( AF_INET , SOCK_STREAM , 0 ) ;
2016-09-03 06:32:10 +00:00
memset ( & serv_addr , ' 0 ' , sizeof ( serv_addr ) ) ;
2016-05-23 07:46:32 +00:00
serv_addr . sin_family = AF_INET ;
2016-09-03 06:32:10 +00:00
serv_addr . sin_addr . s_addr = htonl ( INADDR_ANY ) ;
2016-09-27 19:23:41 +00:00
serv_addr . sin_port = htons ( ServerInfo - > Port ) ;
2016-05-23 07:46:32 +00:00
2018-03-26 11:59:38 +00:00
LogMessage ( " Listening on %s port %d \n " , ChannelName [ ServerInfo - > ServerIndex ] , ServerInfo - > Port ) ;
2016-09-03 06:32:10 +00:00
2016-09-27 19:23:41 +00:00
if ( setsockopt ( ServerInfo - > sockfd , SOL_SOCKET , SO_REUSEADDR , & ( int ) { 1 } , sizeof ( int ) ) < 0 )
{
2016-09-03 06:32:10 +00:00
LogMessage ( " setsockopt(SO_REUSEADDR) failed " ) ;
}
2016-09-27 19:23:41 +00:00
if ( bind ( ServerInfo - > sockfd , ( struct sockaddr * ) & serv_addr , sizeof ( serv_addr ) ) < 0 )
2016-05-23 07:46:32 +00:00
{
2016-09-03 06:32:10 +00:00
LogMessage ( " Server failed errno %d \n " , errno ) ;
exit ( - 1 ) ;
}
2016-09-27 19:23:41 +00:00
listen ( ServerInfo - > sockfd , 10 ) ;
2016-09-14 08:13:11 +00:00
2016-09-27 19:23:41 +00:00
while ( run )
2016-05-23 07:46:32 +00:00
{
2019-02-27 09:36:18 +00:00
static char * ChannelName [ 4 ] = { " JSON " , " HAB " , " DATA " , " CHAT " } ;
2016-09-14 08:13:11 +00:00
int MSPerLoop = 100 ;
2016-09-27 19:23:41 +00:00
int ms = 0 ;
int connfd ;
Config . EnableDev = 1 ;
2016-09-03 06:32:10 +00:00
2016-09-27 19:23:41 +00:00
fcntl ( ServerInfo - > sockfd , F_SETFL , fcntl ( ServerInfo - > sockfd , F_GETFL ) & ~ O_NONBLOCK ) ; // Blocking mode so we wait for a connection
2016-09-14 08:13:11 +00:00
2016-09-27 19:23:41 +00:00
connfd = accept ( ServerInfo - > sockfd , ( struct sockaddr * ) NULL , NULL ) ; // Wait for connection
2016-09-03 06:32:10 +00:00
2018-03-26 11:59:38 +00:00
LogMessage ( " Connected to %s client \n " , ChannelName [ ServerInfo - > ServerIndex ] ) ;
2016-09-27 19:23:41 +00:00
ServerInfo - > Connected = 1 ;
2016-09-03 06:32:10 +00:00
2016-09-27 19:23:41 +00:00
fcntl ( connfd , F_SETFL , fcntl ( ServerInfo - > sockfd , F_GETFL ) | O_NONBLOCK ) ; // Non-blocking, so we don't block on receiving any commands from client
2016-09-14 08:13:11 +00:00
2016-09-27 19:23:41 +00:00
while ( ServerInfo - > Connected )
2016-09-03 06:32:10 +00:00
{
2016-09-27 19:23:41 +00:00
int bytecount ;
2016-09-14 08:13:11 +00:00
2016-09-27 19:23:41 +00:00
ms + = MSPerLoop ;
// Listen part
bytecount = - 1 ;
2017-09-01 10:52:52 +00:00
if ( ServerInfo - > ServerIndex = = 0 )
2016-09-14 08:13:11 +00:00
{
2018-04-10 16:54:46 +00:00
static char lines [ 4096 ] ;
2017-09-01 10:52:52 +00:00
char packet [ 4096 ] ;
2016-09-27 19:23:41 +00:00
2017-09-01 10:52:52 +00:00
while ( ( bytecount = recv ( connfd , packet , sizeof ( packet ) , 0 ) ) > 0 )
{
2018-04-10 16:54:46 +00:00
// JSON server
char * lf ;
2017-09-01 10:52:52 +00:00
packet [ bytecount ] = 0 ;
2018-04-10 16:54:46 +00:00
strcat ( lines , packet ) ;
2017-09-01 10:52:52 +00:00
2018-04-10 16:54:46 +00:00
while ( ( lf = strchr ( lines , ' \n ' ) ) ! = NULL )
2017-09-01 10:52:52 +00:00
{
2018-04-10 16:54:46 +00:00
// Terminate string
* lf = ' \0 ' ;
// Process this line
ProcessJSONClientLine ( connfd , lines ) ;
// Shift any other lines over
strcpy ( lines , lf + 1 ) ;
2017-09-01 10:52:52 +00:00
}
}
if ( bytecount = = 0 )
{
// -1 is no more data, 0 means port closed
ServerInfo - > Connected = 0 ;
}
}
2018-03-26 11:59:38 +00:00
else if ( ServerInfo - > ServerIndex = = 1 )
2017-09-01 10:52:52 +00:00
{
char RxByte ;
2016-09-14 08:13:11 +00:00
2017-09-01 10:52:52 +00:00
while ( ( bytecount = recv ( connfd , & RxByte , 1 , 0 ) ) > 0 )
2016-09-14 08:13:11 +00:00
{
2017-09-01 10:52:52 +00:00
Config . LoRaDevices [ Config . HABChannel ] . FromTelnetBuffer [ Config . LoRaDevices [ Config . HABChannel ] . FromTelnetBufferCount + + ] = RxByte ;
LogMessage ( " KEYB BUFFER %d BYTES \n " , Config . LoRaDevices [ Config . HABChannel ] . FromTelnetBufferCount ) ;
2016-09-14 08:13:11 +00:00
}
}
2018-03-26 11:59:38 +00:00
else if ( ServerInfo - > ServerIndex = = 2 )
{
char RxByte ;
while ( ( bytecount = recv ( connfd , & RxByte , 1 , 0 ) ) > 0 )
{
// Nothing as we are only sending
}
}
2019-02-27 09:36:18 +00:00
else if ( ServerInfo - > ServerIndex = = 3 )
{
char packet [ 300 ] ;
while ( ( bytecount = recv ( connfd , packet , sizeof ( packet ) , 0 ) ) > 0 )
{
packet [ bytecount ] = 0 ;
ProcessChatClientLine ( connfd , packet ) ;
}
if ( bytecount = = 0 )
{
// -1 is no more data, 0 means port closed
ServerInfo - > Connected = 0 ;
}
}
2016-09-27 19:23:41 +00:00
if ( bytecount = = 0 )
2016-05-23 07:46:32 +00:00
{
2016-09-27 19:23:41 +00:00
// -1 is no more data, 0 means port closed
2019-02-27 09:36:18 +00:00
LogMessage ( " Disconnected from %s client \n " , ChannelName [ ServerInfo - > ServerIndex ] ) ;
2016-09-27 19:23:41 +00:00
ServerInfo - > Connected = 0 ;
}
2016-09-03 06:32:10 +00:00
2016-09-27 19:23:41 +00:00
if ( ServerInfo - > Connected )
{
2017-09-01 10:52:52 +00:00
// Send part
if ( ServerInfo - > ServerIndex = = 0 )
2016-09-03 06:32:10 +00:00
{
2017-09-01 10:52:52 +00:00
// Send to JSON client
2019-05-09 10:09:30 +00:00
static int SendDelay = 0 ;
if ( ( SendDelay + = MSPerLoop ) > = 1000 )
2016-09-27 19:23:41 +00:00
{
2019-05-09 10:09:30 +00:00
SendDelay = 0 ;
if ( SendJSON ( connfd ) )
{
ServerInfo - > Connected = 0 ;
}
2016-09-27 19:23:41 +00:00
}
2017-09-01 10:52:52 +00:00
}
2018-03-26 11:59:38 +00:00
else if ( ServerInfo - > ServerIndex = = 1 )
2017-09-01 10:52:52 +00:00
{
2018-04-10 16:54:46 +00:00
// Telnet port (provides Telnet-like connection to HAB)
2017-09-01 10:52:52 +00:00
int Channel ;
for ( Channel = 0 ; Channel < = 1 ; Channel + + )
{
if ( Config . LoRaDevices [ Channel ] . ToTelnetBufferCount > 0 )
{
send ( connfd , Config . LoRaDevices [ Channel ] . ToTelnetBuffer , Config . LoRaDevices [ Channel ] . ToTelnetBufferCount , 0 ) ;
Config . LoRaDevices [ Channel ] . ToTelnetBufferCount = 0 ;
}
}
2018-03-26 11:59:38 +00:00
}
else if ( ServerInfo - > ServerIndex = = 2 )
{
2018-04-10 16:54:46 +00:00
// Direct telemetry port
2018-03-26 11:59:38 +00:00
int Channel ;
for ( Channel = 0 ; Channel < = 1 ; Channel + + )
{
if ( Config . LoRaDevices [ Channel ] . LocalDataCount > 0 )
{
send ( connfd , Config . LoRaDevices [ Channel ] . LocalDataBuffer , Config . LoRaDevices [ Channel ] . LocalDataCount , 0 ) ;
Config . LoRaDevices [ Channel ] . LocalDataCount = 0 ;
}
}
2016-09-03 06:32:10 +00:00
}
2016-05-23 07:46:32 +00:00
}
2016-09-27 19:23:41 +00:00
delay ( MSPerLoop ) ;
2016-09-03 06:32:10 +00:00
}
2016-09-27 19:23:41 +00:00
close ( connfd ) ;
2016-09-03 06:32:10 +00:00
}
2016-05-23 07:46:32 +00:00
2016-09-03 06:32:10 +00:00
return NULL ;
}