#! /usr/bin/perl -w # ARQ module arq.pm by PA0R. This module is part of the PSK_ARQ suite of # programs. PSK_ARQ adds an arq layer to keyboard oriented protocols like # PSK31, PSK63, MFSK, MT63 etc. # arq.pm includes the arq primitives common to server and client. # This program is published under the GPL license. # Copyright (C) 2005 # Rein Couperus PA0R (rein@couperus.com) # # * arq.pm is free software; you can redistribute it and/or modify # * it under the terms of the GNU General Public License as published by # * the Free Software Foundation; either version 2 of the License, or # * (at your option) any later version. # * # * arq.pm is distributed in the hope that it will be useful, # * but WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # * GNU General Public License for more details. # * # * You should have received a copy of the GNU General Public License # * along with this program; if not, write to the Free Software # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################### # link layer spec for PSK_ARQ ######################################### =header1 PSK_ARQ MODULE generic block format: dcl[info])12EF ||| | +-checksum (4xAlphaNum) ||| +-----block (1 ... 128 chars) ||+-------block type |+--------stream id +---------protocol number Frame: .... SendQueue: < >< > | | Firstsent Lastblock ReceiveQueue: < >< >< >< > | | Goodblock EndBlock listen --- connect ---data ---data --- data --- statreq data---statreq disc | | | | | | | connected data ---statrprt statrprt ack =cut use Digest::CRC qw(crc16); use Fcntl; my $debug = 0; my $monitor = 1; my $ShowBlock = 1; my $Iamserver = 0; my $ServerCall = ""; my $ClientCall = ""; my $Call = ""; my $hiscall = ""; my $output = ">$ENV{HOME}/gmfsk_autofile"; # Tx output my $TxInputfile = "TxInputfile"; # Tx input my $Inputfile = "$ENV{HOME}/gMFSK.log"; # Rx input my $CutInput = 4; ###################### constants ############################### my $Conreq = "c"; my $Conack = "k"; my $Statreq = "p"; my $Statrprt = "s"; my $Conid = "i"; my $Disreq = "d"; my $Disack = "b"; my $Abort = 'a'; my $Streamid = "0"; my $InputString = ""; my $HeaderStart = " "; my $FrameEnd = " "; my $Txdelay = 1; my $Bufferlength = 64; ###################### status variables ####################### my $Blockindex = 6; # Data block length (2^x) my $MaxDataBlocks = 8; # Max. number of data blocks to be sent my $Lastblockinframe = 0; # Flag for last block in frame my $Idle_counter = 0; # seconds from last my $Connect_time = 0; # connect time in seconds my $Interval_time = 0; # 500 seconds interval my $InputLine = ""; # Input from gmfsk my $TxFlag = 0; # TX on my $ConnectFlag = 0; # Station is connected ######### my status my $Firstsent = 0; # First block I sent last turn my $Lastblock = 0; # Last block I sent last turn my $Endblock = 0; # Last I received o.k. my $Goodblock = 0; # Last block I received conseq. o.k, 1st in send queue my $Lastqueued = 0; # Last block in my send queue my $TXServerStatus= ""; my $ServerStatus = ""; # Listen, Connect_req, Disconnect_req, Abort_req my @Missing = (); # List of repeat requests my $MissString = ""; # List of repeat requests my $ReceivedLastBlock = 0; # Flag for end of frame ################## ######### his status my $HisGoodblock = 0; # Other station's Good block my $HisLastblock = 0; # Other station's Block last sent my $HisEndblock = 0; # Other station's last received block my @HisMissing = (); # Other station's missing blocks ################### ##################### queues ################################## my $TxTextQueue = ""; # Text in from mail engine my @SendQueue = (); # Array of data ready for sending my $RxTextQueue = ""; # Text string my @ReceiveQueue = (); # Array of msg received ok. my $TextOut = ""; my @options = (); my $Latitude = ""; my $Longitude = ""; if (-e ".PSKoptions") { open (OPTIONS, ".PSKoptions") or die "No options file\n"; @options = ; close (OPTIONS); chomp $options[0]; chomp $options[1]; chomp $options[2]; chomp $options[3]; chomp $options[4]; $ClientCall = $options[0]; $ServerCall = $options[1]; $Blockindex = $options[2]; $Latitude = $options[3]; $Longitude = $options[4]; } $StartHeader = sprintf("%c", '1'); $FrameEnd = sprintf("%c%c", '4','10'); $BlockLengthStr= sprintf("%c", $Blockindex + 48); $BlockLength = (2 ** $Blockindex) ; $Call = $ClientCall; 1; ########################################################### sub newsession { # new session number ########################################################### ++$SessionNumber; $SessionNumber %= 10; } ########################################################### sub newblocknumber { # get new blocknumber ########################################################### $Lastqueued++; return ($Lastqueued % $Bufferlength); } ########################################################### sub makeindex { # make transmitable index from number ########################################################### my $index = shift @_; my $character = ""; $character = sprintf ("%c", ($index % $Bufferlength) + 32); return $character; } ########################################################### sub contime { # UTC time of this connect ########################################################### # (my $sec, my $min, my $hr) =gmtime; # $Contime = sprintf ("%02d:%02d", $hr, $min); } ############################################################ sub checksum { # Checksum of header + block ############################################################ # Time + password + header + block ############################################################ my $String = shift (@_); my $Encrypted = "0000" . sprintf ("%X", crc16($String)); return substr ($Encrypted, -4); } ############################################################ sub newconnectblock { # Connect (client:port, server:port) # c block = Client:port Server:port # e.g.: '00cEA3FG:1024 PI4TUE:24 4' ############################################################ my $server = shift @_; my $Call = shift @_; $Connect_time = 0; # start timer return ("0" . $Streamid . $Conreq . $ClientCall . ":1024 " . $server . ":24 " . $BlockLengthStr) } ############################################################### sub newackblock { # Connect acknowledge (server:port, client:port) # k block = Server:port Client:port # e.g: '00kPI4TUE:24 EA3FG:1024 8' ############################################################### my $server = shift @_; my $Call = shift @_; $Connect_time = 0; # start timer return ("0" . $Streamid . $Conack . $server . ":24 " . $Call . ":1024 " . $BlockLengthStr); } ############################################################### sub pollblock { # poll #p frame = #e.g.: '00pXHCAB' ############################################################### my ($MyLast, $Good, $Last, @RptBlocks) = @_; my $MyLastblock = sprintf ("%c", $MyLast + 0x20); my $thisgoodblock = sprintf("%c", $Goodblock + 32); my $thisLastblock = sprintf("%c", $Endblock + 32); my $misses = join('', @RptBlocks); return ("0" . $Streamid . $Statreq . $MyLastblock . $thisgoodblock . $thisLastblock . $misses ); } ################################################################ sub statreport { # Status report (End, Good, Lastrx, Missing) #p frame = #e.g.: '00sXHCAB' ################################################################ my ($MyLast, $Good, $Last, @RptBlocks) = @_; # if ($MyLast) { my $MyLastchar = sprintf ("%c", $MyLast + 0x20); # my $Goodchar = sprintf ("%c", $Good + 0x20); # my $Lastchar = sprintf("%c", $Last + 0x20); my $Goodchar = sprintf ("%c", $Goodblock + 32); my $Lastchar = sprintf("%c", $Endblock + 32); my $misses = join('', @RptBlocks); return ("0" . $Streamid . $Statrprt . $MyLastchar . $Goodchar . $Lastchar . $misses ); # } } ############################################################### sub identblock { # Identify (mycall, hiscall) #i frame = '00iPI4TUE de PA0R' ############################################################### my ($Call, $hiscall) = @_; if ($Iamserver == 1) { return ( "0" . $Streamid . $Conid . $hiscall . " de " . $Call); }else { return ( "0" . $Streamid . $Conid . $Call . " de " . $hiscall); } } ############################################################## sub disconnectblock { # Disconnect session #d frame = "" #e.g.: '00d' ############################################################## return ( "0" . $Streamid . $Disreq); } ############################################################## sub abortblock { # Abort session #a frame = "" #e.g.: '00a' ############################################################## return ( "0" . $Streamid . $Abort); } ############################################################## sub Queue_txdata { ############################################################## $TxTextQueue .= shift @_; my $newqueuedblock = 0; my $qlength = $Lastqueued - $HisGoodblock; if ($qlength < 0) { $qlength += $Bufferlength; } if ($qlength > 60) { return }; # next time better.... while (length $TxTextQueue > 0 ) { $newqueuedblock = newblocknumber(); $Sendqueue[ $newqueuedblock ] = substr ($TxTextQueue, 0, $BlockLength); $Lastqueued = $newqueuedblock; if (length $TxTextQueue >= $BlockLength) { $TxTextQueue = substr($TxTextQueue, $BlockLength); } else { $TxTextQueue = ""; } if ($debug == 5){ print $TxTextQueue, "\n"; } $qlength++; last if ($qlength > 60) ; } if ($debug == 5) { printf ("Lastqueued=%d, Queuelength=%d\n", $Lastqueued, $qlength); } } ############################################################## sub packdata { # Add header # <0x20...0x5f> # e.g.: '00jThis is data for' ############################################################## #print "List=",@_, "\n"; my $Currentblock = shift @_; my $Data = shift @_; # my $current = makeindex($Currentblock); #printf ("Current=%s, Data=%s\n", $Currentblock, $Data); if ($Data) { return ( "0" . $Streamid # . $current . $Currentblock . $Data); } } ############################################################# sub make_block { #Adds SOH and checksum # e.g.: '00jThis is data for'akj0 ############################################################# my $info = shift @_; if ($info) { my $check = checksum ($info); return ( $StartHeader . $info . $check); } } ############################################################# sub sendit { # send routine ############################################################# my $sendstring = shift @_; my $counter = 0; my $index = index ($sendstring, sprintf("%c", 0x04)); if ($index > 0) { sleep ($Txdelay); while (-e $output) { sleep (1); $counter++; if ($counter > 1) { last; } } $sendstring = "iiiii" . $sendstring; # enable lock on first block... open (OUT, $output); print OUT $sendstring; close (OUT); $Idle_counter = 0; # Activity, reset counter } } ############################################################ sub send_frame { #send blocks in queue # frame = [] ############################################################ my $Payload = shift @_; my $charindex = 0; my $outstring = ""; if ($TXServerStatus eq "TXAbortreq") { # send abort frame my $finfo = abortblock(); $outstring .= make_block($finfo); } elsif ($TXServerStatus eq "TXConnect_ack") { # send connect ack my $info = newackblock ($ServerCall, $ClientCall); $Lastblockinframe = 1; $outstring .= make_block($info); } elsif ($TXServerStatus eq "TXConnect") { # send connect request my $info = newconnectblock($ServerCall, $ClientCall); $Lastblockinframe = 1; $outstring .= make_block($info); } elsif ($TXServerStatus eq "TXDisconnect") { # send disconnect request my $info = disconnectblock(); $outstring .= make_block($info); $Lastblockinframe = 1; } elsif ($TXServerStatus eq "TXPoll") { # send poll # printf ("Sending poll: Lastblock=%d, Endblcok=%d, Goodblock=%d, Missing=%s\n", $Lastblock, $Endblock, $Goodblock, $Missing); my $info = pollblock($Lastblock, $Endblock, $Goodblock, @Missing); $Lastblockinframe = 1; $outstring .= make_block($info); } elsif ($TXServerStatus eq "TXStat") { # send status # printf ("Sending status: Lastblock=%d, Endblock=%d, Goodblock=%d, Missing=%s\n", $Lastblock, $Endblock, $Goodblock, $Missing); my $info = statreport($Lastblock, $Endblock, $Goodblock, @Missing); $Lastblockinframe = 1; $outstring .= make_block($info); } elsif ($TXServerStatus eq "TXTraffic") { # traffic ## id block if ($Interval_time > 500) { # every 500 seconds $Interval_time = 0; my $info = identblock($ServerCall, $ClientCall); $outstring .= make_block($info); } ## Data if ($debug == 5) { #debug printf ("Payload=%s\n", $Payload); } Queue_txdata($Payload); my $queuelength = ($Lastqueued - $HisGoodblock) % $Bufferlength; # lenght of payload queue if ($debug == 5) { #debug print "payloadqueue =", $queuelength, "\n"; } my $blocks_sent = 0; my $text = ""; ## missing data foreach $blockindex (@HisMissing) { $info = packdata($blockindex, $Sendqueue[(ord $blockindex) - 32]); if ($info) { $outstring .= make_block($info); $blocks_sent++; } } ## queued data if ($debug == 5) { #debug printf ("HisEndblock=%d, Blocks_sent=%d, Last_queued=%d, Maxdata=%d\n", $HisEndblock, $blocks_sent, $Lastqueued, $MaxDataBlocks); } for ($runvar = $HisEndblock +1; ($queuelength > 0) && ($runvar <= $HisEndblock + ($MaxDataBlocks - $blocks_sent)); $runvar++) { if ($debug == 5 ) { #debug printf ("Runvar=%d, Lastqueued=%d\n", $runvar, $Lastqueued); } if ($runvar > ($Bufferlength -1)) { $charindex = $runvar - $Bufferlength; } else { $charindex = $runvar; } $Lastblock = $charindex; if ($debug == 5) { #debug printf ("Runvar=%d, lastqueued=%d\n", $runvar, $Lastqueued); } if (($Lastqueued - $runvar) < 0) { last if ($Lastqueued -$runvar + $Bufferlength) == 0; } else { last if ($runvar > $Lastqueued) ; } my $char = sprintf("%c", $charindex + 32); if ($Sendqueue[$charindex]) { $info = packdata($char, $Sendqueue[ord ($char) - 32]); if ($debug == 5) { #debug printf ("charindex=%d, char=%s", $charindex, $char); } $outstring .= make_block($info); last if ($runvar == $Lastqueued); } else { last; } } ## status block $info = statreport($Lastblock, $Endblock, $Goodblock, @Missing); $outstring .= make_block($info); $Lastblockinframe= 1; } if ($Lastblockinframe == 1) { $outstring .= $FrameEnd; $Lastblockinframe = 0; } if ($debug == 0) { sendit($outstring); } else { print $outstring; print "\n"; sendit($outstring); } } ####################### end send_frame ############################## #################################################################### sub disconnect { #################################################################### $TXServerStatus = "TXDisconnect"; send_frame(); return; } ##################################################################### sub handle_rxqueue { # Do we have consecutive good buffers? ##################################################################### my $runvar = 0; my $Endpoint = 0; my $index = 0; my $inx = 0; my $cell = ""; my $Character = ""; @Missing = (); $Missing = ""; if ($HisLastblock == $Goodblock) { $Endblock = $Goodblock; return; } elsif ($HisLastblock < ($Goodblock)) { $Endpoint = $HisLastblock + $Bufferlength; } else { $Endpoint = $HisLastblock; } if ($debug == 5) { printf ("Hislast=%d, Goodblock=%d, Endblock=%d, Endpoint=%d\n", $HisLastblock, $Goodblock, $Endblock, $Endpoint); } # set missing blocks my $Goodstuff = 1; my $missers = 0; for ($runvar = $Goodblock + 1; $runvar <= $Endpoint; $runvar++) { if ($runvar > ($Bufferlength - 1)) { $index = $runvar - $Bufferlength; } else { $index = $runvar; } if ($ReceiveQueue[$index]) { if ($debug == 5) { #debug printf ("%d - %s\n", $index, $ReceiveQueue[$index]); } $Character = ""; $Endblock = $index; #set Endblock if ($Goodstuff == 1) { $Goodblock = $index; $RxTextQueue .= $ReceiveQueue[$index]; $ReceiveQueue[$index] = ""; } } else { $Goodstuff = 0; $missers++; if ($missers > $MaxDataBlocks){ $Endblock = $index; # safety net, something is wrong... last; } $Character = makeindex($index); push @Missing, $Character; $MissString = join ('', @Missing); $MissString = substr ($MissString, 0, $MaxDataBlocks -1 ); if ($debug == 5) { printf("Endpoint=%d, Index=%d, Info:%s", $Endpoint, $index, $ReceiveQueue[$index]); printf("\nMissString=%s\n", $MissString); } } } } ##################################################################### sub unframe { # get frame from gmfsk and unpack ##################################################################### my $TextFile = shift @_; my $Block = ""; my $BlockIndex = 0; my $ii = 0; my $closure = ""; while ($closure ne "") { if ($debug == 2) { printf ("Input=%s\n", $TextFile); } my $BlockStart = index ($TextFile, ""); if ($debug == 2) { printf ("Start=%d\n", $BlockStart); } if ($BlockStart < 0) { # not enough stuff yet last; } else { $Idle_counter = 0; # but we have a block coming... } $Block = substr ($TextFile, $BlockStart); if ($debug == 2) { printf ("Block=%s\n", $Block); } my $BlockEnd = index ($Block, "", 5); if ($BlockEnd < 0 ) { $BlockEnd = index ($Block, ""); } if ($BlockEnd < 0) { last; } # not enough stuff yet if ($debug == 2) { printf ("End=%d\n", $BlockEnd); } $Block = substr ($Block, 0, $BlockEnd + 5); reset; if ($Block =~ ?((.)(.)(.)(.*))(....)()?s || $Block =~ ?((.)(.)(.)(.*))(....)()?s) { my $checkinfo = $1; my $operand = $4; my $payload = $5; my $check = $6; $closure = $7; if ($debug == 5) { print "All :",$1, "\n"; print "Proto :", $2, "\n"; print "Stream:", $3, "\n"; print "Oper :" ,$4, "\n"; print "Data :", $5, "\n"; print "Check :", $6, "\n"; print "Close :", $7, "\n"; } ## got it, remove from queue $TextFile = substr ($TextFile, index($TextFile, $1) + 4 + length ($1)); if ($debug == 2) { printf ("Txtfromfile_now:%s\n", $TextFile); print checksum($checkinfo), "\n"; print $check, "\n"; } ## checksum o.k.? if ($check eq checksum($checkinfo)) { if ($debug == 2) { print "checksum o.k.\n" ; printf ("operand=%s\n", $operand); } ## monitor if ($monitor) { if ($ShowBlock) { print $Block, "\n";} if (ord $4 > 95) { if (substr ($4, 0, 1) eq "p") { my $lastblockvalue = ord (substr ($5, 0, 1)) - 32; my $goodblockvalue = ord (substr ($5, 1, 1)) - 32; my $endblockvalue = ord (substr ($5, 2, 1)) - 32; my $missingvalue = substr ($5, 3); printf ("> Poll : last=%d good=%d end=%d missing=%s\n", $lastblockvalue, $goodblockvalue, $endblockvalue, $missingvalue); } if (substr ($4, 0, 1) eq "s") { my $lastblockvalue = ord (substr ($5, 0, 1)) - 32; my $goodblockvalue = ord (substr ($5, 1, 1)) - 32; my $endblockvalue = ord (substr ($5, 2, 1)) - 32; my $missingvalue = substr ($5, 3); printf ("> Status : last=%d good=%d end=%d missing=%s\n", $lastblockvalue, $goodblockvalue, $endblockvalue, $missingvalue); } if (substr ($4, 0, 1) eq "a") {printf ("> Abort \n\n");} if (substr ($4, 0, 1) eq "c") {printf ("> Connect: %s\n\n", $5);} if (substr ($4, 0, 1) eq "d") {printf ("> Disconnect\n\n");} if (substr ($4, 0, 1) eq "i") {printf ("> Ident : %s\n\n", $5);} } else { my $zahl = (ord $4) - 32; printf ("> Data: %2d\n%s\n\n", $zahl, $5); } # end monitor } if ($closure eq "") { $ServerStatus = "EOT"; $ReceivedLastBlock = 1; } ## abort if ($operand eq 'a') { $ServerStatus = "Abort"; return $TextFile; ## connect request ('PA0R:1024 PI4TUE:24 4') } elsif ($operand eq 'c') { if ($payload =~ ?(.*):(.*)\s(.*):(.*)\s(.)?s) { if ($debug == 2) { print $1, "\n"; print $2, "\n"; print $3, "\n"; print $4, "\n"; print $5, "\n"; } if ($Iamserver) { if ($3 ne $ServerCall) { print "Not my call...\n"; return($TextFile); } else { $ServerStatus = "Connect_req"; $Call = $1; # set the call $ClientCall = $1; my $Maxlen = (ord $5) - 48; # if ($Maxlen <= $Blockindex) { $Blockindex = $Maxlen; # set max blocklength $BlockLengthStr= sprintf("%c", $Blockindex + 48); $BlockLength = (2 ** $Blockindex) ; # todo: setup ports # } # if ($debug == 2) { print $ServerStatus, "\n"; print "Called by $ClientCall\n"; print "Max block length = $5\n"; # } } } else { print "I am no server\n"; return($TextFile); } } ## Connect acknowledge (PI4TUE:24 PA0R:1024 4) } elsif ($operand eq 'k') { print "ACK\n"; $Idle_counter = 0; $ServerStatus = "Connect_ack"; if ($payload =~ /.*\s.*\s(.)/s){ my $Maxlen = ord $1 - 48; if ($Maxlen <= $Blockindex) { $Blockindex = $Maxlen; # set max blocklength } } return $TextFile; ## disconnect } elsif ($operand eq 'd') { $ServerStatus = "Disconnect_req"; last; return $TextFile; ## status block ('abcdef') } elsif ($operand eq 's') { if ($payload =~ /(.)(.)(.)(.*)/s) { $HisLastblock = ord ($1) - 32; my $HisGoodblockchar = $2; my $HisEndblockchar = $3; $HisMissString = $4; @HisMissing = split('', $HisMissString); $ServerStatus = "Status_rx"; $HisGoodblock = (ord $HisGoodblockchar) - 32; $HisEndblock = (ord $HisEndblockchar) - 32; if ($debug == 2) { print $HisLastblock, "\n"; print $HisGoodblock, "\n"; print $HisEndblock, "\n"; print $HisMissString, "\n"; } handle_rxqueue(); $ReceivedlastBlock = 1; return $TextFile; } ## poll block ('abcdef') } elsif ($operand eq 'p') { if ($payload =~ /(.)(.)(.)(.*)/s) { $HisLastblock = ord($1) - 32; $HisGoodblock = ord($2) -32; $HisEndblock = ord($3) - 32; $HisMissString = $4; @HisMissing = split('', $HisMissString); $ServerStatus = "Poll_rx"; if ($debug == 2) { print $HisLastblock, "\n"; print $HisGoodblock, "\n"; print $HisEndblock, "\n"; print $HisMissingString, "\n"; } handle_rxqueue(); $ReceivedlastBlock = 1; return $TextFile; } ## data block } else { $ServerStatus = "Data"; my $Current = (ord $operand) - 32; if ($debug == 2) { ##debug printf ("Current=%d\n", $Current); printf ("Payload=%s\n", $payload); } $ReceiveQueue[$Current] = $payload; if ($debug == 2) { ##debug for (my $ij = 0; $ij < $Bufferlength ; $ij++) { if ($ReceiveQueue[$ij]) { printf ("%d-%s\n", $ij, $ReceiveQueue[$ij]); } } } } } } } return $TextFile; } ##################################################################### sub getinput { ##################################################################### my $buffer = ""; $bytes = sysread INFH, $buffer, $Bufferlength ; #print "buffer:", $buffer, "\n"; if ($bytes > 0) { $InputLine .= $buffer; } else { return; } if ($InputLine =~ /|/) { $Idle_counter = 0; # activity.... reset counter } # printf ("In :%s\n", $InputLine); if ($InputLine =~ //){ $TxFlag = 0; } if ($InputLine =~ /^RX/ ){ $TxFlag = 0; } reset; if ($InputLine =~ s/TX .*\n//sg) { return ""; }elsif ($InputLine =~ /TX \(.*\)/){ $TxFlag = 1; } elsif ($InputLine =~ /RX .*\n|.*|.*|.*/ && $TxFlag == 0){ my $outline = $InputLine; if ($InputLine =~ /.*/ && $TxFlag == 0){ $InputLine = substr ($InputLine, -6); } if ($InputLine =~ /(.*)/ && $TxFlag == 0){ if (length $1 < 7) { $Inputline = ""; } else { $InputLine = substr ($InputLine, -6); } } if ($TxFlag == 0) { $InputLine = ""; reset; $outline =~ s/RX \(.*\): //g; return $outline; } } return ""; } ##################################################################### sub gettxinput { ##################################################################### if (-s "TxInputfile") { my $txinfile = `cat TxInputfile`; unlink "TxInputfile"; my @strcharacters = split //, $txinfile; foreach my $badchar (@strcharacters) { if (ord ($badchar) < 5) { $badchar = sprintf ("|Ctl-%c|", ord ("A") + ord ($badchar)); } } $txinfile = join "", @strcharacters; $txinfile =~ tr/\200-\377/./; $txinfile =~ s///g; $txinfile =~ s///g; return $txinfile; } Queue_txdata(""); return ""; } ######################################################### sub listening { ######################################################### my $string = getinput(); unless ($string) { return; } $TextFromFile .= $string; $TextFromFile =~ s/RX\s\(\d+-\d+-\d+\s\d+:\d+Z\):\s//s; $TextFromFile = unframe ($TextFromFile); # Text from gmfsk logfile } ##################################################################### sub initialize { ##################################################################### $Call = $ClientCall; for (my $i = 0; $i < $Bufferlength; $i++) { $ReceiveQueue[$i] = ""; } sysopen (INFH, $Inputfile, O_RDONLY); } ##################################################################### sub get_rxstatus { ##################################################################### return $ServerStatus; } ##################################################################### sub reset_rxstatus { ##################################################################### $ServerStatus = "Listening"; } ##################################################################### sub get_call { ##################################################################### return $ClientCall; } ##################################################################### sub set_txstatus { ##################################################################### $TXServerStatus = shift @_; } ##################################################################### sub set_connectstatus { ##################################################################### $ConnectedFlag = "Connected"; } ##################################################################### sub reset_connectstatus { ##################################################################### $ConnectedFlag = "Disconnected"; } ##################################################################### sub get_connectstatus { ##################################################################### return $ConnectedFlag ; } ##################################################################### sub reset_arq { ##################################################################### $Firstsent = 0; $Lastblock = 0; $Endblock = 0; $Goodblock = 0; $Lastqueued = 0; @Missing = (); $MissString = ""; $HisGoodblock = 0; # Other station's Good block $HisLastblock = 0; # Other station's Block last sent $HisEndblock = 0; # Other station's last received block @HisMissing = (); # Other station's missing blocks @SendQueue = (); $TxTextQueue = ""; $RxTextQueue = ""; @ReceiveQueue = (); $Idle_counter = 0; # seconds from last $Connect_time = 0; # connect time in seconds $Interval_time = 0; # 500 seconds interval if (-e $TxInputfile) { unlink $TxInputfile; } } ##################################################################### sub get_rxqueue { ##################################################################### return $RxTextQueue; } ##################################################################### sub reset_rxqueue { ##################################################################### $RxTextQueue = ""; } ##################################################################### sub get_rxqueue_status { ##################################################################### my @outlist = (); push @outlist, $Lastblock; push @outlist, $Endblock; push @outlist, $Goodblock; push @outlist, $MissString; return @outlist; } ##################################################################### sub check_lastblock { ##################################################################### my $flag = $ReceivedLastBlock; $ReceivedLastBlock = 0; return $flag; } ##################################################################### sub inc_idle { ##################################################################### $Idle_counter++; $Connect_time++; $Interval_time++; } ##################################################################### sub get_idle { ##################################################################### return $Idle_counter; } ##################################################################### sub get_connect_time { ##################################################################### return $Connect_time; } ##################################################################### sub get_sendqueue { ##################################################################### my $qlength = $Lastqueued - $HisGoodblock; if ($qlength < 0) { $qlength += $Bufferlength }; return $qlength; } ###################### END ####################################