Skip to content

Commit 1f9310b

Browse files
committed
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.
1 parent 6207e2e commit 1f9310b

File tree

1 file changed

+163
-90
lines changed

1 file changed

+163
-90
lines changed

kissnet.c

Lines changed: 163 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// This file is part of Dire Wolf, an amateur radio packet TNC.
33
//
44
// Copyright (C) 2011-2014, 2015 John Langner, WB2OSZ
5+
// Copyright (C) 2016 Angus Ainslie angus at akkea.ca, VE6GUS
56
//
67
// This program is free software: you can redistribute it and/or modify
78
// it under the terms of the GNU General Public License as published by
@@ -128,15 +129,21 @@
128129
#include "kiss_frame.h"
129130
#include "xmit.h"
130131

132+
// TODO: no idea how to do this on windows
133+
#if __WIN32__
134+
#define MAX_NET_CLIENTS 1
135+
#else
136+
#define MAX_NET_CLIENTS 4
137+
#endif
131138

132-
static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
133-
// TODO: multiple instances if multiple KISS network clients!
139+
static kiss_frame_t kf[MAX_NET_CLIENTS]; /* Accumulated KISS frame and state of decoder. */
140+
// TODO: multiple instances if multiple KISS network clients!
134141

135142

136-
static int client_sock; /* File descriptor for socket for */
137-
/* communication with client application. */
138-
/* Set to -1 if not connected. */
139-
/* (Don't use SOCKET type because it is unsigned.) */
143+
static int client_sock[MAX_NET_CLIENTS]; /* File descriptor for socket for */
144+
/* communication with client application. */
145+
/* Set to -1 if not connected. */
146+
/* (Don't use SOCKET type because it is unsigned.) */
140147

141148

142149
static void * connect_listen_thread (void *arg);
@@ -187,16 +194,18 @@ void kissnet_init (struct misc_config_s *mc)
187194
#endif
188195
int e;
189196
int kiss_port = mc->kiss_port;
197+
int i;
190198

191199

192200
#if DEBUG
193201
text_color_set(DW_COLOR_DEBUG);
194202
dw_printf ("kissnet_init ( %d )\n", kiss_port);
195203
#endif
196204

197-
memset (&kf, 0, sizeof(kf));
198-
199-
client_sock = -1;
205+
for( i=0; i<MAX_NET_CLIENTS; i++ ) {
206+
client_sock[i] = -1;
207+
memset (&kf, 0, sizeof(kf));
208+
}
200209

