Skip to content
Snippets Groups Projects
Commit 76ab9293 authored by Adrien Béraud's avatar Adrien Béraud Committed by Adrien Béraud
Browse files

gitserver: cleanup

It all started from
  src/jamidht/gitserver.cpp: In member function ‘bool jami::GitServer::Impl::parseOrder(const uint8_t*, std::size_t)’:
  src/jamidht/gitserver.cpp:111:9: warning: ‘pkt_len’ may be used uninitialized [-Wmaybe-uninitialized]

Change-Id: I2ac85ed1c21ecf346aecd71cd1d0ccf9d6cf6024
parent 2008feb8
No related branches found
No related tags found
No related merge requests found
...@@ -34,6 +34,7 @@ using namespace std::string_view_literals; ...@@ -34,6 +34,7 @@ using namespace std::string_view_literals;
constexpr auto FLUSH_PKT = "0000"sv; constexpr auto FLUSH_PKT = "0000"sv;
constexpr auto NAK_PKT = "0008NAK\n"sv; constexpr auto NAK_PKT = "0008NAK\n"sv;
constexpr auto DONE_PKT = "0009done\n"sv; constexpr auto DONE_PKT = "0009done\n"sv;
constexpr auto DONE_CMD = "done\n"sv;
constexpr auto WANT_CMD = "want"sv; constexpr auto WANT_CMD = "want"sv;
constexpr auto HAVE_CMD = "have"sv; constexpr auto HAVE_CMD = "have"sv;
constexpr auto SERVER_CAPABILITIES constexpr auto SERVER_CAPABILITIES
...@@ -55,11 +56,8 @@ public: ...@@ -55,11 +56,8 @@ public:
std::lock_guard<std::mutex> lk(destroyMtx_); std::lock_guard<std::mutex> lk(destroyMtx_);
if (isDestroying_) if (isDestroying_)
return len; return len;
std::string data(buf, buf + len); if (parseOrder(std::string_view((const char*)buf, len)))
auto needMoreParsing = parseOrder(buf, len); while(parseOrder());
while (needMoreParsing) {
needMoreParsing = parseOrder();
};
return len; return len;
}); });
} }
...@@ -72,15 +70,14 @@ public: ...@@ -72,15 +70,14 @@ public:
socket_->shutdown(); socket_->shutdown();
} }
} }
bool parseOrder(const uint8_t* buf = nullptr, std::size_t len = 0); bool parseOrder(std::string_view buf = {});
void sendReferenceCapabilities(bool sendVersion = false); void sendReferenceCapabilities(bool sendVersion = false);
void answerToWantOrder();
bool NAK(); bool NAK();
void ACKCommon(); void ACKCommon();
bool ACKFirst(); bool ACKFirst();
void sendPackData(); void sendPackData();
std::map<std::string, std::string> getParameters(const std::string& pkt_line); std::map<std::string, std::string> getParameters(std::string_view pkt_line);
std::string repositoryId_ {}; std::string repositoryId_ {};
std::string repository_ {}; std::string repository_ {};
...@@ -95,36 +92,65 @@ public: ...@@ -95,36 +92,65 @@ public:
}; };
bool bool
GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len) GitServer::Impl::parseOrder(std::string_view buf)
{ {
std::string pkt = cachedPkt_; std::string pkt = std::move(cachedPkt_);
if (buf) if (!buf.empty())
pkt += std::string({buf, buf + len}); pkt += buf;
cachedPkt_.clear();
// Parse pkt len // Parse pkt len
// Reference: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt#L51 // Reference: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt#L51
// The first four bytes define the length of the packet and 0000 is a FLUSH pkt // The first four bytes define the length of the packet and 0000 is a FLUSH pkt
unsigned int pkt_len; unsigned int pkt_len = 0;
std::from_chars(pkt.data(), pkt.data() + 4, pkt_len, 16); auto [p, ec] = std::from_chars(pkt.data(), pkt.data() + 4, pkt_len, 16);
if (ec != std::errc()) {
JAMI_ERROR("Can't parse packet size");
}
if (pkt_len != pkt.size()) { if (pkt_len != pkt.size()) {
// Store next packet part // Store next packet part
if (pkt_len == 0) { if (pkt_len == 0) {
// FLUSH_PKT // FLUSH_PKT
pkt_len = 4; pkt_len = 4;
} }
cachedPkt_ = pkt.substr(pkt_len, pkt.size() - pkt_len); cachedPkt_ = pkt.substr(pkt_len);
}
auto pack = std::string_view(pkt).substr(4, pkt_len - 4);
if (pack == DONE_CMD) {
// Reference:
// https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L390 Do
// not do multi-ack, just send ACK + pack file
// In case of no common base, send NAK
JAMI_INFO("Peer negotiation is done. Answering to want order");
bool sendData;
if (common_.empty())
sendData = NAK();
else
sendData = ACKFirst();
if (sendData)
sendPackData();
return !cachedPkt_.empty();
} else if (pack.empty()) {
if (!haveRefs_.empty()) {
// Reference:
// https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L390
// Do not do multi-ack, just send ACK + pack file In case of no common base ACK
ACKCommon();
NAK();
}
return !cachedPkt_.empty();
} }
// NOTE: do not remove the size to detect the 0009done packet
pkt = pkt.substr(0, pkt_len);
if (pkt.find(UPLOAD_PACK_CMD) == 4) { auto lim = pack.find(' ');
auto cmd = pack.substr(0, lim);
auto dat = (lim < pack.size()) ? pack.substr(lim+1) : std::string_view{};
if (cmd == UPLOAD_PACK_CMD) {
// Cf: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L166 // Cf: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L166
// References discovery // References discovery
JAMI_INFO("Upload pack command detected."); JAMI_INFO("Upload pack command detected.");
auto version = 1; auto version = 1;
auto parameters = getParameters(pkt); auto parameters = getParameters(dat);
auto versionIt = parameters.find("version"); auto versionIt = parameters.find("version");
bool sendVersion = false; bool sendVersion = false;
if (versionIt != parameters.end()) { if (versionIt != parameters.end()) {
...@@ -132,7 +158,7 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len) ...@@ -132,7 +158,7 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len)
version = std::stoi(versionIt->second); version = std::stoi(versionIt->second);
sendVersion = true; sendVersion = true;
} catch (...) { } catch (...) {
JAMI_WARN("Invalid version detected: %s", versionIt->second.c_str()); JAMI_WARNING("Invalid version detected: {}", versionIt->second);
} }
} }
if (version == 1) { if (version == 1) {
...@@ -140,18 +166,14 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len) ...@@ -140,18 +166,14 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len)
} else { } else {
JAMI_ERR("That protocol version is not yet supported (version: %u)", version); JAMI_ERR("That protocol version is not yet supported (version: %u)", version);
} }
} else if (pkt.find(WANT_CMD) == 4) { } else if (cmd == WANT_CMD) {
// Reference: // Reference:
// https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L229 // https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L229
// TODO can have more want // TODO can have more want
auto content = pkt.substr(5, pkt_len - 5); wantedReference_ = dat.substr(0, 40);
auto commit = content.substr(4, 40);
wantedReference_ = commit;
JAMI_INFO("Peer want ref: %s", wantedReference_.c_str()); JAMI_INFO("Peer want ref: %s", wantedReference_.c_str());
} else if (pkt.find(HAVE_CMD) == 4) { } else if (cmd == HAVE_CMD) {
auto content = pkt.substr(5, pkt_len - 5); const auto& commit = haveRefs_.emplace_back(dat.substr(0, 40));
auto commit = content.substr(4, 40);
haveRefs_.emplace_back(commit);
if (common_.empty()) { if (common_.empty()) {
// Detect first common commit // Detect first common commit
// Reference: // Reference:
...@@ -169,29 +191,8 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len) ...@@ -169,29 +191,8 @@ GitServer::Impl::parseOrder(const uint8_t* buf, std::size_t len)
common_ = commit; common_ = commit;
} }
} }
} else if (pkt == DONE_PKT) {
// Reference:
// https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L390 Do
// not do multi-ack, just send ACK + pack file
// In case of no common base, send NAK
JAMI_INFO("Peer negotiation is done. Answering to want order");
bool sendData;
if (common_.empty())
sendData = NAK();
else
sendData = ACKFirst();
if (sendData)
sendPackData();
} else if (pkt == FLUSH_PKT) {
if (!haveRefs_.empty()) {
// Reference:
// https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L390
// Do not do multi-ack, just send ACK + pack file In case of no common base ACK
ACKCommon();
NAK();
}
} else { } else {
JAMI_WARN("Unwanted packet received: %s", pkt.c_str()); JAMI_WARNING("Unwanted packet received: {}", pkt);
} }
return !cachedPkt_.empty(); return !cachedPkt_.empty();
} }
...@@ -432,18 +433,17 @@ GitServer::Impl::sendPackData() ...@@ -432,18 +433,17 @@ GitServer::Impl::sendPackData()
} }
std::map<std::string, std::string> std::map<std::string, std::string>
GitServer::Impl::getParameters(const std::string& pkt_line) GitServer::Impl::getParameters(std::string_view pkt_line)
{ {
std::map<std::string, std::string> parameters; std::map<std::string, std::string> parameters;
std::string key, value; std::string key, value;
auto isKey = true; auto isKey = true;
auto nullChar = 0; auto nullChar = 0;
for (std::size_t i = 0; i < pkt_line.size(); ++i) { for (auto letter: pkt_line) {
auto letter = pkt_line[i];
if (letter == '\0') { if (letter == '\0') {
// parameters such as host or version are after the first \0 // parameters such as host or version are after the first \0
if (nullChar != 0 && !key.empty()) { if (nullChar != 0 && !key.empty()) {
parameters[key] = value; parameters[std::move(key)] = std::move(value);
} }
nullChar += 1; nullChar += 1;
isKey = true; isKey = true;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment