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