1 /*
2  *
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include "client_socket.h"
18 
19 #include "android-base/logging.h"
20 
21 #include <arpa/inet.h>
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 
26 #include <cstdint>
27 #include <cstring>
28 #include <vector>
29 
30 namespace {
HostOrderUInt16(const void * src)31 std::uint16_t HostOrderUInt16(const void* src) {
32   std::uint16_t result{};
33   std::memcpy(&result, src, sizeof result);
34   return htons(result);
35 }
36 
HostOrderUInt32(const void * src)37 std::uint32_t HostOrderUInt32(const void* src) {
38   std::uint32_t result{};
39   std::memcpy(&result, src, sizeof result);
40   return htonl(result);
41 }
42 }  // namespace
43 
44 using cfp::ClientSocket;
45 
ClientSocket(std::uint16_t port)46 ClientSocket::ClientSocket(std::uint16_t port)
47     : socket_fd_{socket(AF_INET, SOCK_STREAM, 0)} {
48   sockaddr_in server_addr{};
49 
50   if (socket_fd_ < 0) {
51     LOG(ERROR) << "couldn't create socket\n";
52     return;
53   }
54   server_addr.sin_family = AF_INET;
55   server_addr.sin_port = htons(port);
56 
57   if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
58     LOG(ERROR) << "couldn't convert localhost address\n";
59     close();
60     return;
61   }
62 
63   if (connect(socket_fd_, reinterpret_cast<sockaddr*>(&server_addr),
64               sizeof server_addr) < 0) {
65     LOG(ERROR) << "connection failed\n";
66     close();
67     return;
68   }
69 }
70 
~ClientSocket()71 ClientSocket::~ClientSocket() { close(); }
72 
ClientSocket(ClientSocket && other)73 ClientSocket::ClientSocket(ClientSocket&& other)
74     : socket_fd_{other.socket_fd_} {
75   other.socket_fd_ = -1;
76 }
77 
operator =(ClientSocket && other)78 ClientSocket& ClientSocket::operator=(ClientSocket&& other) {
79   close();
80   socket_fd_ = other.socket_fd_;
81   other.socket_fd_ = -1;
82   return *this;
83 }
84 
RecvAll(ssize_t count)85 std::vector<unsigned char> ClientSocket::RecvAll(ssize_t count) {
86   std::vector<unsigned char> buf(count);
87   size_t total_read = 0;
88   while (total_read < buf.size()) {
89     auto just_read =
90         read(socket_fd_, buf.data() + total_read, buf.size() - total_read);
91     if (just_read <= 0) {
92       LOG(ERROR) << "read failed";
93       return {};
94     }
95     total_read += static_cast<size_t>(just_read);
96   }
97   return buf;
98 }
99 
RecvUInt16()100 std::uint16_t ClientSocket::RecvUInt16() {
101   return HostOrderUInt16(RecvAll(sizeof(std::uint16_t)).data());
102 }
103 
RecvUInt32()104 std::uint32_t ClientSocket::RecvUInt32() {
105   return HostOrderUInt32(RecvAll(sizeof(std::uint32_t)).data());
106 }
107 
close()108 void ClientSocket::close() {
109   if (socket_fd_ >= 0) {
110     ::close(socket_fd_);
111     socket_fd_ = -1;
112   }
113 }
114