1 #pragma once
2
3 /*
4 * Copyright (C) 2017 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "common/libs/fs/shared_fd.h"
20
21 #include <unistd.h>
22
23 #include <cstddef>
24 #include <cstdint>
25 #include <mutex>
26 #include <vector>
27
28 namespace cvd {
29 using Message = std::vector<std::uint8_t>;
30
31 class ServerSocket;
32
33 // Recv and Send wait until all data has been received or sent.
34 // Send is thread safe in this regard, Recv is not.
35 class ClientSocket {
36 public:
ClientSocket(ClientSocket && other)37 ClientSocket(ClientSocket&& other) : fd_{other.fd_} {}
38
39 ClientSocket& operator=(ClientSocket&& other) {
40 fd_ = other.fd_;
41 return *this;
42 }
43
44 ClientSocket(int port);
45
46 ClientSocket(const ClientSocket&) = delete;
47 ClientSocket& operator=(const ClientSocket&) = delete;
48
49 Message Recv(std::size_t length);
50 // RecvAny will receive whatever is available.
51 // An empty message returned indicates error or close.
52 Message RecvAny(std::size_t length);
53 // Sends are called with MSG_NOSIGNAL to suppress SIGPIPE
54 ssize_t SendNoSignal(const std::uint8_t* data, std::size_t size);
55 ssize_t SendNoSignal(const Message& message);
56
57 template <std::size_t N>
SendNoSignal(const std::uint8_t (& data)[N])58 ssize_t SendNoSignal(const std::uint8_t (&data)[N]) {
59 return SendNoSignal(data, N);
60 }
61
62 bool closed() const;
63
64 private:
65 friend ServerSocket;
ClientSocket(cvd::SharedFD fd)66 explicit ClientSocket(cvd::SharedFD fd) : fd_(fd) {}
67
68 cvd::SharedFD fd_;
69 bool other_side_closed_{};
70 mutable std::mutex closed_lock_;
71 std::mutex send_lock_;
72 };
73
74 class ServerSocket {
75 public:
76 explicit ServerSocket(int port);
77
78 ServerSocket(const ServerSocket&) = delete;
79 ServerSocket& operator=(const ServerSocket&) = delete;
80
81 ClientSocket Accept();
82
83 private:
84 cvd::SharedFD fd_;
85 };
86
87 void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b);
88 void AppendInNetworkByteOrder(Message* msg, const std::uint16_t s);
89 void AppendInNetworkByteOrder(Message* msg, const std::uint32_t w);
90 void AppendInNetworkByteOrder(Message* msg, const std::int32_t w);
91 void AppendInNetworkByteOrder(Message* msg, const std::string& str);
92
AppendToMessage(Message *)93 inline void AppendToMessage(Message*) {}
94
95 template <typename T, typename... Ts>
AppendToMessage(Message * msg,T v,Ts...vals)96 void AppendToMessage(Message* msg, T v, Ts... vals) {
97 AppendInNetworkByteOrder(msg, v);
98 AppendToMessage(msg, vals...);
99 }
100
101 template <typename... Ts>
CreateMessage(Ts...vals)102 Message CreateMessage(Ts... vals) {
103 Message m;
104 AppendToMessage(&m, vals...);
105 return m;
106 }
107
108 } // namespace cvd
109