blob: 8c6b491e0d59513561486c3c63672241f6e52490 [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);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090031 SocketForwarder(const SocketForwarder&) = delete;
32 SocketForwarder& operator=(const SocketForwarder&) = delete;
33
Garrick Evans3cbac7c2019-04-18 15:31:31 +090034 virtual ~SocketForwarder();
35
36 // Runs the forwarder. The sockets are closed and released on exit,
37 // so this can only be run once.
38 void Run() override;
Garrick Evans088cd0e2019-06-04 15:20:43 +090039 bool IsRunning() const;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090040
Andreea Costinas456ee5b2020-09-08 15:11:43 +020041 // Sets a closure for testing, which will be called when the forwarder is
42 // stopped.
43 void SetStopQuitClosureForTesting(base::OnceClosure closure);
44
Garrick Evans3cbac7c2019-04-18 15:31:31 +090045 private:
Garrick Evans7db0dda2019-05-20 11:50:06 +090046 static constexpr int kBufSize = 4096;
47
48 void Poll();
Garrick Evans7db0dda2019-05-20 11:50:06 +090049 bool ProcessEvents(uint32_t events, int efd, int cfd);
50
Garrick Evans3cbac7c2019-04-18 15:31:31 +090051 std::unique_ptr<Socket> sock0_;
52 std::unique_ptr<Socket> sock1_;
Garrick Evans7db0dda2019-05-20 11:50:06 +090053 char buf0_[kBufSize] = {0};
54 char buf1_[kBufSize] = {0};
55 ssize_t len0_;
56 ssize_t len1_;
Andreea Costinas456ee5b2020-09-08 15:11:43 +020057 // Indicates if an EOF has been sent (if it is greater than -1) and which
58 // socket fd it was received on. This means that the socket file descriptor
59 // indicated here should not be read from, only written to.
60 int eof_;
61 // Handles the case when the peer associated with |src| was closed for
62 // writing. If the other peer is still open, the SocketForwarder will stop
63 // listening for read events on the |src| socket, forward the write shutdown
64 // to |dst| and return true to continue forwarding data received from the
65 // other peer. If the |dst| socket is also closed for writing, it will return
66 // false, which will stop the SocketForwarder instance. In case of error, it
67 // returns false.
68 bool HandleConnectionClosed(Socket* src, Socket* dst, int cfd);
Garrick Evans7db0dda2019-05-20 11:50:06 +090069
70 std::atomic<bool> poll_;
71 std::atomic<bool> done_;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090072
Andreea Costinas456ee5b2020-09-08 15:11:43 +020073 base::OnceClosure stop_quit_closure_for_testing_;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090074};
75
Garrick Evans3388a032020-03-24 11:25:55 +090076} // namespace patchpanel
Garrick Evans3cbac7c2019-04-18 15:31:31 +090077
Garrick Evans3388a032020-03-24 11:25:55 +090078#endif // PATCHPANEL_SOCKET_FORWARDER_H_