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 <string>
27 #include <vector>
28
29 namespace cuttlefish {
30 using Message = std::vector<std::uint8_t>;
31
32 // Recv and Send wait until all data has been received or sent.
33 // Send is thread safe in this regard, Recv is not.
34 class ClientSocket {
35 public:
ClientSocket(ClientSocket && other)36 ClientSocket(ClientSocket&& other) : fd_{other.fd_} {}
37
38 ClientSocket& operator=(ClientSocket&& other) {
39 fd_ = other.fd_;
40 return *this;
41 }
42
43 ClientSocket(int port);
44
45 ClientSocket(const ClientSocket&) = delete;
46 ClientSocket& operator=(const ClientSocket&) = delete;
47
48 Message Recv(std::size_t length);
49 // RecvAny will receive whatever is available.
50 // An empty message returned indicates error or close.
51 Message RecvAny(std::size_t length);
52 // Sends are called with MSG_NOSIGNAL to suppress SIGPIPE
53 ssize_t SendNoSignal(const std::uint8_t* data, std::size_t size);
54 ssize_t SendNoSignal(const Message& message);
55
56 template <std::size_t N>
SendNoSignal(const std::uint8_t (& data)[N])57 ssize_t SendNoSignal(const std::uint8_t (&data)[N]) {
58 return SendNoSignal(data, N);
59 }
60
61 bool closed() const;
62
63 private:
64 friend class ServerSocket;
ClientSocket(SharedFD fd)65 explicit ClientSocket(SharedFD fd) : fd_(fd) {}
66
67 SharedFD fd_;
68 bool other_side_closed_{};
69 mutable std::mutex closed_lock_;
70 std::mutex send_lock_;
71 };
72
73 class ServerSocket {
74 public:
75 explicit ServerSocket(int port);
76
77 ServerSocket(const ServerSocket&) = delete;
78 ServerSocket& operator=(const ServerSocket&) = delete;
79
80 ClientSocket Accept();
81
82 private:
83 SharedFD fd_;
84 };
85
86 void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b);
87 void AppendInNetworkByteOrder(Message* msg, const std::uint16_t s);
88 void AppendInNetworkByteOrder(Message* msg, const std::uint32_t w);
89 void AppendInNetworkByteOrder(Message* msg, const std::int32_t w);
90 void AppendInNetworkByteOrder(Message* msg, const std::string& str);
91
AppendToMessage(Message *)92 inline void AppendToMessage(Message*) {}
93
94 template <typename T, typename... Ts>
AppendToMessage(Message * msg,T v,Ts...vals)95 void AppendToMessage(Message* msg, T v, Ts... vals) {
96 AppendInNetworkByteOrder(msg, v);
97 AppendToMessage(msg, vals...);
98 }
99
100 template <typename... Ts>
CreateMessage(Ts...vals)101 Message CreateMessage(Ts... vals) {
102 Message m;
103 AppendToMessage(&m, vals...);
104 return m;
105 }
106
107 } // namespace cuttlefish
108