blob: 97c6b1333d6113981b6c1e035a9ce15868ba27be [file] [log] [blame]
Ryan Haining2c1efe62018-12-20 17:44:33 -08001/*
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
30namespace {
31std::uint16_t HostOrderUInt16(const void* src) {
32 std::uint16_t result{};
33 std::memcpy(&result, src, sizeof result);
34 return htons(result);
35}
36
37std::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
44using cfp::ClientSocket;
45
46ClientSocket::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
71ClientSocket::~ClientSocket() { close(); }
72
73ClientSocket::ClientSocket(ClientSocket&& other)
74 : socket_fd_{other.socket_fd_} {
75 other.socket_fd_ = -1;
76}
77
78ClientSocket& ClientSocket::operator=(ClientSocket&& other) {
79 close();
80 socket_fd_ = other.socket_fd_;
81 other.socket_fd_ = -1;
82 return *this;
83}
84
85std::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
100std::uint16_t ClientSocket::RecvUInt16() {
101 return HostOrderUInt16(RecvAll(sizeof(std::uint16_t)).data());
102}
103
104std::uint32_t ClientSocket::RecvUInt32() {
105 return HostOrderUInt32(RecvAll(sizeof(std::uint32_t)).data());
106}
107
108void ClientSocket::close() {
109 if (socket_fd_ >= 0) {
110 ::close(socket_fd_);
111 socket_fd_ = -1;
112 }
113}