blob: 95cc48f678ca3cd4df682406ec24deba0c20edee [file] [log] [blame]
Garrick Evans3cbac7c2019-04-18 15:31:31 +09001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#ifndef PATCHPANEL_SOCKET_FORWARDER_H_
6#define PATCHPANEL_SOCKET_FORWARDER_H_
Garrick Evans3cbac7c2019-04-18 15:31:31 +09007
8#include <netinet/ip.h>
9#include <sys/socket.h>
10
Garrick Evans7db0dda2019-05-20 11:50:06 +090011#include <atomic>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090012#include <memory>
13#include <string>
14
Andreea Costinas456ee5b2020-09-08 15:11:43 +020015#include <base/callback.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090016#include <base/macros.h>
17#include <base/memory/weak_ptr.h>
18#include <base/threading/simple_thread.h>
Andreea Costinas74f45d22020-03-13 10:29:31 +010019#include <brillo/brillo_export.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090020
Garrick Evans3388a032020-03-24 11:25:55 +090021#include "patchpanel/socket.h"
Garrick Evans3cbac7c2019-04-18 15:31:31 +090022
Garrick Evans3388a032020-03-24 11:25:55 +090023namespace patchpanel {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090024// Forwards data between a pair of sockets.
25// This is a simple implementation as a thread main function.
Andreea Costinas74f45d22020-03-13 10:29:31 +010026class BRILLO_EXPORT SocketForwarder : public base::SimpleThread {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090027 public:
28 SocketForwarder(const std::string& name,
29 std::unique_ptr<Socket> sock0,
30 std::unique_ptr<Socket> sock1);
31 virtual ~SocketForwarder();
32
33 // Runs the forwarder. The sockets are closed and released on exit,
34 // so this can only be run once.
35 void Run() override;
Garrick Evans088cd0e2019-06-04 15:20:43 +090036 bool IsRunning() const;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090037
Andreea Costinas456ee5b2020-09-08 15:11:43 +020038 // Sets a closure for testing, which will be called when the forwarder is
39 // stopped.
40 void SetStopQuitClosureForTesting(base::OnceClosure closure);
41
Garrick Evans3cbac7c2019-04-18 15:31:31 +090042 private:
Garrick Evans7db0dda2019-05-20 11:50:06 +090043 static constexpr int kBufSize = 4096;
44
45 void Poll();
Garrick Evans7db0dda2019-05-20 11:50:06 +090046 bool ProcessEvents(uint32_t events, int efd, int cfd);
47
Garrick Evans3cbac7c2019-04-18 15:31:31 +090048 std::unique_ptr<Socket> sock0_;
49 std::unique_ptr<Socket> sock1_;
Garrick Evans7db0dda2019-05-20 11:50:06 +090050 char buf0_[kBufSize] = {0};
51 char buf1_[kBufSize] = {0};
52 ssize_t len0_;
53 ssize_t len1_;
Andreea Costinas456ee5b2020-09-08 15:11:43 +020054 // Indicates if an EOF has been sent (if it is greater than -1) and which
55 // socket fd it was received on. This means that the socket file descriptor
56 // indicated here should not be read from, only written to.
57 int eof_;
58 // Handles the case when the peer associated with |src| was closed for
59 // writing. If the other peer is still open, the SocketForwarder will stop
60 // listening for read events on the |src| socket, forward the write shutdown
61 // to |dst| and return true to continue forwarding data received from the
62 // other peer. If the |dst| socket is also closed for writing, it will return
63 // false, which will stop the SocketForwarder instance. In case of error, it
64 // returns false.
65 bool HandleConnectionClosed(Socket* src, Socket* dst, int cfd);
Garrick Evans7db0dda2019-05-20 11:50:06 +090066
67 std::atomic<bool> poll_;
68 std::atomic<bool> done_;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090069
Andreea Costinas456ee5b2020-09-08 15:11:43 +020070 base::OnceClosure stop_quit_closure_for_testing_;
71
Garrick Evans3cbac7c2019-04-18 15:31:31 +090072 DISALLOW_COPY_AND_ASSIGN(SocketForwarder);
73};
74
Garrick Evans3388a032020-03-24 11:25:55 +090075} // namespace patchpanel
Garrick Evans3cbac7c2019-04-18 15:31:31 +090076
Garrick Evans3388a032020-03-24 11:25:55 +090077#endif // PATCHPANEL_SOCKET_FORWARDER_H_