diff options
author | Sergey Yershov <yershov@corp.mail.ru> | 2016-10-21 19:54:02 +0300 |
---|---|---|
committer | Sergey Yershov <yershov@corp.mail.ru> | 2016-10-25 17:33:35 +0300 |
commit | 1f1d0a58713f4f4817827aa108f75e0657014813 (patch) | |
tree | eff7e58b59addf80982788177617215f4f840622 /tracking | |
parent | 8314310c0e8a63bed40abf95b7741b10c24521eb (diff) |
[tracking] Made tracking work
Diffstat (limited to 'tracking')
-rw-r--r-- | tracking/connection.cpp | 31 | ||||
-rw-r--r-- | tracking/connection.hpp | 1 | ||||
-rw-r--r-- | tracking/protocol.cpp | 62 | ||||
-rw-r--r-- | tracking/protocol.hpp | 38 | ||||
-rw-r--r-- | tracking/reporter.cpp | 26 | ||||
-rw-r--r-- | tracking/reporter.hpp | 11 | ||||
-rw-r--r-- | tracking/tracking.pro | 2 | ||||
-rw-r--r-- | tracking/tracking_tests/protocol_test.cpp | 34 | ||||
-rw-r--r-- | tracking/tracking_tests/reporter_test.cpp | 34 | ||||
-rw-r--r-- | tracking/tracking_tests/tracking_tests.pro | 3 |
10 files changed, 213 insertions, 29 deletions
diff --git a/tracking/connection.cpp b/tracking/connection.cpp index 550a797afc..26cbfadba3 100644 --- a/tracking/connection.cpp +++ b/tracking/connection.cpp @@ -1,5 +1,8 @@ -#include "connection.hpp" +#include "tracking/connection.hpp" +#include "tracking/protocol.hpp" + +#include "platform/platform.hpp" #include "platform/socket.hpp" namespace @@ -22,19 +25,27 @@ Connection::Connection(unique_ptr<platform::Socket> socket, string const & host, bool Connection::Reconnect() { m_socket->Close(); - return m_socket->Open(m_host, m_port); + + if (!m_socket->Open(m_host, m_port)) + return false; + + auto packet = Protocol::CreateAuthPacket(GetPlatform().UniqueClientId()); + if (!m_socket->Write(packet.data(), static_cast<uint32_t>(packet.size()))) + return false; + + string check(begin(Protocol::kFail), end(Protocol::kFail)); + bool const isSuccess = + m_socket->Read(reinterpret_cast<uint8_t *>(&check[0]), static_cast<uint32_t>(check.size())); + if (!isSuccess || check != string(begin(Protocol::kOk), end(Protocol::kOk))) + return false; + + return true; } // TODO: implement historical bool Connection::Send(boost::circular_buffer<DataPoint> const & points) { - ASSERT(m_buffer.empty(), ()); - - MemWriter<decltype(m_buffer)> writer(m_buffer); - using coding::TrafficGPSEncoder; - TrafficGPSEncoder::SerializeDataPoints(TrafficGPSEncoder::kLatestVersion, writer, points); - bool const isSuccess = m_socket->Write(m_buffer.data(), m_buffer.size()); - m_buffer.clear(); - return isSuccess; + auto packet = Protocol::CreateDataPacket(points); + return m_socket->Write(packet.data(), static_cast<uint32_t>(packet.size())); } } // namespace tracking diff --git a/tracking/connection.hpp b/tracking/connection.hpp index a87f3dbbf1..48445444bd 100644 --- a/tracking/connection.hpp +++ b/tracking/connection.hpp @@ -31,6 +31,5 @@ private: string const m_host; uint16_t const m_port; bool const m_isHistorical; - vector<uint8_t> m_buffer; }; } // namespace tracking diff --git a/tracking/protocol.cpp b/tracking/protocol.cpp new file mode 100644 index 0000000000..ada9a49842 --- /dev/null +++ b/tracking/protocol.cpp @@ -0,0 +1,62 @@ +#include "tracking/protocol.hpp" + +#include "coding/endianness.hpp" + +#include "base/assert.hpp" + +#include "std/cstdint.hpp" + +namespace tracking +{ +uint8_t const Protocol::kOk[4] = {'O', 'K', '\n', '\n'}; +uint8_t const Protocol::kFail[4] = {'F', 'A', 'I', 'L'}; + +static_assert(sizeof(Protocol::kFail) >= sizeof(Protocol::kOk), ""); + +vector<uint8_t> Protocol::CreateAuthPacket(string const & clientId) +{ + vector<uint8_t> packet; + + InitHeader(packet, PacketType::CurrentAuth, static_cast<uint32_t>(clientId.size())); + packet.insert(packet.end(), begin(clientId), end(clientId)); + + return packet; +} + +vector<uint8_t> Protocol::CreateDataPacket(DataElements const & points) +{ + vector<uint8_t> buffer; + MemWriter<decltype(buffer)> writer(buffer); + Encoder::SerializeDataPoints(Encoder::kLatestVersion, writer, points); + + vector<uint8_t> packet; + InitHeader(packet, PacketType::CurrentData, static_cast<uint32_t>(buffer.size())); + packet.insert(packet.end(), begin(buffer), end(buffer)); + + return packet; +} + +void Protocol::InitHeader(vector<uint8_t> & packet, PacketType type, uint32_t payloadSize) +{ + packet.resize(sizeof(uint32_t)); + uint32_t & size = *reinterpret_cast<uint32_t *>(packet.data()); + size = payloadSize; + + ASSERT_LESS(size, 0x00FFFFFF, ()); + + if (!IsBigEndian()) + size = ReverseByteOrder(size); + + packet[0] = static_cast<uint8_t>(type); +} + +string DebugPrint(Protocol::PacketType type) +{ + switch (type) + { + case Protocol::PacketType::AuthV0: return "AuthV0"; + case Protocol::PacketType::DataV0: return "DataV0"; + default: return "Unknown"; + } +} +} // namespace tracking diff --git a/tracking/protocol.hpp b/tracking/protocol.hpp new file mode 100644 index 0000000000..6b15b7bdeb --- /dev/null +++ b/tracking/protocol.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "coding/traffic.hpp" + +#include "std/string.hpp" +#include "std/vector.hpp" + +#include "boost/circular_buffer.hpp" + +namespace tracking +{ +class Protocol +{ +public: + using Encoder = coding::TrafficGPSEncoder; + using DataElements = boost::circular_buffer<Encoder::DataPoint>; + + static uint8_t const kOk[4]; + static uint8_t const kFail[4]; + + enum class PacketType + { + AuthV0 = 0x81, + DataV0 = 0x82, + + CurrentAuth = AuthV0, + CurrentData = DataV0 + }; + + static vector<uint8_t> CreateAuthPacket(string const & clientId); + static vector<uint8_t> CreateDataPacket(DataElements const & points); + +private: + static void InitHeader(vector<uint8_t> & packet, PacketType type, uint32_t payloadSize); +}; + +string DebugPrint(Protocol::PacketType type); +} // namespace tracking diff --git a/tracking/reporter.cpp b/tracking/reporter.cpp index b161b4e3d6..35b59c65ae 100644 --- a/tracking/reporter.cpp +++ b/tracking/reporter.cpp @@ -8,8 +8,6 @@ #include "std/target_os.hpp" -#include "private.h" - namespace { double constexpr kRequiredHorizontalAccuracy = 10.0; @@ -25,21 +23,22 @@ namespace tracking // Keys saved for existing users, so can' fix it easy, need migration. // Use this hack until change to special traffic key. #if defined(OMIM_OS_IPHONE) -const char Reporter::kEnabledSettingsKey[] = "StatisticsEnabled"; +const char Reporter::kEnableTrackingKey[] = "StatisticsEnabled"; #elif defined(OMIM_OS_ANDROID) -const char Reporter::kEnabledSettingsKey[] = "AllowStat"; +const char Reporter::kEnableTrackingKey[] = "AllowStat"; #else -const char Reporter::kEnabledSettingsKey[] = "AllowStat"; +const char Reporter::kEnableTrackingKey[] = "AllowStat"; #endif // static milliseconds const Reporter::kPushDelayMs = milliseconds(10000); -Reporter::Reporter(unique_ptr<platform::Socket> socket, milliseconds pushDelay) - : m_realtimeSender(move(socket), TRACKING_REALTIME_HOST, TRACKING_REALTIME_PORT, false) +Reporter::Reporter(unique_ptr<platform::Socket> socket, string const & host, uint16_t port, + milliseconds pushDelay) + : m_realtimeSender(move(socket), host, port, false) , m_pushDelay(pushDelay) , m_points(kRealTimeBufferSize) - , m_thread([this]{Run();}) + , m_thread([this] { Run(); }) { } @@ -82,8 +81,15 @@ void Reporter::Run() m_input.clear(); lock.unlock(); - if (SendPoints()) - m_points.clear(); + if (m_points.empty() && m_idleFn) + { + m_idleFn(); + } + else + { + if (SendPoints()) + m_points.clear(); + } lock.lock(); auto const passedMs = duration_cast<milliseconds>(steady_clock::now() - startTime); diff --git a/tracking/reporter.hpp b/tracking/reporter.hpp index 2c85b69969..380a3cd460 100644 --- a/tracking/reporter.hpp +++ b/tracking/reporter.hpp @@ -7,6 +7,7 @@ #include "std/chrono.hpp" #include "std/condition_variable.hpp" #include "std/mutex.hpp" +#include "std/string.hpp" #include "std/unique_ptr.hpp" #include "std/vector.hpp" @@ -28,13 +29,16 @@ class Reporter final { public: static milliseconds const kPushDelayMs; - static const char kEnabledSettingsKey[]; + static const char kEnableTrackingKey[]; - Reporter(unique_ptr<platform::Socket> socket, milliseconds pushDelay); + Reporter(unique_ptr<platform::Socket> socket, string const & host, uint16_t port, + milliseconds pushDelay); ~Reporter(); void AddLocation(location::GpsInfo const & info); + inline void SetIdleFunc(function<void()> fn) { m_idleFn = fn; } + private: void Run(); bool SendPoints(); @@ -43,6 +47,9 @@ private: milliseconds m_pushDelay; bool m_wasConnected = false; double m_lastConnectionAttempt = 0.0; + // Function to be called every |kPushDelayMs| in + // case no points were sent. + function<void()> m_idleFn; // Input buffer for incoming points. Worker thread steals it contents. vector<DataPoint> m_input; // Last collected points, sends periodically to server. diff --git a/tracking/tracking.pro b/tracking/tracking.pro index 2418e67637..42e7d13953 100644 --- a/tracking/tracking.pro +++ b/tracking/tracking.pro @@ -8,8 +8,10 @@ include($$ROOT_DIR/common.pri) SOURCES += \ connection.cpp \ + protocol.cpp \ reporter.cpp \ HEADERS += \ connection.hpp \ + protocol.hpp \ reporter.hpp \ diff --git a/tracking/tracking_tests/protocol_test.cpp b/tracking/tracking_tests/protocol_test.cpp new file mode 100644 index 0000000000..f3b72d6160 --- /dev/null +++ b/tracking/tracking_tests/protocol_test.cpp @@ -0,0 +1,34 @@ +#include "testing/testing.hpp" + +#include "tracking/protocol.hpp" + +using namespace tracking; + +UNIT_TEST(Protocol_CreateAuthPacket) +{ + auto packet = Protocol::CreateAuthPacket("AAA"); + TEST_EQUAL(packet.size(), 7, ()); + TEST_EQUAL(Protocol::PacketType(packet[0]), Protocol::PacketType::CurrentAuth, ()); + TEST_EQUAL(packet[1], 0x00, ()); + TEST_EQUAL(packet[2], 0x00, ()); + TEST_EQUAL(packet[3], 0x03, ()); + TEST_EQUAL(packet[4], 'A', ()); + TEST_EQUAL(packet[5], 'A', ()); + TEST_EQUAL(packet[6], 'A', ()); +} + +UNIT_TEST(Protocol_CreateDataPacket) +{ + Protocol::DataElements buffer(5); + buffer.push_back(Protocol::DataElements::value_type(1, ms::LatLon(10, 10))); + buffer.push_back(Protocol::DataElements::value_type(2, ms::LatLon(15, 15))); + auto packet = Protocol::CreateDataPacket(buffer); + TEST_EQUAL(packet.size(), 26, ()); + TEST_EQUAL(Protocol::PacketType(packet[0]), Protocol::PacketType::CurrentData, ()); + TEST_EQUAL(packet[1], 0x00, ()); + TEST_EQUAL(packet[2], 0x00, ()); + TEST_EQUAL(packet[3], 22, ()); + TEST_EQUAL(packet[4], 1, ()); + TEST_EQUAL(packet[5], 227, ()); + TEST_EQUAL(packet[6], 241, ()); +} diff --git a/tracking/tracking_tests/reporter_test.cpp b/tracking/tracking_tests/reporter_test.cpp index 685b4f19f7..bdd47a60a5 100644 --- a/tracking/tracking_tests/reporter_test.cpp +++ b/tracking/tracking_tests/reporter_test.cpp @@ -1,4 +1,7 @@ +#include "testing/testing.hpp" + #include "tracking/reporter.hpp" +#include "tracking/protocol.hpp" #include "coding/traffic.hpp" @@ -6,8 +9,6 @@ #include "platform/platform_tests_support/test_socket.hpp" #include "platform/socket.hpp" -#include "testing/testing.hpp" - #include "base/math.hpp" #include "base/thread.hpp" @@ -28,13 +29,36 @@ void TransferLocation(Reporter & reporter, TestSocket & testSocket, double times gpsInfo.m_horizontalAccuracy = 1.0; reporter.AddLocation(gpsInfo); + using Packet = tracking::Protocol::PacketType; vector<uint8_t> buffer; - size_t const readSize = testSocket.ReadServer(buffer); - TEST_GREATER(readSize, 0, ()); + size_t readSize = 0; + size_t attempts = 3; + do + { + readSize = testSocket.ReadServer(buffer); + if (attempts-- && readSize == 0) + continue; + switch (Packet(buffer[0])) + { + case Packet::CurrentAuth: + { + buffer.clear(); + testSocket.WriteServer(tracking::Protocol::kOk); + break; + } + case Packet::CurrentData: + { + readSize = 0; + break; + } + } + } while (readSize); + TEST(!buffer.empty(), ()); vector<coding::TrafficGPSEncoder::DataPoint> points; MemReader memReader(buffer.data(), buffer.size()); ReaderSource<MemReader> src(memReader); + src.Skip(sizeof(uint32_t /* header */)); coding::TrafficGPSEncoder::DeserializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion, src, points); @@ -51,7 +75,7 @@ UNIT_TEST(Reporter_TransferLocations) auto socket = make_unique<TestSocket>(); TestSocket & testSocket = *socket.get(); - Reporter reporter(move(socket), milliseconds(10) /* pushDelay */); + Reporter reporter(move(socket), "localhost", 0, milliseconds(10) /* pushDelay */); TransferLocation(reporter, testSocket, 1.0, 2.0, 3.0); TransferLocation(reporter, testSocket, 4.0, 5.0, 6.0); TransferLocation(reporter, testSocket, 7.0, 8.0, 9.0); diff --git a/tracking/tracking_tests/tracking_tests.pro b/tracking/tracking_tests/tracking_tests.pro index 81465b60aa..6009b5ffda 100644 --- a/tracking/tracking_tests/tracking_tests.pro +++ b/tracking/tracking_tests/tracking_tests.pro @@ -26,4 +26,5 @@ win*|linux* { SOURCES += \ $$ROOT_DIR/testing/testingmain.cpp \ - reporter_test.cpp + protocol_test.cpp \ + reporter_test.cpp \ |