From 1f9310b79e657dcaaa4106602809d7fee57a3159 Mon Sep 17 00:00:00 2001 From: Angus Ainslie Date: Wed, 25 Jan 2017 14:29:31 +0000 Subject: [PATCH] Add multiple client support to kiss TCP ports. This only works on Linux ( and probably other POSIX platforms ) as I don't think Windows has select. --- kissnet.c | 239 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 156 insertions(+), 83 deletions(-) diff --git a/kissnet.c b/kissnet.c index e377657..8b3ab28 100644 --- a/kissnet.c +++ b/kissnet.c @@ -2,6 +2,7 @@ // This file is part of Dire Wolf, an amateur radio packet TNC. // // Copyright (C) 2011-2014, 2015 John Langner, WB2OSZ +// Copyright (C) 2016 Angus Ainslie angus at akkea.ca, VE6GUS // // 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 @@ -128,15 +129,21 @@ #include "kiss_frame.h" #include "xmit.h" +// TODO: no idea how to do this on windows +#if __WIN32__ +#define MAX_NET_CLIENTS 1 +#else +#define MAX_NET_CLIENTS 4 +#endif -static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */ - // TODO: multiple instances if multiple KISS network clients! +static kiss_frame_t kf[MAX_NET_CLIENTS]; /* Accumulated KISS frame and state of decoder. */ + // TODO: multiple instances if multiple KISS network clients! -static int client_sock; /* File descriptor for socket for */ - /* communication with client application. */ - /* Set to -1 if not connected. */ - /* (Don't use SOCKET type because it is unsigned.) */ +static int client_sock[MAX_NET_CLIENTS]; /* File descriptor for socket for */ + /* communication with client application. */ + /* Set to -1 if not connected. */ + /* (Don't use SOCKET type because it is unsigned.) */ static void * connect_listen_thread (void *arg); @@ -187,6 +194,7 @@ void kissnet_init (struct misc_config_s *mc) #endif int e; int kiss_port = mc->kiss_port; + int i; #if DEBUG @@ -194,9 +202,10 @@ void kissnet_init (struct misc_config_s *mc) dw_printf ("kissnet_init ( %d )\n", kiss_port); #endif - memset (&kf, 0, sizeof(kf)); - - client_sock = -1; + for( i=0; i 0) { - SLEEP_SEC(1); /* Already connected. Try again later. */ + i = 0 + while (client_sock[i] > 0) { + if(( ++i % MAX_NET_CLIENTS ) == 0 ) { + SLEEP_SEC(1); /* All clients already connected. Try again later. */ + i = 0 ; + } } #define QUEUE_SIZE 5 @@ -359,9 +372,9 @@ static void * connect_listen_thread (void *arg) text_color_set(DW_COLOR_INFO); dw_printf("Ready to accept KISS client application on port %s ...\n", kiss_port_str); - client_sock = accept(listen_sock, NULL, NULL); + client_sock[i] = accept(listen_sock, NULL, NULL); - if (client_sock == -1) { + if (client_sock[i] == -1) { text_color_set(DW_COLOR_ERROR); dw_printf("Accept failed with error: %d\n", WSAGetLastError()); closesocket(listen_sock); @@ -383,6 +396,7 @@ static void * connect_listen_thread (void *arg) int kiss_port = (int)(long)arg; int listen_sock; int bcopt = 1; + int i; listen_sock= socket(AF_INET,SOCK_STREAM,0); if (listen_sock == -1) { @@ -409,12 +423,12 @@ static void * connect_listen_thread (void *arg) #endif if (bind(listen_sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)) == -1) { - text_color_set(DW_COLOR_ERROR); - dw_printf("Bind failed with error: %d\n", errno); - dw_printf("%s\n", strerror(errno)); - dw_printf("Some other application is probably already using port %d.\n", kiss_port); - dw_printf("Try using a different port number with KISSPORT in the configuration file.\n"); - return (NULL); + text_color_set(DW_COLOR_ERROR); + dw_printf("Bind failed with error: %d\n", errno); + dw_printf("%s\n", strerror(errno)); + dw_printf("Some other application is probably already using port %d.\n", kiss_port); + dw_printf("Try using a different port number with KISSPORT in the configuration file.\n"); + return (NULL); } getsockname( listen_sock, (struct sockaddr *)(&sockaddr), &sockaddr_size); @@ -426,8 +440,12 @@ static void * connect_listen_thread (void *arg) while (1) { - while (client_sock > 0) { - SLEEP_SEC(1); /* Already connected. Try again later. */ + i = 0; + while (client_sock[i] > 0) { + if(( ++i % MAX_NET_CLIENTS ) == 0 ) { + i = 0; + SLEEP_SEC(1); /* Already connected. Try again later. */ + } } #define QUEUE_SIZE 5 @@ -440,12 +458,12 @@ static void * connect_listen_thread (void *arg) } text_color_set(DW_COLOR_INFO); - dw_printf("Ready to accept KISS client application on port %d ...\n", kiss_port); + dw_printf("Ready to accept KISS client %d application on port %d ...\n", i, kiss_port); - client_sock = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size); + client_sock[i] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size); text_color_set(DW_COLOR_INFO); - dw_printf("\nConnected to KISS client application ...\n\n"); + dw_printf("\nConnected to KISS client %d application on fd %d...\n\n", i, client_sock[i] ); } #endif @@ -483,64 +501,66 @@ void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen) int kiss_len; int j; int err; + int i; + + for( i = 0; i= 2) { + /* AX.25 frame with the CRC removed. */ + text_color_set(DW_COLOR_DEBUG); + dw_printf ("\n"); + dw_printf ("Packet content before adding KISS framing and any escapes:\n"); + hex_dump (fbuf, flen); + } - stemp[0] = (chan << 4) + 0; - memcpy (stemp+1, fbuf, flen); + kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff); - if (kiss_debug >= 2) { - /* AX.25 frame with the CRC removed. */ - text_color_set(DW_COLOR_DEBUG); - dw_printf ("\n"); - dw_printf ("Packet content before adding KISS framing and any escapes:\n"); - hex_dump (fbuf, flen); - } + /* This has the escapes and the surrounding FENDs. */ - kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff); - - /* This has the escapes and the surrounding FENDs. */ - - if (kiss_debug) { - kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len); - } - } + if (kiss_debug) { + kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len); + } + } #if __WIN32__ - err = send (client_sock, (char*)kiss_buff, kiss_len, 0); - if (err == SOCKET_ERROR) - { - text_color_set(DW_COLOR_ERROR); - dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError()); - closesocket (client_sock); - client_sock = -1; - WSACleanup(); - } + err = send (client_sock[i], (char*)kiss_buff, kiss_len, 0); + if (err == SOCKET_ERROR) + { + text_color_set(DW_COLOR_ERROR); + dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError()); + closesocket (client_sock[i]); + client_sock[i] = -1; + WSACleanup(); + } #else - err = write (client_sock, kiss_buff, kiss_len); - if (err <= 0) - { - text_color_set(DW_COLOR_ERROR); - dw_printf ("\nError sending message to KISS client application. Closing connection.\n\n"); - close (client_sock); - client_sock = -1; + err = write (client_sock[i], kiss_buff, kiss_len); + if (err <= 0) + { + text_color_set(DW_COLOR_ERROR); + dw_printf ("\nError sending message to KISS client application. Closing connection %d.\n\n", i); + close (client_sock[i]); + client_sock[i] = -1; + } } #endif @@ -626,20 +646,21 @@ static int read_from_socket (int fd, char *ptr, int len) /* Return one byte (value 0 - 255) */ -static int kiss_get (void) +static int kiss_get ( int socket_id ) { unsigned char ch; int n; while (1) { - while (client_sock <= 0) { +#if __WIN32__ + while (client_sock[socket_id] <= 0) { SLEEP_SEC(1); /* Not connected. Try again later. */ } - +#endif /* Just get one byte at a time. */ - n = read_from_socket (client_sock, (char *)(&ch), 1); + n = read_from_socket (client_sock[socket_id], (char *)(&ch), 1); if (n == 1) { #if DEBUG9 @@ -661,11 +682,13 @@ static int kiss_get (void) text_color_set(DW_COLOR_ERROR); dw_printf ("\nError reading KISS byte from clent application. Closing connection.\n\n"); #if __WIN32__ - closesocket (client_sock); + closesocket (client_sock[socket_id]); #else - close (client_sock); + close (client_sock[socket_id]); #endif - client_sock = -1; + client_sock[socket_id] = -1; + + return( -1 ); } } @@ -674,15 +697,65 @@ static int kiss_get (void) static void * kissnet_listen_thread (void *arg) { unsigned char ch; - + int i = 0; + int count; + int max_fd; + fd_set set; + struct timeval tv; #if DEBUG text_color_set(DW_COLOR_DEBUG); - dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock); + dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock[i]); #endif while (1) { - ch = kiss_get(); - kiss_rec_byte (&kf, ch, kiss_debug, kissnet_send_rec_packet); +#if __WIN32__ + ch = kiss_get( i ); + kiss_rec_byte (&kf[i], ch, kiss_debug, kissnet_send_rec_packet); +#else + FD_ZERO( &set ); + for( max_fd=0, i=0; i 0 ) { + FD_SET( client_sock[i], &set); + if( client_sock[i] > max_fd ) + max_fd = client_sock[i]; + } + + if( max_fd == 0 ) { + SLEEP_SEC(1); + continue; + } + else + { + tv.tv_sec = 1; + tv.tv_usec = 0; + count = select( max_fd + 1, &set, NULL, NULL, &tv ); + } + + if( count > 0 ) { + for( i=0; i 0 && FD_ISSET( client_sock[i], &set )) { + ch = kiss_get( i ); + if( ch != -1 ) + kiss_rec_byte (&kf[i], ch, kiss_debug, + kissnet_send_rec_packet); + } + } + } + else if ( count == 0 ) + { + #if DEBUG + dw_printf ("kissnet_listen_thread timeout\n"); + #endif + } + else + { + // TODO : Should we do something here ? + #if DEBUG + dw_printf ("kissnet_listen_thread error\n"); + #endif + } + +#endif } return (NULL); /* to suppress compiler warning. */