blob: eb094a1743958e9f948f0ecd8817593e21035b7f [file] [log] [blame]
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +00001//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Other libraries and framework includes
11#include "lldb/Host/ConnectionFileDescriptor.h"
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/STLExtras.h"
15
16// Project includes
17#include "AdbClient.h"
18
19#include <sstream>
20
21using namespace lldb;
22using namespace lldb_private;
23
24namespace {
25
26const uint32_t kConnTimeout = 10000; // 10 ms
27const char * kOKAY = "OKAY";
28const char * kFAIL = "FAIL";
29
30} // namespace
31
32AdbClient::AdbClient (const std::string &device_id)
33 : m_device_id (device_id)
34{
35}
36
37void
38AdbClient::SetDeviceID (const std::string& device_id)
39{
40 m_device_id = device_id;
41}
42
43Error
44AdbClient::Connect ()
45{
46 Error error;
47 m_conn.Connect ("connect://localhost:5037", &error);
48
49 return error;
50}
51
52Error
53AdbClient::GetDevices (DeviceIDList &device_list)
54{
55 device_list.clear ();
56
57 auto error = SendMessage ("host:devices");
58 if (error.Fail ())
59 return error;
60
61 error = ReadResponseStatus ();
62 if (error.Fail ())
63 return error;
64
65 std::string in_buffer;
66 error = ReadMessage (in_buffer);
67
68 llvm::StringRef response (in_buffer);
69 llvm::SmallVector<llvm::StringRef, 4> devices;
70 response.split (devices, "\n", -1, false);
71
72 for (const auto device: devices)
73 device_list.push_back (device.split ('\t').first);
74
75 return error;
76}
77
78Error
79AdbClient::SetPortForwarding (const uint16_t port)
80{
81 char message[48];
82 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
83
84 const auto error = SendDeviceMessage (message);
85 if (error.Fail ())
86 return error;
87
88 return ReadResponseStatus ();
89}
90
91Error
92AdbClient::DeletePortForwarding (const uint16_t port)
93{
94 char message[32];
95 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
96
97 const auto error = SendDeviceMessage (message);
98 if (error.Fail ())
99 return error;
100
101 return ReadResponseStatus ();
102}
103
104Error
105AdbClient::SendMessage (const std::string &packet)
106{
107 auto error = Connect ();
108 if (error.Fail ())
109 return error;
110
111 char length_buffer[5];
112 snprintf (length_buffer, sizeof (length_buffer), "%04zx", packet.size ());
113
114 ConnectionStatus status;
115
116 m_conn.Write (length_buffer, 4, status, &error);
117 if (error.Fail ())
118 return error;
119
120 m_conn.Write (packet.c_str (), packet.size (), status, &error);
121 return error;
122}
123
124Error
125AdbClient::SendDeviceMessage (const std::string &packet)
126{
127 std::ostringstream msg;
128 msg << "host-serial:" << m_device_id << ":" << packet;
129 return SendMessage (msg.str ());
130}
131
132Error
133AdbClient::ReadMessage (std::string &message)
134{
135 message.clear ();
136
137 char buffer[5];
138 buffer[4] = 0;
139
140 Error error;
141 ConnectionStatus status;
142
143 m_conn.Read (buffer, 4, kConnTimeout, status, &error);
144 if (error.Fail ())
145 return error;
146
147 size_t packet_len = 0;
148 sscanf (buffer, "%zx", &packet_len);
149 std::string result (packet_len, 0);
150 m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error);
151 if (error.Success ())
152 result.swap (message);
153
154 return error;
155}
156
157Error
158AdbClient::ReadResponseStatus()
159{
160 char buffer[5];
161
162 static const size_t packet_len = 4;
163 buffer[packet_len] = 0;
164
165 Error error;
166 ConnectionStatus status;
167
168 m_conn.Read (buffer, packet_len, kConnTimeout, status, &error);
169 if (error.Fail ())
170 return error;
171
172 if (strncmp (buffer, kOKAY, packet_len) != 0)
173 {
174 if (strncmp (buffer, kFAIL, packet_len) == 0)
175 {
176 std::string error_message;
177 error = ReadMessage (error_message);
178 if (error.Fail ())
179 return error;
180 error.SetErrorString (error_message.c_str ());
181 }
182 else
183 error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer);
184 }
185
186 return error;
187}