201210
if (kiss_port == 0) {
202211
text_color_set(DW_COLOR_INFO);
@@ -343,8 +352,12 @@ static void * connect_listen_thread (void *arg)
343352

344353
while (1) {
345354

346-
while (client_sock > 0) {
347-
SLEEP_SEC(1); /* Already connected. Try again later. */
355+
i = 0
356+
while (client_sock[i] > 0) {
357+
if(( ++i % MAX_NET_CLIENTS ) == 0 ) {
358+
SLEEP_SEC(1); /* All clients already connected. Try again later. */
359+
i = 0 ;
360+
}
348361
}
349362

350363
#define QUEUE_SIZE 5
@@ -359,9 +372,9 @@ static void * connect_listen_thread (void *arg)
359372
text_color_set(DW_COLOR_INFO);
360373
dw_printf("Ready to accept KISS client application on port %s ...\n", kiss_port_str);
361374

362-
client_sock = accept(listen_sock, NULL, NULL);
375+
client_sock[i] = accept(listen_sock, NULL, NULL);
363376

364-
if (client_sock == -1) {
377+
if (client_sock[i] == -1) {
365378
text_color_set(DW_COLOR_ERROR);
366379
dw_printf("Accept failed with error: %d\n", WSAGetLastError());
367380
closesocket(listen_sock);
@@ -383,6 +396,7 @@ static void * connect_listen_thread (void *arg)
383396
int kiss_port = (int)(long)arg;
384397
int listen_sock;
385398
int bcopt = 1;
399+
int i;
386400

387401
listen_sock= socket(AF_INET,SOCK_STREAM,0);
388402
if (listen_sock == -1) {
@@ -409,12 +423,12 @@ static void * connect_listen_thread (void *arg)
409423
#endif
410424

411425
if (bind(listen_sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)) == -1) {
412-
text_color_set(DW_COLOR_ERROR);
413-
dw_printf("Bind failed with error: %d\n", errno);
414-
dw_printf("%s\n", strerror(errno));
415-
dw_printf("Some other application is probably already using port %d.\n", kiss_port);
416-
dw_printf("Try using a different port number with KISSPORT in the configuration file.\n");
417-
return (NULL);
426+
text_color_set(DW_COLOR_ERROR);
427+
dw_printf("Bind failed with error: %d\n", errno);
428+
dw_printf("%s\n", strerror(errno));
429+
dw_printf("Some other application is probably already using port %d.\n", kiss_port);
430+
dw_printf("Try using a different port number with KISSPORT in the configuration file.\n");
431+
return (NULL);
418432
}
419433

420434
getsockname( listen_sock, (struct sockaddr *)(&sockaddr), &sockaddr_size);
@@ -426,8 +440,12 @@ static void * connect_listen_thread (void *arg)
426440

427441
while (1) {
428442

429-
while (client_sock > 0) {
430-
SLEEP_SEC(1); /* Already connected. Try again later. */
443+
i = 0;
444+
while (client_sock[i] > 0) {
445+
if(( ++i % MAX_NET_CLIENTS ) == 0 ) {
446+
i = 0;
447+
SLEEP_SEC(1); /* Already connected. Try again later. */
448+
}
431449
}
432450

433451
#define QUEUE_SIZE 5
@@ -440,12 +458,12 @@ static void * connect_listen_thread (void *arg)
440458
}
441459

442460
text_color_set(DW_COLOR_INFO);
443-
dw_printf("Ready to accept KISS client application on port %d ...\n", kiss_port);
461+
dw_printf("Ready to accept KISS client %d application on port %d ...\n", i, kiss_port);
444462

445-
client_sock = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
463+
client_sock[i] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
446464

447465
text_color_set(DW_COLOR_INFO);
448-
dw_printf("\nConnected to KISS client application ...\n\n");
466+
dw_printf("\nConnected to KISS client %d application on fd %d...\n\n", i, client_sock[i] );
449467

450468
}
451469
#endif
@@ -483,64 +501,66 @@ void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen)
483501
int kiss_len;
484502
int j;
485503
int err;
486-
487-
488-
if (client_sock == -1) {
489-
return;
490-
}
491-
if (flen < 0) {
492-
flen = strlen((char*)fbuf);
493-
if (kiss_debug) {
494-
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
495-
}
496-
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
497-
kiss_len = strlen((char *)kiss_buff);
498-
}
499-
else {
500-
501-
502-
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
503-
504-
assert (flen < sizeof(stemp));
505-
506-
stemp[0] = (chan << 4) + 0;
507-
memcpy (stemp+1, fbuf, flen);
508-
509-
if (kiss_debug >= 2) {
510-
/* AX.25 frame with the CRC removed. */
511-
text_color_set(DW_COLOR_DEBUG);
512-
dw_printf ("\n");
513-
dw_printf ("Packet content before adding KISS framing and any escapes:\n");
514-
hex_dump (fbuf, flen);
515-
}
516-
517-
kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff);
518-
519-
/* This has the escapes and the surrounding FENDs. */
520-
521-
if (kiss_debug) {
522-
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
523-
}
524-
}
504+
int i;
505+
506+
for( i = 0; i<MAX_NET_CLIENTS; i++ ) {
507+
if (client_sock[i] == -1) {
508+
continue;
509+
}
510+
if (flen < 0) {
511+
flen = strlen((char*)fbuf);
512+
if (kiss_debug) {
513+
kiss_debug_print (TO_CLIENT, "Fake command prompt", fbuf, flen);
514+
}
515+
strlcpy ((char *)kiss_buff, (char *)fbuf, sizeof(kiss_buff));
516+
kiss_len = strlen((char *)kiss_buff);
517+
}
518+
else {
519+
520+
521+
unsigned char stemp[AX25_MAX_PACKET_LEN + 1];
522+
523+
assert (flen < sizeof(stemp));
524+
525+
stemp[0] = (chan << 4) + 0;
526+
memcpy (stemp+1, fbuf, flen);
527+
528+
if (kiss_debug >= 2) {
529+
/* AX.25 frame with the CRC removed. */
530+
text_color_set(DW_COLOR_DEBUG);
531+
dw_printf ("\n");
532+
dw_printf ("Packet content before adding KISS framing and any escapes:\n");
533+
hex_dump (fbuf, flen);
534+
}
535+
536+
kiss_len = kiss_encapsulate (stemp, flen+1, kiss_buff);
537+
538+
/* This has the escapes and the surrounding FENDs. */
539+
540+
if (kiss_debug) {
541+
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
542+
}
543+
}
525544

526545
#if __WIN32__
527-
err = send (client_sock, (char*)kiss_buff, kiss_len, 0);
528-
if (err == SOCKET_ERROR)
529-
{
530-
text_color_set(DW_COLOR_ERROR);
531-
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
532-
closesocket (client_sock);
533-
client_sock = -1;
534-
WSACleanup();
535-
}
546+
err = send (client_sock[i], (char*)kiss_buff, kiss_len, 0);
547+
if (err == SOCKET_ERROR)
548+
{
549+
text_color_set(DW_COLOR_ERROR);
550+
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
551+
closesocket (client_sock[i]);
552+
client_sock[i] = -1;
553+
WSACleanup();
554+
}
536555
#else
537-
err = write (client_sock, kiss_buff, kiss_len);
538-
if (err <= 0)
539-
{
540-
text_color_set(DW_COLOR_ERROR);
541-
dw_printf ("\nError sending message to KISS client application. Closing connection.\n\n");
542-
close (client_sock);
543-
client_sock = -1;
556+
err = write (client_sock[i], kiss_buff, kiss_len);
557+
if (err <= 0)
558+
{
559+
text_color_set(DW_COLOR_ERROR);
560+
dw_printf ("\nError sending message to KISS client application. Closing connection %d.\n\n", i);
561+
close (client_sock[i]);
562+
client_sock[i] = -1;
563+
}
544564
}
545565
#endif
546566

@@ -626,20 +646,21 @@ static int read_from_socket (int fd, char *ptr, int len)
626646
/* Return one byte (value 0 - 255) */
627647

628648

629-
static int kiss_get (void)
649+
static int kiss_get ( int socket_id )
630650
{
631651
unsigned char ch;
632652
int n;
633653

634654
while (1) {
635655

636-
while (client_sock <= 0) {
656+
#if __WIN32__
657+
while (client_sock[socket_id] <= 0) {
637658
SLEEP_SEC(1); /* Not connected. Try again later. */
638659
}
639-
660+
#endif
640661
/* Just get one byte at a time. */
641662

642-
n = read_from_socket (client_sock, (char *)(&ch), 1);
663+
n = read_from_socket (client_sock[socket_id], (char *)(&ch), 1);
643664

644665
if (n == 1) {
645666
#if DEBUG9
@@ -661,11 +682,13 @@ static int kiss_get (void)
661682
text_color_set(DW_COLOR_ERROR);
662683
dw_printf ("\nError reading KISS byte from clent application. Closing connection.\n\n");
663684
#if __WIN32__
664-
closesocket (client_sock);
685+
closesocket (client_sock[socket_id]);
665686
#else
666-
close (client_sock);
687+
close (client_sock[socket_id]);
667688
#endif
668-
client_sock = -1;
689+
client_sock[socket_id] = -1;
690+
691+
return( -1 );
669692
}
670693
}
671694

@@ -674,15 +697,65 @@ static int kiss_get (void)
674697
static void * kissnet_listen_thread (void *arg)
675698
{
676699
unsigned char ch;
677-
700+
int i = 0;
701+
int count;
702+
int max_fd;
703+
fd_set set;
704+
struct timeval tv;
678705
#if DEBUG
679706
text_color_set(DW_COLOR_DEBUG);
680-
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock);
707+
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock[i]);
681708
#endif
682709

683710
while (1) {
684-
ch = kiss_get();
685-
kiss_rec_byte (&kf, ch, kiss_debug, kissnet_send_rec_packet);
711+
#if __WIN32__
712+
ch = kiss_get( i );
713+
kiss_rec_byte (&kf[i], ch, kiss_debug, kissnet_send_rec_packet);
714+
#else
715+
FD_ZERO( &set );
716+
for( max_fd=0, i=0; i<MAX_NET_CLIENTS; i++ )
717+
if( client_sock[i] > 0 ) {
718+
FD_SET( client_sock[i], &set);
719+
if( client_sock[i] > max_fd )
720+
max_fd = client_sock[i];
721+
}
722+
723+
if( max_fd == 0 ) {
724+
SLEEP_SEC(1);
725+
continue;
726+
}
727+
else
728+
{
729+
tv.tv_sec = 1;
730+
tv.tv_usec = 0;
731+
count = select( max_fd + 1, &set, NULL, NULL, &tv );
732+
}
733+
734+
if( count > 0 ) {
735+
for( i=0; i<MAX_NET_CLIENTS; i++ ) {
736+
if( client_sock[i] > 0 && FD_ISSET( client_sock[i], &set )) {
737+
ch = kiss_get( i );
738+
if( ch != -1 )
739+
kiss_rec_byte (&kf[i], ch, kiss_debug,
740+
kissnet_send_rec_packet);
741+
}
742+
}
743+
}
744+
else if ( count == 0 )
745+
{
746+
#if DEBUG
747+
dw_printf ("kissnet_listen_thread timeout\n");
748+
#endif
749+
}
750+
else
751+
{
752+
// TODO : Should we do something here ?
753+
#if DEBUG
754+
dw_printf ("kissnet_listen_thread error\n");
755+
#endif
756+
}
757+
758+
#endif
686759
}
687760

688761
return (NULL); /* to suppress compiler warning. */

0 commit comments

Comments
 (0)