* auto i/o - Added socket interface to allow separate program to access
    - CONNECT
    - DISCONNECT
    - CONNECTION_STATE
    - SEND_TEXT
    - RECEIVE_TEXT
    Allows similarly modified flmsg to send/recv messages using
    flarq / ARQ transport protocol.
  * ARQ reset - force complete reset of all ARQ processes
    - drops link without any indicator to connected station
    - equivalent of stopping and restarting flarq
    - courtesy demands that you inform the CONNECTED station
      to also kill the connection at that end of the link.
    - use Control-Left_click on the "CONNECT / DISCONNECT"
      button to initiate the forced reset.
  * Update ARQ icons
  * Disable auto-open flmsg when flmsg->flarq->fldigi data path
    is active.
pull/4/head
David Freese 2016-04-12 13:38:23 -05:00
rodzic 9c04f07877
commit 76ab77cd0c
13 zmienionych plików z 3077 dodań i 1148 usunięć

2287
data/flarq.pdf 100644

File diff suppressed because one or more lines are too long

Plik diff jest za duży Load Diff

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 12 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 361 KiB

Wyświetl plik

@ -35,19 +35,25 @@ $EXTRA_LIBS $FLXMLRPC_LIBS"
# CPPFLAGS
FLARQ_BUILD_CPPFLAGS="-I\$(srcdir) -I\$(srcdir)/include -I\$(srcdir)/fileselector \
-I\$(srcdir)/flarq-src -I\$(srcdir)/flarq-src/include"
if test "x$ac_cv_flxmlrpc" != "xyes"; then
FLARQ_BUILD_CPPFLAGS="$FLARQ_BUILD_CPPFLAGS -I\$(srcdir)/xmlrpcpp"
fi
# CXXFLAGS
FLARQ_BUILD_CXXFLAGS="$FLTK_CFLAGS $X_CFLAGS $MAC_UNIVERSAL_CFLAGS $INTL_CFLAGS $PTW32_CFLAGS \
$BFD_CFLAGS -pipe -Wall -fexceptions $OPT_CFLAGS $DEBUG_CFLAGS"
if test "x$target_mingw32" = "xyes"; then
FLARQ_BUILD_CXXFLAGS="-mthreads $FLARQ_BUILD_CXXFLAGS"
fi
if test "x$ac_cv_flxmlrpc" != "xyes"; then
FLARQ_BUILD_CXXFLAGS="$FLARQ_BUILD_CXXFLAGS -I\$(srcdir)/xmlrpcpp"
fi
# LDFLAGS
FLARQ_BUILD_LDFLAGS="$MAC_UNIVERSAL_LDFLAGS"
if test "x$target_mingw32" = "xyes"; then
FLARQ_BUILD_LDFLAGS="-mthreads $FLARQ_BUILD_LDFLAGS"
fi
# LDADD
FLARQ_BUILD_LDADD="$FLTK_LIBS $X_LIBS $INTL_LIBS $PTW32_LIBS $BFD_LIBS $EXTRA_LIBS"
FLARQ_BUILD_LDADD="$FLTK_LIBS $X_LIBS $INTL_LIBS $PTW32_LIBS $BFD_LIBS $EXTRA_LIBS $FLXMLRPC_LIBS"
if test "x$ac_cv_debug" = "xyes"; then
FLDIGI_BUILD_CXXFLAGS="$FLDIGI_BUILD_CXXFLAGS -UNDEBUG"

Wyświetl plik

@ -35,16 +35,25 @@ include/hamlib.h \
rigcontrol/hamlib.cxx \
include/rigclass.h \
rigcontrol/rigclass.cxx
XMLRPC_SRC = \
include/xmlrpc.h \
misc/xmlrpc.cxx
FLDIGI_WIN32_RES_SRC = fldigirc.rc
FLARQ_WIN32_RES_SRC = flarq-src/flarqrc.rc
COMMON_WIN32_RES_SRC = common.rc
BENCHMARK_SRC = include/benchmark.h misc/benchmark.cxx
REGEX_SRC = compat/regex.h compat/regex.c
STACK_SRC = include/stack.h misc/stack.cxx
MINGW32_SRC = include/compat.h compat/getsysinfo.c compat/mingw.c compat/mingw.h
NLS_SRC = misc/nls.cxx include/nls.h
# We distribute these but do not always compile them
@ -77,7 +86,7 @@ XMLRPCPP_SRC = \
EXTRA_fldigi_SOURCES = $(HAMLIB_SRC) $(XMLRPC_SRC) $(FLDIGI_WIN32_RES_SRC) $(COMMON_WIN32_RES_SRC) \
$(BENCHMARK_SRC) $(REGEX_SRC) $(STACK_SRC) $(MINGW32_SRC) $(NLS_SRC) $(XMLRPCPP_SRC)
EXTRA_flarq_SOURCES = $(FLARQ_WIN32_RES_SRC) $(COMMON_WIN32_RES_SRC)
EXTRA_flarq_SOURCES = $(FLARQ_WIN32_RES_SRC) $(COMMON_WIN32_RES_SRC) $(XMLRPCPP_SRC)
fldigi_SOURCES =
flarq_SOURCES =
@ -86,11 +95,16 @@ fldigi_SOURCES += $(XMLRPC_SRC)
if !ENABLE_FLXMLRPC
fldigi_SOURCES += $(XMLRPCPP_SRC)
flarq_SOURCES += $(XMLRPCPP_SRC)
else
fldigi_CPPFLAGS += @FLXMLRPC_CFLAGS@
fldigi_CXXFLAGS += @FLXMLRPC_CFLAGS@
fldigi_CFLAGS += @FLXMLRPC_CFLAGS@
fldigi_LDFLAGS += @FLXMLRPC_LIBS@
flarq_CPPFLAGS += @FLXMLRPC_CFLAGS@
flarq_CXXFLAGS += @FLXMLRPC_CFLAGS@
flarq_CFLAGS += @FLXMLRPC_CFLAGS@
flarq_LDFLAGS += @FLXMLRPC_LIBS@
endif
if ENABLE_HAMLIB
@ -734,11 +748,13 @@ flarq_SOURCES += \
flarq-src/b64.cxx \
flarq-src/flarq.cxx \
flarq-src/flarqenv.cxx \
flarq-src/xml_server.cxx \
flarq-src/include/arq.h \
flarq-src/include/arqdialogs.h \
flarq-src/include/b64.h \
flarq-src/include/flarq.h \
flarq-src/include/flarqenv.h \
flarq-src/include/xml_server.h \
include/Fl_Text_Display_mod.H \
include/Fl_Text_Editor_mod.H \
include/FTextView.h \

