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 "glog/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