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