1 #ifndef arq_H 2 #define arq_H 3 4 // ---------------------------------------------------------------------------- 5 // arq module arq.h 6 // Copyright (c) 2007-2009, Dave Freese, W1HKJ 7 // 8 // 9 // This file is part of fldigi. 10 // 11 // Fldigi is free software: you can redistribute it and/or modify 12 // it under the terms of the GNU General Public License as published by 13 // the Free Software Foundation, either version 3 of the License, or 14 // (at your option) any later version. 15 // 16 // Fldigi is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU General Public License for more details. 20 // 21 // You should have received a copy of the GNU General Public License 22 // along with fldigi. If not, see <http://www.gnu.org/licenses/>. 23 // ---------------------------------------------------------------------------- 24 25 // link layer spec for fldigi_arq 26 // 27 // generic Frame format: 28 // <SOH>dcl[info])12EF<EOT|SOH> 29 // | ||| | | | 30 // | ||| | | +--ASCII <SOH> or <EOT> (0x04) character 31 // | ||| | +-------checksum (4xAlphaNum) 32 // | ||| +-------------Payload (1 ... 2^N chars, N 4, 5, 6, 7 8) 33 // | ||+---------------Block type 34 // | |+----------------Stream id 35 // | +-----------------Protocol version number 36 // +---------------------ASCII <SOH> (0x01) character 37 // BLOCKSIZE = 2^n 38 // 39 40 #include <string> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <iostream> 44 #include <vector> 45 #include <list> 46 #include <cctype> 47 48 #include <FL/Fl.H> 49 50 extern int idtimer; 51 52 #define DEBUG 53 54 #define arq_Version "arq 0.1" 55 //===================================================================== 56 // following Block Types are defined in K9PS ARQ Protocol specification 57 #define IDENT 'i' 58 #define CONREQ 'c' 59 #define CONACK 'k' 60 #define REFUSED 'r' 61 #define DISREQ 'd' 62 #define STATUS 's' 63 #define POLL 'p' 64 #define FMTFAIL 'f' 65 // following Block Types are extensions to the K9PS specification 66 #define _ABORT 'a' 67 #define _ACKABORT 'o' 68 #define _DISACK 'b' 69 #define _UNPROTO 'u' 70 #define _TALK 't' 71 //===================================================================== 72 #define SOH 0X01 73 #define STX 0X02 74 #define ACK 0X06 75 #define SUB 0X1A 76 #define EOT 0X04 77 //===================================================================== 78 //ARQ defaults 79 #define MAXHEADERS 8 // Max. number of missing blocks 80 #define MAXCOUNT 64 // DO NOT CHANGE THIS CONSTANT 81 #define EXPONENT 7 // Bufferlength = 2 ^ EXPONENT = 128 82 //===================================================================== 83 //link timing defaults 84 #define RETRIES 5 85 #define RETRYTIME 10000 // # milliseconds between retries 86 #define TXDELAY 500 // # milliseconds from xmt to rcv 87 #define TIMEOUT 60000 // # milliseconds before TIMED OUT 88 #define ARQLOOPTIME 100 // # msec for loop timing 89 //===================================================================== 90 //link states 91 enum LINK_STATES { 92 DOWN = 0, 93 TIMEDOUT, 94 ABORT, 95 ARQ_CONNECTING, 96 ARQ_CONNECTED, 97 WAITING, 98 WAITFORACK, 99 DISCONNECT, 100 DISCONNECTING, 101 ABORTING, 102 STOPPED 103 }; 104 105 //#define DOWN 0 106 //#define TIMEDOUT 1 107 //#define ABORT 3 108 //#define ARQ_CONNECTING 4 109 //#define ARQ_CONNECTED 5 110 //#define WAITING 6 111 //#define WAITFORACK 7 112 //#define DISCONNECT 8 113 //#define DISCONNECTING 9 114 //#define ABORTING 10 115 116 #define SENDING 0x80; 117 118 //===================================================================== 119 120 extern char *ARQASCII[]; 121 122 // crc 16 cycle redundancy check sum for data block integrity 123 124 class Ccrc16 { 125 private: 126 unsigned int crcval; 127 char ss[5]; 128 public: Ccrc16()129 Ccrc16() { crcval = 0xFFFF; } ~Ccrc16()130 ~Ccrc16() {}; reset()131 void reset() { crcval = 0xFFFF;} val()132 unsigned int val() {return crcval;} sval()133 std::string sval() { 134 snprintf(ss, sizeof(ss), "%04X", crcval); 135 return ss; 136 } update(char c)137 void update(char c) { 138 crcval ^= c & 255; 139 for (int i = 0; i < 8; ++i) { 140 if (crcval & 1) 141 crcval = (crcval >> 1) ^ 0xA001; 142 else 143 crcval = (crcval >> 1); 144 } 145 } crc16(char c)146 unsigned int crc16(char c) { 147 update(c); 148 return crcval; 149 } crc16(std::string s)150 unsigned int crc16(std::string s) { 151 reset(); 152 for (size_t i = 0; i < s.length(); i++) 153 update(s[i]); 154 return crcval; 155 } scrc16(std::string s)156 std::string scrc16(std::string s) { 157 crc16(s); 158 return sval(); 159 } 160 }; 161 162 // text block; block # and std::string of text 163 class cTxtBlk { 164 private: 165 int number; 166 std::string txt; 167 public: cTxtBlk()168 cTxtBlk() {number = -1; txt = "";} cTxtBlk(int n,std::string text)169 cTxtBlk(int n, std::string text) { number = n; txt = text; } ~cTxtBlk()170 ~cTxtBlk() {} nbr(int n)171 void nbr(int n) { number = n;} nbr()172 int nbr() { return number; } text()173 std::string text() { return txt; } text(std::string t)174 void text(std::string t) { txt = t;} 175 bool operator <(const cTxtBlk &b)const { return number < b.number; } 176 bool operator ==(const cTxtBlk b)const { return number == b.number; } 177 }; 178 179 180 class arq { 181 182 private: 183 bool arqstop; 184 185 std::string MyCall; 186 std::string UrCall; 187 188 std::string Header; 189 std::string Frame; 190 std::string Payload; 191 std::string rcvPayload; 192 193 std::string logfile; 194 195 char MyStreamID; 196 char UrStreamID; 197 198 char MyBlockLengthChar; 199 char UrBlockLengthChar; 200 char BlockNumberChar; 201 char fID; 202 int blknbr; 203 204 // queues // 205 std::string TxTextQueue; // Text out to mail engine 206 std::string TxPlainTextQueue; // plain text transmit queu 207 std::string RxTextQueue; // Text in from mail engine 208 std::string RxFrameQueue; 209 char lastRxChar; 210 bool TXflag; 211 212 int Bufferlength; 213 int maxheaders; 214 int exponent; 215 216 // status variables 217 int payloadlength; // Average length of payload received 218 int totalRx; // total number of frames received 219 int totalTx; // total number of frames transmitted 220 int nbrbadRx; // number with crc errors 221 int nbrbadTx; // total number of repeats required 222 // int max_idle; // Dynamic timing slot initial value 223 int SessionNumber; 224 bool PollOK; // used for status handshake 225 bool wrappedFlag; // set true if missing blocks bit count 226 // has wrapped around 227 int retrytime; 228 int RetryTime; 229 int retries; 230 int Retries; 231 int timeout; 232 int Timeout; 233 int tx2txdelay; 234 int TxDelay; 235 int loopcount; 236 int _idtimer; 237 238 int baseRetryTime; 239 int baseTimeout; 240 int baseRetries; 241 242 bool immediate; 243 bool primary; 244 245 Ccrc16 framecrc; 246 247 // My status 248 int Firstsent; // First Header I sent last turn 249 int LastHeader; // Last Header I sent last turn 250 int Lastqueued; // Last Header in static send queue 251 252 int EndHeader; // Last I received o.k. 253 int GoodHeader; // Last Header received consecutively 254 int blkcount; 255 int Blocks2Send; // number of blocks at beginning of Tx 256 257 std::vector<int> MyMissing; // missing Rx blocks 258 std::string MissingRxBlocks; 259 std::vector<cTxtBlk> RxPending; // RxPending Rx blocks (not consecutive) 260 261 std::list<cTxtBlk> TxBlocks; // fifo of transmit buffers 262 std::list<cTxtBlk> TxMissing; // fifo of sent; RxPending Status report 263 std::list<cTxtBlk> TxPending; // fifo of transmitted buffers pending print 264 265 // Ur status 266 int UrGoodHeader; // Other station's Good Header 267 int UrLastHeader; // Other station's Header last sent 268 int UrEndHeader; // Other station's last received Header 269 std::vector<int> UrMissing; // Other station's missing Headers 270 271 int LinkState; // status of ARQ link 272 int Sending; 273 274 bool bABORT; 275 276 // Link quality for sending *** used for testing only !! *** 277 // double sendquality; 278 279 void reset(); 280 void resetTx(); 281 void resetRx(); 282 int rtry(); 283 284 void setBufferlength(); 285 286 void checkblocks(); 287 std::string upcase(std::string s); 288 void newblocknumber(); 289 void newHeader(); 290 void IdHeader(); 291 void UnkHeader(); 292 293 void connectFrame(); 294 void disackFrame(); 295 void ackFrame(); 296 void ttyconnectFrame(); 297 void ttyackFrame(); 298 void pollFrame(); 299 void identFrame(); 300 void pingFrame(); 301 void statFrame(); 302 void disconnectFrame(); 303 void abortFrame(); 304 void ackAbortFrame(); 305 void beaconFrame(std::string txt); 306 void textFrame(cTxtBlk block); 307 void talkFrame(std::string txt); 308 309 void addToTxQue(std::string s); 310 311 void sendblocks(); 312 void transmitdata(); 313 frame()314 std::string frame() {return Frame;} 315 316 bool isUrcall(); 317 void parseIDENT(); 318 void parseCONREQ(); 319 void parseCONACK(); 320 void parseREFUSED(); 321 void parseDISREQ(); 322 void parseDISACK(); 323 void parseABORT(); 324 void parseACKABORT(); 325 void parseUNPROTO(); 326 void parseSTATUS(); 327 void parsePOLL(); 328 void parseDATA(); 329 void parseTALK(); 330 331 int parseFrame(std::string txt); 332 333 // external functions called by arq class 334 void (*sendfnc)(const std::string& s); 335 bool (*getc1)(char &); 336 void (*rcvfnc)(); 337 void (*printRX)(std::string s); 338 void (*printTX)(std::string s); 339 void (*printRX_DEBUG)(std::string s); 340 void (*printTX_DEBUG)(std::string s); 341 void (*printTALK)(std::string s); 342 void (*abortfnc)(); 343 void (*disconnectfnc)(); 344 void (*rxUrCall)(std::string s); 345 void (*qualityfnc)(std::string s); 346 void (*printSTATUS)(std::string s, double disptime); 347 348 public: 349 arq(); ~arq()350 ~arq() {}; 351 352 friend void arqloop(void *me); 353 void start_arq(); 354 355 void restart_arq(); 356 357 std::string checksum(std::string &s); 358 myCall(std::string s)359 void myCall(std::string s) { MyCall = upcase(s);} myCall()360 std::string myCall() { return MyCall;} 361 urCall(std::string s)362 void urCall(std::string s) { UrCall = s;} urCall()363 std::string urCall() { return UrCall;} 364 365 void newsession(); 366 setSendFunc(void (* f)(const std::string & s))367 void setSendFunc( void (*f)(const std::string& s)) { sendfnc = f;} setGetCFunc(bool (* f)(char &))368 void setGetCFunc( bool (*f)(char &)) { getc1 = f;} setRcvFunc(void (* f)())369 void setRcvFunc( void (*f)()) { rcvfnc = f;} 370 setPrintRX(void (* f)(std::string s))371 void setPrintRX( void (*f)(std::string s)) { printRX = f;} setPrintTX(void (* f)(std::string s))372 void setPrintTX( void (*f)(std::string s)) { printTX = f;} setPrintTALK(void (* f)(std::string s))373 void setPrintTALK (void (*f)(std::string s)) {printTALK = f;} setPrintRX_DEBUG(void (* f)(std::string s))374 void setPrintRX_DEBUG (void (*f)(std::string s)){printRX_DEBUG = f;} setPrintTX_DEBUG(void (* f)(std::string s))375 void setPrintTX_DEBUG (void (*f)(std::string s)) {printTX_DEBUG = f;} setPrintSTATUS(void (* f)(std::string s,double disptime))376 void setPrintSTATUS (void (*f)(std::string s, double disptime)) { printSTATUS = f;} 377 setMaxHeaders(int mh)378 void setMaxHeaders( int mh ) { maxheaders = mh; } setExponent(int exp)379 void setExponent( int exp ) { exponent = exp; setBufferlength(); } getExponent()380 int getExponent() { return (int) exponent;} setWaitTime(int rtime)381 void setWaitTime( int rtime ) { RetryTime = rtime; baseRetryTime = rtime; } getWaitTime()382 int getWaitTime() { return (int) RetryTime; } setRetries(int rtries)383 void setRetries ( int rtries ) { 384 retries = Retries = baseRetries = rtries; } getRetries()385 int getRetries() { return (int) Retries; } setTimeout(int tout)386 void setTimeout ( int tout ) { Timeout = tout; baseTimeout = tout; } getTimeout()387 int getTimeout() { return (int) Timeout; } getTimeLeft()388 int getTimeLeft() { return (int) timeout * ARQLOOPTIME / 1000; } setTxDelay(int r2t)389 void setTxDelay ( int r2t ) { TxDelay = r2t; } getTxDelay()390 int getTxDelay() { return (int) TxDelay; } getRetryCount()391 int getRetryCount() { return (int)(Retries - retries + 1); } 392 set_idtimer()393 void set_idtimer() { 394 if (idtimer) _idtimer = (idtimer * 60 - 10) * 1000 / ARQLOOPTIME; 395 else _idtimer = (10 * 60 - 10) * 1000 / ARQLOOPTIME; 396 } 397 setrxUrCall(void (* f)(std::string s))398 void setrxUrCall( void (*f)(std::string s)) { rxUrCall = f;} setQualityValue(void (* f)(std::string s))399 void setQualityValue( void (*f)(std::string s)) { qualityfnc = f;} setAbortedTransfer(void (* f)())400 void setAbortedTransfer( void (*f)()) { abortfnc = f;}; setDisconnected(void (* f)())401 void setDisconnected( void (*f)()) { disconnectfnc = f;}; 402 403 void rcvChar( char c ); 404 405 void connect(std::string callsign);//, int blocksize = 6, int retries = 4); 406 407 void sendblocks( std::string txt ); 408 409 void sendBeacon (std::string txt); 410 void sendPlainText( std::string txt ); 411 getText()412 std::string getText() { return RxTextQueue;} 413 void sendText(std::string txt); 414 connected()415 bool connected() { return (LinkState == ARQ_CONNECTED); } 416 void disconnect(); 417 void abort(); 418 state()419 int state() { return (LinkState + Sending);} 420 TXblocks()421 int TXblocks() { return totalTx;} TXbad()422 int TXbad() { return nbrbadTx;} RXblocks()423 int RXblocks() { return totalRx;} RXbad()424 int RXbad() { return nbrbadRx;} 425 quality()426 double quality() { 427 if (totalTx == 0) return 1.0; 428 return ( 1.0 * (totalTx - nbrbadTx) / totalTx ); 429 } 430 percentSent()431 float percentSent() { 432 if (Blocks2Send == 0) return 0.0; 433 if ((TxBlocks.empty() && TxMissing.empty())) return 1.0; 434 return (1.0 * (Blocks2Send - TxBlocks.size() - TxMissing.size()) / Blocks2Send); 435 } 436 transferComplete()437 bool transferComplete() { 438 if (TxMissing.empty() == false) return false; 439 if (TxBlocks.empty() == false) return false; 440 return true; 441 } 442 }; 443 444 #endif 445 446