Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <dhtnet/channel_socket.h>
21 :
22 : #include <memory>
23 : #include <utility>
24 :
25 : namespace jami {
26 :
27 : /**
28 : * Exclusive ownership of a git channel.
29 : *
30 : * Letting go of a shared_ptr to a channel closes nothing: the channel stays
31 : * registered in its multiplexed socket, and the peer keeps a GitServer running
32 : * for it, until one side sends EOF. Storing a channel in this holder makes the
33 : * slot holding it its owner, so a channel cannot be forgotten without being
34 : * closed.
35 : */
36 : class GitSocket
37 : {
38 : public:
39 1015 : GitSocket() = default;
40 1015 : GitSocket(std::shared_ptr<dhtnet::ChannelSocket> socket) noexcept
41 1015 : : socket_(std::move(socket))
42 1015 : {}
43 : GitSocket(GitSocket&&) noexcept = default;
44 2559 : GitSocket& operator=(GitSocket&& other) noexcept
45 : {
46 2559 : if (this != &other) {
47 : // Re-taking ownership of the channel we already hold must not close it.
48 2559 : if (socket_ != other.socket_)
49 1544 : reset();
50 2560 : socket_ = std::move(other.socket_);
51 : }
52 2558 : return *this;
53 : }
54 : GitSocket(const GitSocket&) = delete;
55 : GitSocket& operator=(const GitSocket&) = delete;
56 5054 : ~GitSocket() { reset(); }
57 :
58 24 : explicit operator bool() const noexcept { return static_cast<bool>(socket_); }
59 24 : dhtnet::ChannelSocket* operator->() const noexcept { return socket_.get(); }
60 5653 : const std::shared_ptr<dhtnet::ChannelSocket>& get() const noexcept { return socket_; }
61 :
62 : /** Close the channel and let go of it. */
63 6595 : void reset()
64 : {
65 6595 : if (auto socket = std::move(socket_))
66 6592 : socket->shutdown();
67 6594 : }
68 :
69 : /** Hand the channel over to another owner, leaving it open. */
70 : std::shared_ptr<dhtnet::ChannelSocket> release() noexcept
71 : {
72 : return std::exchange(socket_, nullptr);
73 : }
74 :
75 : private:
76 : std::shared_ptr<dhtnet::ChannelSocket> socket_ {};
77 : };
78 :
79 : } // namespace jami
|