1 //
2 // Copyright 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #define LOG_TAG "test_channel_transport"
18
19 #include "test_channel_transport.h"
20
21 #include <base/logging.h>
22
23 #include "osi/include/log.h"
24 #include "osi/include/osi.h"
25
26 #include <netinet/in.h>
27 #include <sys/socket.h>
28
29 using std::vector;
30
31 namespace test_vendor_lib {
32
SetUp(int port)33 int TestChannelTransport::SetUp(int port) {
34 struct sockaddr_in listen_address;
35 socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
36 memset(&listen_address, 0, sockaddr_in_size);
37
38 OSI_NO_INTR(listen_fd_ = socket(AF_INET, SOCK_STREAM, 0));
39 if (listen_fd_ < 0) {
40 LOG_INFO(LOG_TAG, "Error creating socket for test channel.");
41 return -1;
42 }
43
44 LOG_INFO(LOG_TAG, "port: %d", port);
45 listen_address.sin_family = AF_INET;
46 listen_address.sin_port = htons(port);
47 listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
48
49 if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address),
50 sockaddr_in_size) < 0) {
51 LOG_INFO(LOG_TAG, "Error binding test channel listener socket to address.");
52 close(listen_fd_);
53 return -1;
54 }
55
56 if (listen(listen_fd_, 1) < 0) {
57 LOG_INFO(LOG_TAG, "Error listening for test channel.");
58 close(listen_fd_);
59 return -1;
60 }
61 return listen_fd_;
62 }
63
CleanUp()64 void TestChannelTransport::CleanUp() {
65 if (listen_fd_ == -1) {
66 return;
67 }
68 if (close(listen_fd_)) {
69 LOG_ERROR(LOG_TAG, "Error closing listen_fd_.");
70 }
71 listen_fd_ = -1;
72 }
73
Accept(int listen_fd_)74 int TestChannelTransport::Accept(int listen_fd_) {
75 int accept_fd = -1;
76 struct sockaddr_in test_channel_address;
77 socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
78 memset(&test_channel_address, 0, sockaddr_in_size);
79
80 OSI_NO_INTR(accept_fd = accept(listen_fd_, reinterpret_cast<sockaddr*>(
81 &test_channel_address),
82 &sockaddr_in_size));
83 if (accept_fd < 0) {
84 LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).",
85 errno, strerror(errno));
86
87 if (errno != EAGAIN && errno != EWOULDBLOCK) {
88 LOG_ERROR(LOG_TAG, "Closing listen_fd_ (won't try again).");
89 close(listen_fd_);
90 return -1;
91 }
92 }
93
94 LOG_INFO(LOG_TAG, "accept_fd = %d.", accept_fd);
95
96 return accept_fd;
97 }
98
OnCommandReady(int fd,std::function<void (void)> unwatch)99 void TestChannelTransport::OnCommandReady(int fd,
100 std::function<void(void)> unwatch) {
101 uint8_t command_name_size = 0;
102 read(fd, &command_name_size, 1);
103 vector<uint8_t> command_name_raw;
104 command_name_raw.resize(command_name_size);
105 read(fd, &command_name_raw[0], command_name_size);
106 std::string command_name(command_name_raw.begin(), command_name_raw.end());
107 LOG_INFO(LOG_TAG, "Received command from test channel: %s",
108 command_name.data());
109
110 if (command_name == "CLOSE_TEST_CHANNEL" || command_name == "") {
111 LOG_INFO(LOG_TAG, "Test channel closed");
112 unwatch();
113 close(fd);
114 return;
115 }
116
117 uint8_t num_args = 0;
118 read(fd, &num_args, 1);
119 LOG_INFO(LOG_TAG, "num_args: %d", num_args);
120 vector<std::string> args;
121 for (uint8_t i = 0; i < num_args; ++i) {
122 uint8_t arg_size = 0;
123 read(fd, &arg_size, 1);
124 vector<uint8_t> arg;
125 arg.resize(arg_size);
126 read(fd, &arg[0], arg_size);
127 args.push_back(std::string(arg.begin(), arg.end()));
128 }
129
130 for (size_t i = 0; i < args.size(); ++i)
131 LOG_INFO(LOG_TAG, "Command argument %zu: %s", i, args[i].data());
132
133 command_handler_(command_name, args);
134 }
135
RegisterCommandHandler(const std::function<void (const std::string &,const vector<std::string> &)> & callback)136 void TestChannelTransport::RegisterCommandHandler(
137 const std::function<void(const std::string&, const vector<std::string>&)>&
138 callback) {
139 command_handler_ = callback;
140 }
141
142 } // namespace test_vendor_lib {
143