52 static_cast<time_t
>(duration / 1000000),
53 static_cast<suseconds_t
>(duration % 1000000)
63 if (res == -1 && errno != EINTR) {
82 stringRep.
add(
Link::LINK_TYPE_UNKNOWN,
N_("Unknown"));
87Link::
Link(const
char *fname,
int baud,
NCP *ncp,
bool noDSRCheck,
unsigned short verbose, const
int cancellationFd)
90, cancellationFd_(cancellationFd) {
92 linkType_ = LINK_TYPE_UNKNOWN;
93 for (
int i = 0; i < 256; i++)
99 dataLink_ =
new DataLink(fname, baud,
this, noDSRCheck,
verbose, cancellationFd);
101 pthread_mutex_init(&queueMutex_, NULL);
102 pthread_create(&checkThreadId_, NULL,
expire_check,
this);
115 return ((
unsigned long)
getSpeed() * 1000 / 13200) + 200;
126 for (
int i = 0; i < 256; i++)
134 if (buff.
getLen() > 300) {
150 vector<AckWaitQueueElement>::iterator i;
152 if (i->data.getByte(0) == channel) {
156 vector<BufferStore>::iterator j;
158 if (j->getByte(0) == channel) {
170 lout <<
"Link: >> ack seq=" << seq << endl;
173 int lseq = (seq & 7) | 8;
174 seq = (hseq << 8) + lseq;
187 lout <<
"Link: >> con seq=4" << endl;
192 gettimeofday(&e.
stamp, NULL);
207 lout <<
"Link: >> con seq=1" << endl;
211 gettimeofday(&e.
stamp, NULL);
226 lout <<
"Link: >> con seq=1" << endl;
238 vector<AckWaitQueueElement>::iterator i;
242 int seq = type & 0x0f;
249 seq = (tseq << 3) + (seq & 0x07);
257 lout <<
"Link: << dat seq=" << seq ;
259 lout <<
" " << buff << endl;
276 lout <<
"Link: got XOFF for channel "
283 lout <<
"Link: got XON for channel "
297 lout <<
"Link: DUP\n";
305 struct timeval refstamp;
313 lout <<
"Link: << ack seq=" << seq ;
345 vector<BufferStore> pendingData;
348 gettimeofday(&now, NULL);
349 bool nextFound =
false;
351 if (i->seq == seq+1) {
353 if (i->txcount-- == 0) {
356 lout <<
"Link: >> TRANSMIT timeout seq=" <<
364 lout <<
"Link: >> RETRANSMIT seq=" << i->seq
366 pendingData.push_back(i->data);
375 for (vector<BufferStore>::iterator i = pendingData.begin(); i != pendingData.end(); i++) {
380 lout <<
"Link: << UNMATCHED ack seq=" << seq;
395 if ((i->seq == 0) && (i->data.getByte(0) == 0x21)) {
407 lout <<
"Link: << con seq=" << seq ;
422 lout <<
"Link: << req seq=" << seq;
457 lout <<
"Link: << DISC" << endl;
462 lerr <<
"Link: FATAL: Unknown packet type " << type << endl;
467 vector<BufferStore> tmpQueue;
468 vector<BufferStore>::iterator i;
473 if (i->getByte(0) == channel) {
474 tmpQueue.push_back(*i);
481 for (i = tmpQueue.begin(); i != tmpQueue.end(); i++)
486 vector<BufferStore> tmpQueue;
487 vector<BufferStore>::iterator i;
492 tmpQueue.push_back(*i);
498 for (i = tmpQueue.begin(); i != tmpQueue.end(); i++) {
507 int remoteChan = buf.
getByte(0);
508 if (
xoff_[remoteChan]) {
528 gettimeofday(&e.
stamp, NULL);
534 lout <<
"Link: >> req seq=" << e.
seq << endl;
539 lout <<
"Link: >> dat seq=" << e.
seq;
545 int hseq = e.
seq >> 3;
546 int lseq = 0x30 + ((e.
seq & 7) | 8);
547 int seq = (hseq << 8) + lseq;
562static void timesub(
struct timeval *tv,
unsigned long millisecs) {
563 uint64_t micros = tv->tv_sec;
564 uint64_t sub = millisecs;
567 micros += tv->tv_usec;
568 micros -= (sub * 1000);
569 tv->tv_usec = micros & 0xffffffff;
570 tv->tv_sec = (micros >>= 32) & 0xffffffff;
573static bool olderthan(
struct timeval t1,
struct timeval t2) {
574 uint64_t m1 = t1.tv_sec;
575 uint64_t m2 = t2.tv_sec;
584 vector<AckWaitQueueElement>::iterator i;
606 vector<BufferStore> pendingData;
608 vector<AckWaitQueueElement>::iterator i;
610 gettimeofday(&now, NULL);
611 struct timeval expired = now;
615 if (i->txcount-- == 0) {
618 lout <<
"Link: >> TRANSMIT timeout seq=" << i->seq << endl;
626 lout <<
"Link: >> RETRANSMIT seq=" << i->seq << endl;
627 pendingData.push_back(i->data);
634 for (vector<BufferStore>::iterator i = pendingData.begin(); i != pendingData.end(); i++) {
652 lout <<
"Link: hasFailed: " <<
failed_ <<
", " << lfailed << endl;
#define ENUM_DEFINITION_END(EnumName)
#define ENUM_DEFINITION_BEGIN(EnumName, initWith)
Helper macro to construct an enumeration wrapper Enum<E> for a specific enum type.
A generic container for an array of bytes.
void prependByte(unsigned char c)
Prepends a byte to the content of this instance.
void prependWord(int w)
Prepends a word to the content of this instance.
void addByte(unsigned char c)
Appends a byte to the content of this instance.
void addDWord(long dw)
Appends a dword to the content of this instance.
unsigned long getLen() const
Retrieves the length of a BufferStore.
bool empty() const
Tests if the BufferStore is empty.
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
void discardFirstBytes(int len=0)
Removes bytes from the start of the buffer.
Thread-safe class responsible for managing the underlying serial device and data link framing.
void send(BufferStore &b, bool isEPOC)
Send a buffer out to serial line.
Wrapper class featuring range-checking and string representation of enumerated values.
void reset()
Reset connection and attempt to reconnect to the peer.
const unsigned short verbose_
void transmit(BufferStore buf)
void sendAck(int seq, Enum< link_type > linkType)
void sendReq(Enum< link_type > linkType)
~Link()
Disconnects from device and destroys instance.
Enum< link_type > linkType_
Enum< link_type > getLinkType()
Get the current link type.
pthread_mutex_t queueMutex_
void purgeQueue(int channel)
Purge all outstanding packets for a specified remote channel.
int getSpeed()
Get current speed of the serial device.
std::vector< BufferStore > holdQueue_
void send(const BufferStore &buff)
Send a PLP packet to the Peer.
void transmitHoldQueue(int channel)
void multiAck(struct timeval)
bool hasFailed()
Query connection failure.
std::vector< BufferStore > waitQueue_
void receive(BufferStore buf)
Effectively a delegate method that accepts data from our DataLink instance.
unsigned long retransTimeout()
bool stuffToSend()
Query outstanding packets.
std::vector< AckWaitQueueElement > ackWaitQueue
const int cancellationFd_
Used to signal cancellation.
void receive(BufferStore s)
stringRep add(Link::LINK_TYPE_UNKNOWN, N_("Unknown"))
static bool olderthan(struct timeval t1, struct timeval t2)
static void timesub(struct timeval *tv, unsigned long millisecs)
static void * expire_check(void *arg)
Describes a transmitted packet which has not yet been acknowledged by the peer.
BufferStore data
Packet content.
int txcount
Number of remaining transmit retries.
int seq
Original sequence number.
struct timeval stamp
Time of last transmit.