Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aad72a53 authored by David Pursell's avatar David Pursell
Browse files

fastboot: fix TCP protocol version check.

Currently the TCP handshake fails if the device TCP protocol version
doesn't match the host exactly, but the protocol is supposed to allow
for forwards compatibility by accepting any protocol version >= itself.
That way the other side can potentially lower its protocol to match and
keep going.

This CL fixes the protocol version check and adds corresponding unit
tests.

Bug: http://b/27220700
Change-Id: Ib17f0a55eb910105a27609bc94bf76a30442e92e
parent 8c09555a
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include "tcp.h"

#include <android-base/parseint.h>
#include <android-base/stringprintf.h>

namespace tcp {
@@ -98,7 +99,8 @@ bool TcpTransport::InitializeProtocol(std::string* error) {
        return false;
    }

    char buffer[kHandshakeLength];
    char buffer[kHandshakeLength + 1];
    buffer[kHandshakeLength] = '\0';
    if (socket_->ReceiveAll(buffer, kHandshakeLength, kHandshakeTimeoutMs) != kHandshakeLength) {
        *error = android::base::StringPrintf(
                "No initialization message received (%s). Target may not support TCP fastboot",
@@ -111,9 +113,10 @@ bool TcpTransport::InitializeProtocol(std::string* error) {
        return false;
    }

    if (memcmp(buffer + 2, "01", 2) != 0) {
    int version = 0;
    if (!android::base::ParseInt(buffer + 2, &version) || version < kProtocolVersion) {
        *error = android::base::StringPrintf("Unknown TCP protocol version %s (host version %02d)",
                                             std::string(buffer + 2, 2).c_str(), kProtocolVersion);
                                             buffer + 2, kProtocolVersion);
        return false;
    }

+12 −2
Original line number Diff line number Diff line
@@ -42,6 +42,16 @@ TEST(TcpConnectTest, TestSuccess) {
    EXPECT_EQ("", error);
}

TEST(TcpConnectTest, TestNewerVersionSuccess) {
    std::unique_ptr<SocketMock> mock(new SocketMock);
    mock->ExpectSend("FB01");
    mock->AddReceive("FB99");

    std::string error;
    EXPECT_NE(nullptr, tcp::internal::Connect(std::move(mock), &error));
    EXPECT_EQ("", error);
}

TEST(TcpConnectTest, TestSendFailure) {
    std::unique_ptr<SocketMock> mock(new SocketMock);
    mock->ExpectSendFailure("FB01");
@@ -74,11 +84,11 @@ TEST(TcpConnectTest, TestBadResponseFailure) {
TEST(TcpConnectTest, TestUnknownVersionFailure) {
    std::unique_ptr<SocketMock> mock(new SocketMock);
    mock->ExpectSend("FB01");
    mock->AddReceive("FB02");
    mock->AddReceive("FB00");

    std::string error;
    EXPECT_EQ(nullptr, tcp::internal::Connect(std::move(mock), &error));
    EXPECT_EQ("Unknown TCP protocol version 02 (host version 01)", error);
    EXPECT_EQ("Unknown TCP protocol version 00 (host version 01)", error);
}

// Fixture to configure a SocketMock for a successful TCP connection.