Wyświetl plik

@ -38,9 +38,9 @@ string RXIDENT = "RX: Link Still Active";
string RXCONREQ = "RX: Connect Request";
string RXCONACK = "RX: Connect OK";
string RXDISCONN = "RX: Disconnect Request";
string RXDISCONACK = "RX: Disconnect OK";
string RXDISCONACK = "RX: Disconnect OK";
string RXSTATUS = "RX: Status Report";
string RXPOLL = "RX: Send Blocks Report";
string RXPOLL = "RX: Send Blocks Report";
string TXSTATUS = "TX: Blocks Received OK";
string TXDISCONN = "TX: Disconnect Request";
string TXDISACK = "TX: Disconnect OK";
@ -69,12 +69,12 @@ arq::arq()
printRX_DEBUG = NULL;
printTX_DEBUG = NULL;
rxUrCall = NULL;
Header.erase();
MyStreamID = '0';
UrStreamID = '0';
UrCall.erase();
MyCall.erase();
@ -89,7 +89,7 @@ arq::arq()
TXflag = false;
SessionNumber = 0;
exponent = EXPONENT;
maxheaders = MAXHEADERS;
RetryTime = RETRYTIME;
@ -100,7 +100,7 @@ arq::arq()
primary = false;
setBufferlength();
// status variables //
// totalRx = 0;
@ -122,7 +122,7 @@ arq::arq()
UrLastHeader = MAXCOUNT - 1; // Other station's Header last sent
UrEndHeader = MAXCOUNT - 1; // Other station's last received Header
blkcount = -1;
TXflag = false; // TX on
LinkState = DOWN; // ARQ link is initially down
Sending = 0;
@ -131,7 +131,7 @@ arq::arq()
MyMissing.clear();
MissingRxBlocks = "";
TxBlocks.clear();
TxMissing.clear();
TxPending.clear();
@ -139,17 +139,17 @@ arq::arq()
RxPending.clear();
arqstop = false;
retries = baseRetries = Retries;
baseRetryTime = RetryTime;
baseTimeout = Timeout;
retrytime = RetryTime / ARQLOOPTIME;
timeout = Timeout / ARQLOOPTIME;
loopcount = 0;
tx2txdelay = 0;//TxDelay / ARQLOOPTIME;
// srand(time(NULL));
}
@ -196,14 +196,14 @@ void arq::reset()
// new session number
// unknown stream id = 0
// known id's from 1 to 63
void arq::newsession()
void arq::newsession()
{
if (++SessionNumber == 64) SessionNumber = 1;
MyStreamID = SessionNumber + '0';
}
// get new blocknumber
void arq::newblocknumber()
void arq::newblocknumber()
{
Lastqueued++;
Lastqueued %= MAXCOUNT;
@ -252,7 +252,7 @@ void arq::addToTxQue(string s)
// c Header = Client:port Server:port <streamnr. (0)> <max. Headerlen>
// e.g.: '00cW1HKJ:1025 KH6TY:24 4'
//
void arq::connectFrame()
void arq::connectFrame()
{
char szGlobals[24];
reset();
@ -280,9 +280,9 @@ void arq::connectFrame()
addToTxQue(Frame);
LinkState = CONNECTING;
LinkState = ARQ_CONNECTING;
printSTATUS(TXCONNECT, 5.0);
}
}
// Connect acknowledge (server:port, client:port)
@ -294,7 +294,7 @@ void arq::ackFrame ()
reset();
IdHeader();
Header += CONACK;
Payload.erase();
Payload.append(MyCall);
Payload.append(":24");
@ -304,7 +304,7 @@ void arq::ackFrame ()
Payload += MyStreamID;
Payload += ' ';
Payload += MyBlockLengthChar;
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
@ -317,11 +317,11 @@ void arq::ackFrame ()
// c Header = Caller:port static:port <streamnr. (0)> <max. Headerlen>
// e.g.: '00cW1HKJ:87 KH6TY:87 4'
//
void arq::ttyconnectFrame()
void arq::ttyconnectFrame()
{
UnkHeader();
Header += CONREQ;
Payload.erase();
Payload.append(MyCall);
Payload.append(":87");
@ -332,24 +332,24 @@ void arq::ttyconnectFrame()
Payload += MyStreamID;
Payload += ' ';
Payload += MyBlockLengthChar;
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
addToTxQue(Frame);
}
}
// Connect acknowledge (server:port, client:port)
// k Header = Server:port Client:port <streamnr.> <max. Headerlen>
// e.g: '00kKH6TY:87 W1HKJ 4'
// Service id # 87 is keyboard-to-keyboard
//
void arq::ttyackFrame()
void arq::ttyackFrame()
{
IdHeader();
Header += CONACK;
Payload.erase();
Payload.append(MyCall);
Payload.append(":87");
@ -357,7 +357,7 @@ void arq::ttyackFrame()
Payload.append(UrCall);
Payload += ' ';
Payload += MyBlockLengthChar;
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
@ -371,12 +371,12 @@ void arq::identFrame()
{
IdHeader();
Header += IDENT;
Payload.erase();
Payload.append(UrCall);
Payload.append(" de ");
Payload.append(MyCall);
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
@ -386,7 +386,7 @@ void arq::identFrame()
char szIDENT[80];
snprintf(szIDENT,sizeof(szIDENT), TXIDENT.c_str(), retries);
printSTATUS(szIDENT, 5.0);
}
// e.g. Ping frame
@ -396,27 +396,27 @@ void arq::pingFrame()
{
IdHeader();
Header += _UNPROTO;
Payload.erase();
Payload.append(MyCall);
Payload.append(":7");
Payload += ' ';
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
addToTxQue(Frame);
}
// talk frame
// similar to UNPROTO frame
// but only sent if CONNECTED
// but only sent if ARQ_CONNECTED
void arq::talkFrame(string txt)
{
IdHeader();
Header += _TALK;
Payload.erase();
Payload.append(MyCall);
Payload.append(":73");
@ -442,11 +442,11 @@ void arq::ackAbortFrame()
Payload += (GoodHeader + 0x20);
Payload += (EndHeader + 0x20);
Payload.append(MissingRxBlocks);
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
addToTxQue(Frame);
printSTATUS(TXSTATUS, 5.0);
}
@ -455,7 +455,7 @@ void arq::ackAbortFrame()
//p frame = <last Header tx><last Header rx ok><last Header rx> <missing Headers>
//e.g.: '00sXHCAB'
//
void arq::statFrame()
void arq::statFrame()
{
IdHeader();
Header += STATUS;
@ -465,11 +465,11 @@ void arq::statFrame()
Payload += (GoodHeader + 0x20);
Payload += (EndHeader + 0x20);
Payload.append(MissingRxBlocks);
Frame = Header + Payload;
Frame = Frame + checksum(Frame);
Frame += EOT;
addToTxQue(Frame);
printSTATUS(TXSTATUS, 5.0);
}
@ -498,7 +498,7 @@ void arq::disackFrame()
{
IdHeader();
Header += _DISACK;
Payload.erase();
Payload.append(MyCall);
Payload.append(":91");
@ -531,7 +531,7 @@ void arq::abortFrame()
// u Header = From:port data
// e.g: '00uKH6TY:72 Beacon text '
//
void arq::beaconFrame(string txt)
void arq::beaconFrame(string txt)
{
UnkHeader();
Header += _UNPROTO;
@ -555,7 +555,7 @@ void arq::beaconFrame(string txt)
// poll
//p frame = <last Header tx><last Header rx ok><last Header rx> <missing Headers>
//e.g.: '00pXHCAB'
void arq::pollFrame()
void arq::pollFrame()
{
IdHeader();
@ -603,8 +603,8 @@ void arq::parseCONREQ()
size_t p1 = 0, p2 = rcvPayload.find(':');
if (p2 == string::npos)
return;
// if (LinkState == CONNECTED || LinkState == WAITFORACK) return; // disallow multiple connects
// if (LinkState == ARQ_CONNECTED || LinkState == WAITFORACK) return; // disallow multiple connects
// requesting stations callsign
UrCall = upcase(rcvPayload.substr(p1, p2 - p1));
p1 = rcvPayload.find(' ', p2+1);
@ -631,7 +631,7 @@ void arq::parseCONREQ()
UrStreamID = rcvPayload[p1];
p1++; // *p1 ==> requested block size
UrBlockLengthChar = rcvPayload[p1];
p1 += 3; // *p1 ==>" TnnnRnnnWnnn"
if (p1 < rcvPayload.length()) {
char num[7];
@ -655,7 +655,7 @@ void arq::parseCONREQ()
Timeout += Retries * RetryTime;
}
}
/*
/*
char line[80];
string NewValues = "Temporary control parameters set to\n";
snprintf(line, 79, " Retries = %d\n", Retries);
@ -668,15 +668,15 @@ void arq::parseCONREQ()
*/
}
}
reset();
LinkState = WAITFORACK;
newsession();
if (rxUrCall) rxUrCall(UrCall);
if (rxUrCall) rxUrCall(UrCall);
TxTextQueue.clear();//erase();
TxTextQueue.clear();
ackFrame();
immediate = true;
printSTATUS(RXCONREQ, 5.0);
@ -685,10 +685,10 @@ void arq::parseCONREQ()
void arq::parseCONACK()
{
if (LinkState < CONNECTING ) { //!= CONNECTING) {
if (LinkState < ARQ_CONNECTING ) { //!= ARQ_CONNECTING) {
return; // Connect Acknowledge only valid during a connect
}
size_t p1 = 0, p2 = rcvPayload.find(':');
// LinkState = DOWN;
if (p2 == string::npos)
@ -708,7 +708,7 @@ void arq::parseCONACK()
UrCall.erase();
return;
}
p1++; // *p1 ==> StreamID for requesting station
UrStreamID = rcvPayload[p1];
p1++; // *p1 ==> requested block size
@ -716,9 +716,9 @@ void arq::parseCONACK()
RxTextQueue.clear();//erase();
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
timeout = Timeout / ARQLOOPTIME;
statFrame();
immediate = true;
primary = true;
@ -753,14 +753,14 @@ void arq::parseABORT()
if (abortfnc) abortfnc();
ackAbortFrame();
immediate = true;
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
}
void arq::parseACKABORT()
{
reset();
if (abortfnc) abortfnc();
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
}
void arq::parseUNPROTO()
@ -787,7 +787,7 @@ void arq::parseSTATUS()
{
// create the missing list
// all reported missing blocks
if (LinkState >= CONNECTED) {
if (LinkState >= ARQ_CONNECTED) {
UrLastHeader = rcvPayload[0] - 0x20; // Other station's Header last sent
UrGoodHeader = rcvPayload[1] - 0x20; // Other station's Good Header
UrEndHeader = rcvPayload[2] - 0x20; // Other station's last received Header
@ -809,10 +809,10 @@ void arq::parseSTATUS()
}
missing.push_back(LastHeader);
}
if (missing.empty())
TxMissing.clear();
TxMissing.clear();
if (TxMissing.empty() == false) {
list<cTxtBlk> keep;
list<cTxtBlk>::iterator p = TxMissing.begin();
@ -846,19 +846,19 @@ void arq::parseSTATUS()
switch (LinkState) {
case WAITFORACK :
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
break;
case DISCONNECTING :
if (rxUrCall) rxUrCall("");
LinkState = DOWN;
break;
case WAITING :
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
break;
// case ABORTING :
// reset();
// if (abortfnc) abortfnc();
// LinkState = CONNECTED;
// LinkState = ARQ_CONNECTED;
// break;
// case ABORT :
// break;
@ -871,12 +871,12 @@ void arq::parseSTATUS()
void arq::parsePOLL()
{
if (LinkState == DISCONNECTING || LinkState == DOWN ||
LinkState == TIMEDOUT || LinkState == ABORT )
LinkState == TIMEDOUT || LinkState == ABORT )
return;
statFrame();
immediate = true;
LinkState = CONNECTED;
LinkState = ARQ_CONNECTED;
printSTATUS(RXPOLL, 5.0);
}
@ -884,18 +884,18 @@ void arq::parseDATA()
{
vector<cTxtBlk>::iterator p1, p2;
int n1, n2;
if (LinkState < CONNECTED) return; // do not respond if DOWN or TIMEDOUT
for (p1 = RxPending.begin(); p1 < RxPending.end(); p1++)
if (LinkState < ARQ_CONNECTED) return; // do not respond if DOWN or TIMEDOUT
for (p1 = RxPending.begin(); p1 < RxPending.end(); p1++)
if (blknbr == p1->nbr()) {
return;
}
char szStatus[80];
snprintf(szStatus, sizeof(szStatus),"RX: data block %d", blknbr);
printSTATUS(szStatus, 5.0);
cTxtBlk tempblk(blknbr, rcvPayload);
RxPending.push_back (tempblk);
@ -920,7 +920,7 @@ void arq::parseDATA()
}
// add RxPending blocks that are consecutive to GoodHeader
p1 = RxPending.begin();
p1 = RxPending.begin();
while (!RxPending.empty()) {
if ((p1->nbr() != (GoodHeader +1) % MAXCOUNT))
break;
@ -988,14 +988,14 @@ int arq::parseFrame(string txt)
// treat unproto TALK as a special case
// no effort made to confirm the data by the CRC value
if (fID == _TALK) {
if (LinkState >= CONNECTED) {
if (LinkState >= ARQ_CONNECTED) {
timeout = Timeout / ARQLOOPTIME;
parseTALK();
retries = Retries;
}
return -1;
}
string sRcvdCRC = testcrc.scrc16( txt.substr(0, len - 4));
if (sRcvdCRC != txt.substr(len - 4) ) {
@ -1007,7 +1007,7 @@ int arq::parseFrame(string txt)
retries = Retries;
switch (fID) {
case IDENT :
case IDENT :
if (!isUrcall())
break;
blknbr = fID - 0x20;
@ -1016,8 +1016,8 @@ int arq::parseFrame(string txt)
printRX_DEBUG("IDENT:");
}
break;
case CONREQ :
if (LinkState > TIMEDOUT)
case CONREQ :
if (LinkState > TIMEDOUT)
break; // disallow multiple connects
blknbr = fID - 0x20;
parseCONREQ();
@ -1104,11 +1104,11 @@ int arq::parseFrame(string txt)
}
}
if (printRX_DEBUG) {
printRX_DEBUG(txt); printRX_DEBUG("\n");
printRX_DEBUG(txt); printRX_DEBUG("\n");
}
if (LinkState == CONNECTED)
if (LinkState == ARQ_CONNECTED)
timeout = Timeout / ARQLOOPTIME;
return fID;
@ -1124,10 +1124,10 @@ void arq::rcvChar( char c )
tx2txdelay = TxDelay / ARQLOOPTIME;
return;
}
if (lastRxChar == SOH && c == SOH) // consecutive <SOH> characters
return;
if (lastRxChar == EOT && c == EOT) // consecutive <EOT> characters
return;
@ -1142,7 +1142,7 @@ void arq::rcvChar( char c )
} else
RxFrameQueue += c;
}
lastRxChar = c;
}
@ -1152,8 +1152,8 @@ void arq::sendText (string txt)
{
size_t offset = 0;
cTxtBlk tempblk;
if (LinkState < CONNECTED) return;
if (LinkState < ARQ_CONNECTED) return;
Blocks2Send = 0;
while (offset < txt.length()) {
newblocknumber();
@ -1171,7 +1171,7 @@ void arq::sendblocks()
int missedblks = 0, newblks = 0;
int framecount = 0;
cTxtBlk tempblk;
if (TxMissing.empty() == false) {
list<cTxtBlk>::iterator p = TxMissing.begin();
while (p != TxMissing.end()) {
@ -1205,7 +1205,7 @@ void arq::sendblocks()
if (LinkState != ABORT && LinkState != ABORTING)
LinkState = WAITING;
}
void arq::connect(string callsign)
{
UrCall = callsign;
@ -1215,7 +1215,7 @@ void arq::connect(string callsign)
if (rxUrCall) rxUrCall(UrCall);
TxTextQueue.clear();
connectFrame();
LinkState = CONNECTING;
LinkState = ARQ_CONNECTING;
immediate = true;
}
@ -1226,7 +1226,7 @@ void arq::disconnect()
RetryTime = baseRetryTime;
totalTx = 0;
nbrbadTx = 0;
LinkState = DISCONNECT;
}
@ -1289,7 +1289,7 @@ void arqloop(void *who)
{
arq *me = (arq *)who;
char c;
// check for received chars including 0x06 for Sending = 0
if (me->getc1(c) == true) {
me->rcvChar(c);
@ -1310,7 +1310,7 @@ void arqloop(void *who)
me->immediate = false;
} else {
switch (me->LinkState) {
case CONNECTING :
case ARQ_CONNECTING :
break;
case DISCONNECT :
me->LinkState = DISCONNECTING;
@ -1320,7 +1320,7 @@ void arqloop(void *who)
me->TxPlainTextQueue.clear();
me->disconnectFrame();
me->immediate = true;
break;
break;
case DISCONNECTING :
if (me->retrytime-- == 0) {
me->retrytime = me->rtry();
@ -1383,8 +1383,8 @@ void arqloop(void *who)
}
}
break;
case CONNECTED :
case ARQ_CONNECTED :
default:
if (me->TxTextQueue.empty() == false) {
me->transmitdata();
@ -1399,7 +1399,7 @@ void arqloop(void *who)
}
me->timeout--;
if (me->timeout == 0 // 10000 / ARQLOOPTIME // 10 seconds remaining
&& me->LinkState == CONNECTED // link is connected
&& me->LinkState == ARQ_CONNECTED // link is connected
&& me->primary == true ) { // this is the connecting station
if (--me->retries) { // repeat Retries and then allow timeout
me->TxTextQueue.clear();
@ -1409,14 +1409,14 @@ void arqloop(void *who)
}
}
if (me->timeout == 0) {
if (me->LinkState == CONNECTED)
if (me->LinkState == ARQ_CONNECTED)
me->LinkState = TIMEDOUT;
else
me->LinkState = DOWN;
me->Retries = me->baseRetries;
me->Timeout = me->baseTimeout;
me->RetryTime = me->baseRetryTime;
me->retries = me->Retries;
me->retrytime = me->rtry();
me->TxMissing.clear();
@ -1446,8 +1446,29 @@ void arqloop(void *who)
}
}
if (me->arqstop)
if (me->arqstop) {
me->LinkState = STOPPED;
me->arqstop = false;
me->LinkState = DOWN;
me->Retries = me->baseRetries;
me->Timeout = me->baseTimeout;
me->RetryTime = me->baseRetryTime;
me->retries = me->Retries;
me->retrytime = me->rtry();
me->TxMissing.clear();
me->TxBlocks.clear();
me->TxTextQueue.clear();
me->TxPlainTextQueue.clear();
me->timeout = me->Timeout / ARQLOOPTIME;
if (me->rxUrCall) me->rxUrCall("");
me->printSTATUS(STIMEDOUT, 10.0);
Fl::repeat_timeout( 1.0, arqloop, me);
return;
}
Fl::repeat_timeout( ARQLOOPTIME/1000.0, arqloop, me);
}
@ -1458,4 +1479,8 @@ void arq::start_arq()
Fl::add_timeout(1.0, arqloop, this);
}
void arq::restart_arq() {
arqstop = true;
}
//---------------------------------------------------------------------

Wyświetl plik

@ -77,9 +77,13 @@
#include "b64.h"
#include "gettext.h"
#include "xml_server.h"
#define FLDIGI_port "7322"
#define MPSK_port "3122"
#define FLARQ_XML_PORT 7422
#define MPSK_TX "TX"
#define MPSK_RX "RX"
#define MPSK_TX2RX "RX_AFTER_TX"
@ -946,6 +950,7 @@ void arqCLOSE()
{
tcpip->close();
saveConfig();
exit_server();
exit(0);
}
@ -974,7 +979,14 @@ void restart()
void arqCONNECT()
{
if (digi_arq->state() < CONNECTED) {
int state = Fl::event_state();
if ((state & FL_CTRL) == FL_CTRL) {
digi_arq->restart_arq();
txtURCALL->value("");
restart();
return;
}
if (digi_arq->state() < ARQ_CONNECTED) {
if (strlen(txtURCALL->value()) > 0)
digi_arq->connect(txtURCALL->value());
} else {
@ -1140,7 +1152,6 @@ void payloadText(string s)
}
if (incomingText.find(arqemail) != string::npos)
haveemail = true;
incomingText = "";
startpos = string::npos;
endpos = string::npos;
fnamepos = string::npos;
@ -1151,6 +1162,9 @@ void payloadText(string s)
rxARQfile = false;
rxARQhavesize = false;
rxTextReady = true;
if (incomingText.find("FLMSG_XFR") != std::string::npos)
xml_rx_text_ready = true;
incomingText = "";
txtStatus->value("");
prgStatus->value(0.0);
prgStatus->label("");
@ -1220,7 +1234,7 @@ void moveEmailFile()
void sendEmailFile()
{
if (arqstate < CONNECTED) {
if (arqstate < ARQ_CONNECTED) {
fl_alert2("Not connected");
return;
}
@ -1284,7 +1298,7 @@ void sendEmailFile()
void sendAsciiFile()
{
if (arqstate < CONNECTED) {
if (arqstate < ARQ_CONNECTED) {
fl_alert2("Not connected");
return;
}
@ -1336,7 +1350,7 @@ void sendAsciiFile()
void sendImageFile()
{
if (arqstate < CONNECTED) {
if (arqstate < ARQ_CONNECTED) {
fl_alert2("Not connected");
return;
}
@ -1385,7 +1399,7 @@ void sendImageFile()
void sendBinaryFile()
{
if (arqstate < CONNECTED) {
if (arqstate < ARQ_CONNECTED) {
fl_alert2("Not connected");
return;
}
@ -1432,6 +1446,43 @@ void sendBinaryFile()
sendingfile = false;
}
void send_xml_text(std::string fname, std::string txt)
{
if (arqstate < ARQ_CONNECTED) {
fl_alert2("Not connected");
return;
}
size_t txtsize;
char sizemsg[40];
if (!txt.empty()) {
TX.erase();
TX.append(arqfile);
TX.append(fname);
TX.append("\n");
TX.append(arqascii);
txtsize = txt.length();
arqPayloadSize = txtsize;
blocksSent = 0;
snprintf(sizemsg, sizeof(sizemsg), "ARQ:SIZE::%d\n",
static_cast<int>(txtsize));
TX.append(sizemsg);
TX.append(arqstart);
TX.append(txt);
TX.append(arqend);
traffic = true;
sendingfile = true;
statusmsg = "Sending XML payload: ";
statusmsg.append(fname);
txtStatus->value(statusmsg.c_str());
cbClearText();
return;
}
traffic = false;
sendingfile = false;
}
char statemsg[80];
void dispState()
@ -1450,7 +1501,7 @@ void dispState()
// mnuSend->deactivate();
mnu->redraw();
}
else if (arqstate == CONNECTED || arqstate == WAITING) {
else if (arqstate == ARQ_CONNECTED || arqstate == WAITING) {
if (btnCONNECT->active())
btnCONNECT->label("Disconnect");
if (!autobeacon)
@ -1467,7 +1518,7 @@ void dispState()
if (currstate <= 0x7F) // receiving
switch (currstate) {
case CONNECTING :
case ARQ_CONNECTING :
snprintf(statemsg, sizeof(statemsg), "CONNECTING: %d", digi_arq->getTimeLeft());
txtState->value(statemsg);
txtState->redraw();
@ -1486,7 +1537,7 @@ void dispState()
autobeacon = false;
break;
case WAITING :
case CONNECTED :
case ARQ_CONNECTED :
char szState[80];
snprintf(szState, sizeof(szState),"CONNECTED - Quality = %4.2f",
digi_arq->quality());
@ -1573,7 +1624,7 @@ void mainloop(void *)
if (rxTextReady) {
if (haveemail)
saveEmailFile();
else
else if (!xml_rx_text_ready)
saveRxFile();
}
Fl::repeat_timeout(0.1, mainloop);
@ -1893,6 +1944,8 @@ int main (int argc, char *argv[] )
arqwin->icon((char *)flarq_icon_pixmap);
#endif
start_xml_server(FLARQ_XML_PORT);
arqwin->show(argc, argv);
return Fl::run();
}

Wyświetl plik

@ -27,13 +27,13 @@
// generic Frame format:
// <SOH>dcl[info])12EF<EOT|SOH>
// | ||| | | |
// | ||| | | +--ASCII <SOH> or <EOT> (0x04) character
// | ||| | | +--ASCII <SOH> or <EOT> (0x04) character
// | ||| | +-------checksum (4xAlphaNum)
// | ||| +-------------Payload (1 ... 2^N chars, N 4, 5, 6, 7 8)
// | ||+---------------Block type
// | ||+---------------Block type
// | |+----------------Stream id
// | +-----------------Protocol version number
// +---------------------ASCII <SOH> (0x01) character
// +---------------------ASCII <SOH> (0x01) character
// BLOCKSIZE = 2^n
//
@ -88,19 +88,33 @@ using namespace std;
#define ARQLOOPTIME 100 // # msec for loop timing
//=====================================================================
//link states
#define DOWN 0
#define TIMEDOUT 1
#define ABORT 3
#define CONNECTING 4
#define CONNECTED 5
#define WAITING 6
#define WAITFORACK 7
#define DISCONNECT 8
#define DISCONNECTING 9
#define ABORTING 10
enum LINK_STATES {
DOWN = 0,
TIMEDOUT,
ABORT,
ARQ_CONNECTING,
ARQ_CONNECTED,
WAITING,
WAITFORACK,
DISCONNECT,
DISCONNECTING,
ABORTING,
STOPPED
};
//#define DOWN 0
//#define TIMEDOUT 1
//#define ABORT 3
//#define ARQ_CONNECTING 4
//#define ARQ_CONNECTED 5
//#define WAITING 6
//#define WAITFORACK 7
//#define DISCONNECT 8
//#define DISCONNECTING 9
//#define ABORTING 10
#define SENDING 0x80;
//=====================================================================
extern char *ARQASCII[];
@ -129,8 +143,8 @@ public:
crcval = (crcval >> 1);
}
}
unsigned int crc16(char c) {
update(c);
unsigned int crc16(char c) {
update(c);
return crcval;
}
unsigned int crc16(string s) {
@ -166,7 +180,7 @@ public:
class arq {
private:
bool arqstop;
bool arqstop;
string MyCall;
string UrCall;
@ -175,18 +189,18 @@ private:
string Frame;
string Payload;
string rcvPayload;
string logfile;
char MyStreamID;
char UrStreamID;
char MyBlockLengthChar;
char UrBlockLengthChar;
char BlockNumberChar;
char fID;
int blknbr;
// queues //
string TxTextQueue; // Text out to mail engine
string TxPlainTextQueue; // plain text transmit queu
@ -219,14 +233,14 @@ private:
int tx2txdelay;
int TxDelay;
int loopcount;
int baseRetryTime;
int baseTimeout;
int baseRetries;
bool immediate;
bool primary;
Ccrc16 framecrc;
// My status
@ -242,7 +256,7 @@ private:
vector<int> MyMissing; // missing Rx blocks
string MissingRxBlocks;
vector<cTxtBlk> RxPending; // RxPending Rx blocks (not consecutive)
list<cTxtBlk> TxBlocks; // fifo of transmit buffers
list<cTxtBlk> TxMissing; // fifo of sent; RxPending Status report
list<cTxtBlk> TxPending; // fifo of transmitted buffers pending print
@ -255,20 +269,19 @@ private:
int LinkState; // status of ARQ link
int Sending;
bool bABORT;
// Link quality for sending *** used for testing only !! ***
// double sendquality;
void reset();
void resetTx();
void resetRx();
int rtry();
void setBufferlength();
void checkblocks();
string upcase(string s);
void newblocknumber();
@ -291,12 +304,12 @@ private:
void beaconFrame(string txt);
void textFrame(cTxtBlk block);
void talkFrame(string txt);
void addToTxQue(string s);
void sendblocks();
void transmitdata();
string frame() {return Frame;}
bool isUrcall();
@ -315,8 +328,8 @@ private:
void parseTALK();
int parseFrame(string txt);
// external functions called by arq class
// external functions called by arq class
void (*sendfnc)(const string& s);
bool (*getc1)(char &);
void (*rcvfnc)();
@ -330,7 +343,7 @@ private:
void (*rxUrCall)(string s);
void (*qualityfnc)(string s);
void (*printSTATUS)(string s, double disptime);
public:
arq();
~arq() {};
@ -338,33 +351,35 @@ public:
friend void arqloop(void *me);
void start_arq();
void restart_arq();
string checksum(string &s);
void myCall(string s) { MyCall = upcase(s);}
string myCall() { return MyCall;}
void urCall(string s) { UrCall = s;}
string urCall() { return UrCall;}
void newsession();
void setSendFunc( void (*f)(const string& s)) { sendfnc = f;}
void setGetCFunc( bool (*f)(char &)) { getc1 = f;}
void setRcvFunc( void (*f)()) { rcvfnc = f;}
void setPrintRX( void (*f)(string s)) { printRX = f;}
void setPrintTX( void (*f)(string s)) { printTX = f;}
void setPrintTALK (void (*f)(string s)) {printTALK = f;}
void setPrintRX_DEBUG (void (*f)(string s)){printRX_DEBUG = f;}
void setPrintTX_DEBUG (void (*f)(string s)) {printTX_DEBUG = f;}
void setPrintSTATUS (void (*f)(string s, double disptime)) { printSTATUS = f;}
void setMaxHeaders( int mh ) { maxheaders = mh; }
void setExponent( int exp ) { exponent = exp; setBufferlength(); }
int getExponent() { return (int) exponent;}
void setWaitTime( int rtime ) { RetryTime = rtime; baseRetryTime = rtime; }
int getWaitTime() { return (int) RetryTime; }
void setRetries ( int rtries ) {
void setRetries ( int rtries ) {
retries = Retries = baseRetries = rtries; }
int getRetries() { return (int) Retries; }
void setTimeout ( int tout ) { Timeout = tout; baseTimeout = tout; }
@ -378,41 +393,41 @@ public:
void setQualityValue( void (*f)(string s)) { qualityfnc = f;}
void setAbortedTransfer( void (*f)()) { abortfnc = f;};
void setDisconnected( void (*f)()) { disconnectfnc = f;};
void rcvChar( char c );
void connect(string callsign);//, int blocksize = 6, int retries = 4);
void sendblocks( string txt );
void sendBeacon (string txt);
void sendPlainText( string txt );
string getText() { return RxTextQueue;}
void sendText(string txt);
bool connected() { return (LinkState == CONNECTED); }
bool connected() { return (LinkState == ARQ_CONNECTED); }
void disconnect();
void abort();
int state() { return (LinkState + Sending);}
int TXblocks() { return totalTx;}
int TXbad() { return nbrbadTx;}
int RXblocks() { return totalRx;}
int RXbad() { return nbrbadRx;}
double quality() {
double quality() {
if (totalTx == 0) return 1.0;
return ( 1.0 * (totalTx - nbrbadTx) / totalTx );
}
float percentSent() {
if (Blocks2Send == 0) return 0.0;
if ((TxBlocks.empty() && TxMissing.empty())) return 1.0;
return (1.0 * (Blocks2Send - TxBlocks.size() - TxMissing.size()) / Blocks2Send);
}
bool transferComplete() {
if (TxMissing.empty() == false) return false;
if (TxBlocks.empty() == false) return false;

Wyświetl plik

@ -47,10 +47,19 @@ extern long iwaittime;
extern long itimeout;
extern int bcnInterval;
// used by xmlrpc interface
extern int arqstate;
extern bool sendingfile;
extern bool rxTextReady;
extern bool rxARQfile;
extern std::string txtarqload;
extern void cb_SaveComposeMail();
extern void cb_CancelComposeMail();
extern void cb_UseTemplate();
extern void cb_OpenComposeMail();
extern void ComposeMail();
extern void send_xml_text(std::string, std::string);
#endif

Wyświetl plik

@ -0,0 +1,51 @@
// ---------------------------------------------------------------------
//
// xml_server.h, a part of flarq
//
// Copyflarqht (C) 2016
// Dave Freese, W1HKJ
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library 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 the program; if not, write to the
//
// Free Software Foundation, Inc.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// ---------------------------------------------------------------------
#ifndef XML_SERVER_H
#define XML_SERVER_H
#include <fstream>
#include <vector>
#include <string>
#include <math.h>
#ifndef WIN32
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#endif
#include "status.h"
#include <FL/fl_show_colormap.H>
#include <FL/fl_ask.H>
extern void start_xml_server(int port = 12345);
extern void exit_server();
extern bool xml_rx_text_ready;
#endif

Wyświetl plik

@ -0,0 +1,216 @@
// ---------------------------------------------------------------------
//
// xml_server.cxx, a part of flarq
//
// Copyflarqht (C) 2016
// Dave Freese, W1HKJ
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library 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 the program; if not, write to the
//
// Free Software Foundation, Inc.
// 51 Franklin Street, Fifth Floor
// Boston, MA 02110-1301 USA.
//
// ---------------------------------------------------------------------
#include <config.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Enumerations.H>
//#include "support.h"
//#include "debug.h"
#include "arq.h"
#include "flarq.h"
#include "xml_server.h"
#include "xmlrpcpp/XmlRpc.h"
using namespace XmlRpc;
// The server
XmlRpcServer flarq_server;
//----------------------------------------------------------------------
// get interface
//----------------------------------------------------------------------
bool xml_rx_text_ready = false;
//----------------------------------------------------------------------
// Request for flarq version
//----------------------------------------------------------------------
class flarq_get_version : public XmlRpcServerMethod {
public:
flarq_get_version(XmlRpcServer* s) : XmlRpcServerMethod("flarq.get_version", s) {}
void execute(XmlRpcValue& params, XmlRpcValue& result) {
result = VERSION;
}
std::string help() { return std::string("returns version number of flarq"); }
} flarq_get_version(&flarq_server);
//----------------------------------------------------------------------
// Request for ARQ state
//----------------------------------------------------------------------
class flarq_get_state : public XmlRpcServerMethod {
public:
flarq_get_state(XmlRpcServer* s) : XmlRpcServerMethod("flarq.get_state", s) {}
// x00 - unconnected
// x81 - connected
// x82 - sending
// x83 - receiving
// x84 - send completed
// x85 - recv completed
void execute(XmlRpcValue& params, XmlRpcValue& result) {
int state = 0;
if (arqstate != ARQ_CONNECTED)
state = 0;
else if (sendingfile)
state = 0x82;
else if (rxARQfile)
state = 0x83;
else if (xml_rx_text_ready)
state = 0x85;
else
state = 0x81;
result = state;
}
std::string help() { return std::string("returns state of connection"); }
} flarq_get_state(&flarq_server);
//----------------------------------------------------------------------
// Request for received text
//----------------------------------------------------------------------
class flarq_rcvd_text : public XmlRpcServerMethod {
public:
flarq_rcvd_text(XmlRpcServer* s) : XmlRpcServerMethod("flarq.rcvd_text", s) {}
void execute(XmlRpcValue& params, XmlRpcValue& result) {
std::string result_string = "none";
if (xml_rx_text_ready) result_string = txtarqload;
xml_rx_text_ready = false;
result = result_string;
txtarqload = "";
}
std::string help() { return std::string("returns received text"); }
} flarq_rcvd_text(&flarq_server);
//----------------------------------------------------------------------
// set interface
//----------------------------------------------------------------------
//------------------------------------------------------------------------------
// Send text
//------------------------------------------------------------------------------
class flarq_send_text : public XmlRpcServerMethod {
public:
flarq_send_text(XmlRpcServer* s) : XmlRpcServerMethod("flarq.send_text", s) {}
void execute(XmlRpcValue& params, XmlRpcValue &result) {
std::string txt_to_send = string(params[0]);
send_xml_text("FLMSG_XFR", txt_to_send);
}
std::string help() { return std::string("send_text"); }
} flarq_send_text(&flarq_server);
struct MLIST {
string name; string signature; string help;
} mlist[] = {
{ "flarq.rcvd_text", "s:n", "return MODE of current VFO" },
{ "flarq.get_state", "s:n", "return PTT state" },
{ "flarq.send_text", "i:i", "set MODE iaw MODE table" }
};
class flarq_list_methods : public XmlRpcServerMethod {
public:
flarq_list_methods(XmlRpcServer *s) : XmlRpcServerMethod("flarq.list_methods", s) {}
void execute(XmlRpcValue& params, XmlRpcValue& result) {
vector<XmlRpcValue> methods;
for (size_t n = 0; n < sizeof(mlist) / sizeof(*mlist); ++n) {
XmlRpcValue::ValueStruct item;
item["name"] = mlist[n].name;
item["signature"] = mlist[n].signature;
item["help"] = mlist[n].help;
methods.push_back(item);
}
result = methods;
}
std::string help() { return std::string("get flarq methods"); }
} flarq_list_methods(&flarq_server);
//------------------------------------------------------------------------------
// support thread xmlrpc clients
//------------------------------------------------------------------------------
pthread_t *xml_thread = 0;
void * xml_thread_loop(void *d)
{
for(;;) {
flarq_server.work(-1.0);
}
return NULL;
}
void start_xml_server(int port)
{
XmlRpc::setVerbosity(0);
// Create the server socket on the specified port
flarq_server.bindAndListen(port);
// Enable introspection
flarq_server.enableIntrospection(true);
xml_thread = new pthread_t;
if (pthread_create(xml_thread, NULL, xml_thread_loop, NULL)) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
void exit_server()
{
flarq_server.exit();
}

Wyświetl plik

@ -62,13 +62,14 @@ Save tags and all enclosed text to date-time stamped file, ie:\n\
~/.nbems/WRAP/recv/extract-20090127-092515.wrap");
#endif
#define bufsize 16
#define bufsize 32
char rx_extract_buff[bufsize + 1];
string rx_buff;
string rx_extract_msg;
bool extract_wrap = false;
bool extract_flamp = false;
bool extract_arq = false;
bool bInit = false;
@ -81,6 +82,7 @@ void rx_extract_reset()
rx_extract_buff[bufsize] = 0;
extract_wrap = false;
extract_flamp = false;
extract_arq = false;
put_status("");
}
@ -286,16 +288,40 @@ void rx_extract_add(int c)
memmove(rx_extract_buff, &rx_extract_buff[1], bufsize - 1);
rx_extract_buff[bufsize - 1] = ch;
if ( strstr(rx_extract_buff, wrap_beg) && !extract_flamp) {
if (!extract_arq && strstr(rx_extract_buff, "ARQ:FILE::FLMSG_XFR")) {
extract_arq = true;
REQ(rx_remove_timer);
REQ(rx_add_timer);
memset(rx_extract_buff, ' ', bufsize);
rx_extract_msg = "Extracting ARQ msg";
put_status(rx_extract_msg.c_str());
return;
} else if (extract_arq) {
REQ(rx_remove_timer);
REQ(rx_add_timer);
if (strstr(rx_extract_buff, "ARQ::ETX"))
rx_extract_reset();
return;
} else if (!extract_flamp && strstr(rx_extract_buff, flamp_beg)) {
extract_flamp = true;
memset(rx_extract_buff, ' ', bufsize);
rx_extract_msg = "Extracting FLAMP";
put_status(rx_extract_msg.c_str());
return;
} else if (extract_flamp) {
REQ(rx_remove_timer);
REQ(rx_add_timer);
if (strstr(rx_extract_buff, flamp_end) != NULL)
rx_extract_reset();
return;
} else if (!extract_wrap && strstr(rx_extract_buff, wrap_beg)) {
rx_buff.assign(wrap_beg);
rx_extract_msg = "Extracting WRAP/FLMSG";
put_status(rx_extract_msg.c_str());
memset(rx_extract_buff, ' ', bufsize);
extract_wrap = true;
REQ(rx_remove_timer);
REQ(rx_add_timer);
return;
} else if (extract_wrap) {
rx_buff += ch;
REQ(rx_remove_timer);
@ -304,16 +330,6 @@ void rx_extract_add(int c)
invoke_flmsg();
rx_extract_reset();
}
} else if (strstr(rx_extract_buff, flamp_beg) && ! extract_wrap) {
extract_flamp = true;
rx_extract_msg = "Extracting FLAMP";
put_status(rx_extract_msg.c_str());
} else if (extract_flamp == true) {
REQ(rx_remove_timer);
REQ(rx_add_timer);
if (strstr(rx_extract_buff, flamp_end) != NULL) {
rx_extract_reset();
}
}
}