Skip to content

Commit 0cc5c20

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 23ea246 commit 0cc5c20

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
@@ -130,15 +131,21 @@
130131

131132
void hex_dump (unsigned char *p, int len); // This should be in a .h file.
132133

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

134-
static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
135-
// TODO: multiple instances if multiple KISS network clients!
141+
static kiss_frame_t kf[MAX_NET_CLIENTS]; /* Accumulated KISS frame and state of decoder. */
142+
// TODO: multiple instances if multiple KISS network clients!
136143

137144

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

143150

144151
// TODO: define in one place, use everywhere.
@@ -196,16 +203,18 @@ void kissnet_init (struct misc_config_s *mc)
196203
int e;
197204
#endif
198205
int kiss_port = mc->kiss_port;
206+
int i;
199207

200208

201209
#if DEBUG
202210
text_color_set(DW_COLOR_DEBUG);
203211
dw_printf ("kissnet_init ( %d )\n", kiss_port);
204212
#endif
205213

206-
memset (&kf, 0, sizeof(kf));
207-
208-
client_sock = -1;
214+
for( i=0; i<MAX_NET_CLIENTS; i++ ) {
215+
client_sock[i] = -1;
216+
memset (&kf, 0, sizeof(kf));
217+
}
209218

210219
if (kiss_port == 0) {
211220
text_color_set(DW_COLOR_INFO);
@@ -352,8 +361,12 @@ static THREAD_F connect_listen_thread (void *arg)
352361

353362
while (1) {
354363

355-
while (client_sock > 0) {
356-
SLEEP_SEC(1); /* Already connected. Try again later. */
364+
i = 0
365+
while (client_sock[i] > 0) {
366+
if(( ++i % MAX_NET_CLIENTS ) == 0 ) {
367+
SLEEP_SEC(1); /* All clients already connected. Try again later. */
368+
i = 0 ;
369+
}
357370
}
358371

359372
#define QUEUE_SIZE 5
@@ -368,9 +381,9 @@ static THREAD_F connect_listen_thread (void *arg)
368381
text_color_set(DW_COLOR_INFO);
369382
dw_printf("Ready to accept KISS client application on port %s ...\n", kiss_port_str);
370383

371-
client_sock = accept(listen_sock, NULL, NULL);
384+
client_sock[i] = accept(listen_sock, NULL, NULL);
372385

373-
if (client_sock == -1) {
386+
if (client_sock[i] == -1) {
374387
text_color_set(DW_COLOR_ERROR);
375388
dw_printf("Accept failed with error: %d\n", WSAGetLastError());
376389
closesocket(listen_sock);
@@ -392,6 +405,7 @@ static THREAD_F connect_listen_thread (void *arg)
392405
int kiss_port = (int)(long)arg;
393406
int listen_sock;
394407
int bcopt = 1;
408+
int i;
395409

396410
listen_sock= socket(AF_INET,SOCK_STREAM,0);
397411
if (listen_sock == -1) {
@@ -418,12 +432,12 @@ static THREAD_F connect_listen_thread (void *arg)
418432
#endif
419433

420434
if (bind(listen_sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)) == -1) {
421-
text_color_set(DW_COLOR_ERROR);
422-
dw_printf("Bind failed with error: %d\n", errno);
423-
dw_printf("%s\n", strerror(errno));
424-
dw_printf("Some other application is probably already using port %d.\n", kiss_port);
425-
dw_printf("Try using a different port number with KISSPORT in the configuration file.\n");
426-
return (NULL);
435+
text_color_set(DW_COLOR_ERROR);
436+
dw_printf("Bind failed with error: %d\n", errno);
437+
dw_printf("%s\n", strerror(errno));
438+
dw_printf("Some other application is probably already using port %d.\n", kiss_port);
439+
dw_printf("Try using a different port number with KISSPORT in the configuration file.\n");
440+
return (NULL);
427441
}
428442

429443
getsockname( listen_sock, (struct sockaddr *)(&sockaddr), &sockaddr_size);
@@ -435,8 +449,12 @@ static THREAD_F connect_listen_thread (void *arg)
435449

436450
while (1) {
437451

438-
while (client_sock > 0) {
439-
SLEEP_SEC(1); /* Already connected. Try again later. */
452+
i = 0;
453+
while (client_sock[i] > 0) {
454+
if(( ++i % MAX_NET_CLIENTS ) == 0 ) {
455+
i = 0;
456+
SLEEP_SEC(1); /* Already connected. Try again later. */
457+
}
440458
}
441459

442460
#define QUEUE_SIZE 5
@@ -449,12 +467,12 @@ static THREAD_F connect_listen_thread (void *arg)
449467
}
450468

451469
text_color_set(DW_COLOR_INFO);
452-
dw_printf("Ready to accept KISS client application on port %d ...\n", kiss_port);
470+
dw_printf("Ready to accept KISS client %d application on port %d ...\n", i, kiss_port);
453471

454-
client_sock = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
472+
client_sock[i] = accept(listen_sock, (struct sockaddr*)(&sockaddr),&sockaddr_size);
455473

456474
text_color_set(DW_COLOR_INFO);
457-
dw_printf("\nConnected to KISS client application ...\n\n");
475+
dw_printf("\nConnected to KISS client %d application on fd %d...\n\n", i, client_sock[i] );
458476

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

534553
#if __WIN32__
535-
err = send (client_sock, (char*)kiss_buff, kiss_len, 0);
536-
if (err == SOCKET_ERROR)
537-
{
538-
text_color_set(DW_COLOR_ERROR);
539-
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
540-
closesocket (client_sock);
541-
client_sock = -1;
542-
WSACleanup();
543-
}
554+
err = send (client_sock[i], (char*)kiss_buff, kiss_len, 0);
555+
if (err == SOCKET_ERROR)
556+
{
557+
text_color_set(DW_COLOR_ERROR);
558+
dw_printf ("\nError %d sending message to KISS client application. Closing connection.\n\n", WSAGetLastError());
559+
closesocket (client_sock[i]);
560+
client_sock[i] = -1;
561+
WSACleanup();
562+
}
544563
#else
545-
err = write (client_sock, kiss_buff, kiss_len);
546-
if (err <= 0)
547-
{
548-
text_color_set(DW_COLOR_ERROR);
549-
dw_printf ("\nError sending message to KISS client application. Closing connection.\n\n");
550-
close (client_sock);
551-
client_sock = -1;
564+
err = write (client_sock[i], kiss_buff, kiss_len);
565+
if (err <= 0)
566+
{
567+
text_color_set(DW_COLOR_ERROR);
568+
dw_printf ("\nError sending message to KISS client application. Closing connection %d.\n\n", i);
569+
close (client_sock[i]);
570+
client_sock[i] = -1;
571+
}
552572
}
553573
#endif
554574

@@ -635,20 +655,21 @@ static int read_from_socket (int fd, char *ptr, int len)
635655
/* Return one byte (value 0 - 255) */
636656

637657

638-
static int kiss_get (void)
658+
static int kiss_get ( int socket_id )
639659
{
640660
unsigned char ch;
641661
int n;
642662

643663
while (1) {
644664

645-
while (client_sock <= 0) {
665+
#if __WIN32__
666+
while (client_sock[socket_id] <= 0) {
646667
SLEEP_SEC(1); /* Not connected. Try again later. */
647668
}
648-
669+
#endif
649670
/* Just get one byte at a time. */
650671

651-
n = read_from_socket (client_sock, (char *)(&ch), 1);
672+
n = read_from_socket (client_sock[socket_id], (char *)(&ch), 1);
652673

653674
if (n == 1) {
654675
#if DEBUG9
@@ -670,11 +691,13 @@ static int kiss_get (void)
670691
text_color_set(DW_COLOR_ERROR);
671692
dw_printf ("\nError reading KISS byte from client application. Closing connection.\n\n");
672693
#if __WIN32__
673-
closesocket (client_sock);
694+
closesocket (client_sock[socket_id]);
674695
#else
675-
close (client_sock);
696+
close (client_sock[socket_id]);
676697
#endif
677-
client_sock = -1;
698+
client_sock[socket_id] = -1;
699+
700+
return( -1 );
678701
}
679702
}
680703

@@ -683,15 +706,65 @@ static int kiss_get (void)
683706
static THREAD_F kissnet_listen_thread (void *arg)
684707
{
685708
unsigned char ch;
686-
709+
int i = 0;
710+
int count;
711+
int max_fd;
712+
fd_set set;
713+
struct timeval tv;
687714
#if DEBUG
688715
text_color_set(DW_COLOR_DEBUG);
689-
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock);
716+
dw_printf ("kissnet_listen_thread ( socket = %d )\n", client_sock[i]);
690717
#endif
691718

692719
while (1) {
693-
ch = kiss_get();
694-
kiss_rec_byte (&kf, ch, kiss_debug, kissnet_send_rec_packet);
720+
#if __WIN32__
721+
ch = kiss_get( i );
722+
kiss_rec_byte (&kf[i], ch, kiss_debug, kissnet_send_rec_packet);
723+
#else
724+
FD_ZERO( &set );
725+
for( max_fd=0, i=0; i<MAX_NET_CLIENTS; i++ )
726+
if( client_sock[i] > 0 ) {
727+
FD_SET( client_sock[i], &set);
728+
if( client_sock[i] > max_fd )
729+
max_fd = client_sock[i];
730+
}
731+
732+
if( max_fd == 0 ) {
733+
SLEEP_SEC(1);
734+
continue;
735+
}
736+
else
737+
{
738+
tv.tv_sec = 1;
739+
tv.tv_usec = 0;
740+
count = select( max_fd + 1, &set, NULL, NULL, &tv );
741+
}
742+
743+
if( count > 0 ) {
744+
for( i=0; i<MAX_NET_CLIENTS; i++ ) {
745+
if( client_sock[i] > 0 && FD_ISSET( client_sock[i], &set )) {
746+
ch = kiss_get( i );
747+
if( ch != -1 )
748+
kiss_rec_byte (&kf[i], ch, kiss_debug,
749+
kissnet_send_rec_packet);
750+
}
751+
}
752+
}
753+
else if ( count == 0 )
754+
{
755+
#if DEBUG
756+
dw_printf ("kissnet_listen_thread timeout\n");
757+
#endif
758+
}
759+
else
760+
{
761+
// TODO : Should we do something here ?
762+
#if DEBUG
763+
dw_printf ("kissnet_listen_thread error\n");
764+
#endif
765+
}
766+
767+
#endif
695768
}
696769

697770
#if __WIN32__

0 commit comments

Comments
 (0)