send a handshake before first packet send

This commit is contained in:
Stephen Birarda 2015-08-25 17:12:03 -07:00
parent 67816c033a
commit cabdee8391
7 changed files with 56 additions and 3 deletions

View file

@ -400,6 +400,12 @@ void Connection::processControl(std::unique_ptr<ControlPacket> controlPacket) {
case ControlPacket::TimeoutNAK:
processTimeoutNAK(move(controlPacket));
break;
case ControlPacket::Handshake:
processHandshake(move(controlPacket));
break;
case ControlPacket::HandshakeACK:
processHandshakeACK(move(controlPacket));
break;
}
}
@ -589,6 +595,19 @@ void Connection::processNAK(std::unique_ptr<ControlPacket> controlPacket) {
_stats.record(ConnectionStats::Stats::ReceivedNAK);
}
void Connection::processHandshake(std::unique_ptr<ControlPacket> controlPacket) {
// immediately respond with a handshake ACK
static auto handshakeACK = ControlPacket::create(ControlPacket::HandshakeACK, 0);
_parentSocket->writeBasePacket(*handshakeACK, _destination);
_hasReceivedHandshake = true;
}
void Connection::processHandshakeACK(std::unique_ptr<ControlPacket> controlPacket) {
// hand off this handshake ACK to the send queue so it knows it can start sending
getSendQueue().handshakeACK();
}
void Connection::processTimeoutNAK(std::unique_ptr<ControlPacket> controlPacket) {
// Override SendQueue's LossList with the timeout NAK list
getSendQueue().overrideNAKListFromPacket(*controlPacket);

View file

@ -90,6 +90,8 @@ private:
void processACK2(std::unique_ptr<ControlPacket> controlPacket);
void processNAK(std::unique_ptr<ControlPacket> controlPacket);
void processTimeoutNAK(std::unique_ptr<ControlPacket> controlPacket);
void processHandshake(std::unique_ptr<ControlPacket> controlPacket);
void processHandshakeACK(std::unique_ptr<ControlPacket> controlPacket);
SendQueue& getSendQueue();
SequenceNumber nextACK() const;
@ -106,6 +108,7 @@ private:
std::chrono::high_resolution_clock::time_point _lastNAKTime;
bool _hasReceivedFirstPacket { false };
bool _hasReceivedHandshake { false }; // flag for receipt of handshake from server
LossList _lossList; // List of all missing packets
SequenceNumber _lastReceivedSequenceNumber; // The largest sequence number received from the peer

View file

@ -100,7 +100,7 @@ void ControlPacket::readType() {
Q_ASSERT_X(bitAndType & CONTROL_BIT_MASK, "ControlPacket::readHeader()", "This should be a control packet");
uint16_t packetType = (bitAndType & ~CONTROL_BIT_MASK) >> (8 * sizeof(Type));
Q_ASSERT_X(packetType <= ControlPacket::Type::TimeoutNAK, "ControlPacket::readType()", "Received a control packet with wrong type");
Q_ASSERT_X(packetType <= ControlPacket::Type::HandshakeACK, "ControlPacket::readType()", "Received a control packet with wrong type");
// read the type
_type = (Type) packetType;

View file

@ -30,7 +30,9 @@ public:
ACK,
ACK2,
NAK,
TimeoutNAK
TimeoutNAK,
Handshake,
HandshakeACK
};
static std::unique_ptr<ControlPacket> create(Type type, qint64 size = -1);

View file

@ -169,7 +169,8 @@ SequenceNumber LossList::popFirstSequenceNumber() {
void LossList::write(ControlPacket& packet, int maxPairs) {
int writtenPairs = 0;
for(const auto& pair : _lossList) {
for (const auto& pair : _lossList) {
packet.writePrimitive(pair.first);
packet.writePrimitive(pair.second);

View file

@ -195,6 +195,31 @@ void SendQueue::run() {
// Record timing
_lastSendTimestamp = high_resolution_clock::now();
if (!_hasReceivedHandshakeACK) {
// we haven't received a handshake ACK from the client
// if it has been at least 100ms since we last sent a handshake, send another now
// hold the time of last send in a static
static auto lastSendHandshake = high_resolution_clock::time_point();
static const int HANDSHAKE_RESEND_INTERVAL_MS = 100;
// calculation the duration since the last handshake send
auto sinceLastHandshake = duration_cast<milliseconds>(high_resolution_clock::now() - lastSendHandshake);
if (sinceLastHandshake.count() >= HANDSHAKE_RESEND_INTERVAL_MS) {
// it has been long enough since last handshake, send another
static auto handshakePacket = ControlPacket::create(ControlPacket::Handshake, 0);
_socket->writeBasePacket(*handshakePacket, _destination);
lastSendHandshake = high_resolution_clock::now();
}
// skip over this iteration since we haven't completed the handshake
continue;
}
bool resentPacket = false;
// the following while makes sure that we find a packet to re-send, if there is one

View file

@ -59,6 +59,7 @@ public slots:
void ack(SequenceNumber ack);
void nak(SequenceNumber start, SequenceNumber end);
void overrideNAKListFromPacket(ControlPacket& packet);
void handshakeACK() { _hasReceivedHandshakeACK = true; }
signals:
void packetSent(int dataSize, int payloadSize);
@ -85,6 +86,8 @@ private:
Socket* _socket { nullptr }; // Socket to send packet on
HifiSockAddr _destination; // Destination addr
std::atomic<bool> _hasReceivedHandshakeACK { false }; // flag for receipt of handshake ACK from client
std::atomic<uint32_t> _lastACKSequenceNumber; // Last ACKed sequence number
MessageNumber _currentMessageNumber { 0 };