Merge changes Ida272d21,If3f29f9e,I7dc5258d,I55258c15,Ibad79770
* changes: adb: win32: cleanup winsock initialization. adb: win32: properly set EBADF in some functions. adb: partially clang-format sysdeps_win32.cpp. adb: implement adb_writev. adb: switch apacket payload to a type that doesn't initialize its contents.
This commit is contained in:
commit
cd71fd5109
16
adb/adb.cpp
16
adb/adb.cpp
|
@ -257,7 +257,7 @@ void send_connect(atransport* t) {
|
|||
<< connection_str.length() << ")";
|
||||
}
|
||||
|
||||
cp->payload = std::move(connection_str);
|
||||
cp->payload.assign(connection_str.begin(), connection_str.end());
|
||||
cp->msg.data_length = cp->payload.size();
|
||||
|
||||
send_packet(cp, t);
|
||||
|
@ -329,7 +329,8 @@ static void handle_new_connection(atransport* t, apacket* p) {
|
|||
handle_offline(t);
|
||||
|
||||
t->update_version(p->msg.arg0, p->msg.arg1);
|
||||
parse_banner(p->payload, t);
|
||||
std::string banner(p->payload.begin(), p->payload.end());
|
||||
parse_banner(banner, t);
|
||||
|
||||
#if ADB_HOST
|
||||
handle_online(t);
|
||||
|
@ -369,8 +370,10 @@ void handle_packet(apacket *p, atransport *t)
|
|||
send_auth_response(p->payload.data(), p->msg.data_length, t);
|
||||
break;
|
||||
#else
|
||||
case ADB_AUTH_SIGNATURE:
|
||||
if (adbd_auth_verify(t->token, sizeof(t->token), p->payload)) {
|
||||
case ADB_AUTH_SIGNATURE: {
|
||||
// TODO: Switch to string_view.
|
||||
std::string signature(p->payload.begin(), p->payload.end());
|
||||
if (adbd_auth_verify(t->token, sizeof(t->token), signature)) {
|
||||
adbd_auth_verified(t);
|
||||
t->failed_auth_attempts = 0;
|
||||
} else {
|
||||
|
@ -378,6 +381,7 @@ void handle_packet(apacket *p, atransport *t)
|
|||
send_auth_request(t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ADB_AUTH_RSAPUBLICKEY:
|
||||
adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
|
||||
|
@ -392,7 +396,9 @@ void handle_packet(apacket *p, atransport *t)
|
|||
|
||||
case A_OPEN: /* OPEN(local-id, 0, "destination") */
|
||||
if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
|
||||
asocket* s = create_local_service_socket(p->payload.c_str(), t);
|
||||
// TODO: Switch to string_view.
|
||||
std::string address(p->payload.begin(), p->payload.end());
|
||||
asocket* s = create_local_service_socket(address.c_str(), t);
|
||||
if (s == nullptr) {
|
||||
send_close(0, p->msg.arg0, t);
|
||||
} else {
|
||||
|
|
15
adb/adb.h
15
adb/adb.h
|
@ -28,6 +28,7 @@
|
|||
#include "adb_trace.h"
|
||||
#include "fdevent.h"
|
||||
#include "socket.h"
|
||||
#include "types.h"
|
||||
#include "usb.h"
|
||||
|
||||
constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024;
|
||||
|
@ -63,20 +64,6 @@ std::string adb_version();
|
|||
using TransportId = uint64_t;
|
||||
class atransport;
|
||||
|
||||
struct amessage {
|
||||
uint32_t command; /* command identifier constant */
|
||||
uint32_t arg0; /* first argument */
|
||||
uint32_t arg1; /* second argument */
|
||||
uint32_t data_length; /* length of payload (0 is allowed) */
|
||||
uint32_t data_check; /* checksum of data payload */
|
||||
uint32_t magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
struct apacket {
|
||||
amessage msg;
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
uint32_t calculate_apacket_checksum(const apacket* packet);
|
||||
|
||||
/* the adisconnect structure is used to record a callback that
|
||||
|
|
|
@ -454,10 +454,8 @@ static void send_auth_publickey(atransport* t) {
|
|||
p->msg.command = A_AUTH;
|
||||
p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
|
||||
|
||||
p->payload = std::move(key);
|
||||
|
||||
// adbd expects a null-terminated string.
|
||||
p->payload.push_back('\0');
|
||||
p->payload.assign(key.data(), key.data() + key.size() + 1);
|
||||
p->msg.data_length = p->payload.size();
|
||||
send_packet(p, t);
|
||||
}
|
||||
|
@ -482,7 +480,7 @@ void send_auth_response(const char* token, size_t token_size, atransport* t) {
|
|||
|
||||
p->msg.command = A_AUTH;
|
||||
p->msg.arg0 = ADB_AUTH_SIGNATURE;
|
||||
p->payload = std::move(result);
|
||||
p->payload.assign(result.begin(), result.end());
|
||||
p->msg.data_length = p->payload.size();
|
||||
send_packet(p, t);
|
||||
}
|
||||
|
|
|
@ -459,7 +459,7 @@ static void jdwp_socket_close(asocket* s) {
|
|||
delete s;
|
||||
}
|
||||
|
||||
static int jdwp_socket_enqueue(asocket* s, std::string) {
|
||||
static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
|
||||
/* you can't write to this asocket */
|
||||
D("LS(%d): JDWP socket received data?", s->id);
|
||||
s->peer->close(s->peer);
|
||||
|
@ -474,7 +474,7 @@ static void jdwp_socket_ready(asocket* s) {
|
|||
* on the second one, close the connection
|
||||
*/
|
||||
if (!jdwp->pass) {
|
||||
std::string data;
|
||||
apacket::payload_type data;
|
||||
data.resize(s->get_max_payload());
|
||||
size_t len = jdwp_process_list(&data[0], data.size());
|
||||
data.resize(len);
|
||||
|
@ -521,7 +521,8 @@ static void jdwp_process_list_updated(void) {
|
|||
for (auto& t : _jdwp_trackers) {
|
||||
if (t->peer) {
|
||||
// The tracker might not have been connected yet.
|
||||
t->peer->enqueue(t->peer, data);
|
||||
apacket::payload_type payload(data.begin(), data.end());
|
||||
t->peer->enqueue(t->peer, std::move(payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +548,7 @@ static void jdwp_tracker_ready(asocket* s) {
|
|||
JdwpTracker* t = (JdwpTracker*)s;
|
||||
|
||||
if (t->need_initial) {
|
||||
std::string data;
|
||||
apacket::payload_type data;
|
||||
data.resize(s->get_max_payload());
|
||||
data.resize(jdwp_process_list_msg(&data[0], data.size()));
|
||||
t->need_initial = false;
|
||||
|
@ -555,7 +556,7 @@ static void jdwp_tracker_ready(asocket* s) {
|
|||
}
|
||||
}
|
||||
|
||||
static int jdwp_tracker_enqueue(asocket* s, std::string) {
|
||||
static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
|
||||
/* you can't write to this socket */
|
||||
D("LS(%d): JDWP tracker received data?", s->id);
|
||||
s->peer->close(s->peer);
|
||||
|
|
65
adb/range.h
65
adb/range.h
|
@ -1,65 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
struct Range {
|
||||
explicit Range(std::string data) : data_(std::move(data)) {}
|
||||
|
||||
Range(const Range& copy) = delete;
|
||||
Range& operator=(const Range& copy) = delete;
|
||||
|
||||
Range(Range&& move) = default;
|
||||
Range& operator=(Range&& move) = default;
|
||||
|
||||
bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return data_.size() - begin_offset_ - end_offset_;
|
||||
};
|
||||
|
||||
void drop_front(size_t n) {
|
||||
CHECK_GE(size(), n);
|
||||
begin_offset_ += n;
|
||||
}
|
||||
|
||||
void drop_end(size_t n) {
|
||||
CHECK_GE(size(), n);
|
||||
end_offset_ += n;
|
||||
}
|
||||
|
||||
char* data() {
|
||||
return &data_[0] + begin_offset_;
|
||||
}
|
||||
|
||||
std::string::iterator begin() {
|
||||
return data_.begin() + begin_offset_;
|
||||
}
|
||||
|
||||
std::string::iterator end() {
|
||||
return data_.end() - end_offset_;
|
||||
}
|
||||
|
||||
std::string data_;
|
||||
size_t begin_offset_ = 0;
|
||||
size_t end_offset_ = 0;
|
||||
};
|
|
@ -24,9 +24,8 @@
|
|||
#include <string>
|
||||
|
||||
#include "fdevent.h"
|
||||
#include "range.h"
|
||||
#include "types.h"
|
||||
|
||||
struct apacket;
|
||||
class atransport;
|
||||
|
||||
/* An asocket represents one half of a connection between a local and
|
||||
|
@ -73,7 +72,7 @@ struct asocket {
|
|||
* peer->ready() when we once again are ready to
|
||||
* receive data.
|
||||
*/
|
||||
int (*enqueue)(asocket* s, std::string data) = nullptr;
|
||||
int (*enqueue)(asocket* s, apacket::payload_type data) = nullptr;
|
||||
|
||||
/* ready is called by the peer when it is ready for
|
||||
* us to send data via enqueue again
|
||||
|
|
|
@ -118,7 +118,7 @@ static void CreateCloser(CloseWithPacketArg* arg) {
|
|||
// each write to give the underlying implementation time to flush.
|
||||
bool socket_filled = false;
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
std::string data;
|
||||
apacket::payload_type data;
|
||||
data.resize(MAX_PAYLOAD);
|
||||
arg->bytes_written += data.size();
|
||||
int ret = s->enqueue(s, std::move(data));
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
|
||||
#include "adb.h"
|
||||
#include "adb_io.h"
|
||||
#include "range.h"
|
||||
#include "transport.h"
|
||||
#include "types.h"
|
||||
|
||||
static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
|
||||
static unsigned local_socket_next_id = 1;
|
||||
|
@ -147,7 +147,7 @@ static SocketFlushResult local_socket_flush_incoming(asocket* s) {
|
|||
// Returns false if the socket has been closed and destroyed as a side-effect of this function.
|
||||
static bool local_socket_flush_outgoing(asocket* s) {
|
||||
const size_t max_payload = s->get_max_payload();
|
||||
std::string data;
|
||||
apacket::payload_type data;
|
||||
data.resize(max_payload);
|
||||
char* x = &data[0];
|
||||
size_t avail = max_payload;
|
||||
|
@ -214,7 +214,7 @@ static bool local_socket_flush_outgoing(asocket* s) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int local_socket_enqueue(asocket* s, std::string data) {
|
||||
static int local_socket_enqueue(asocket* s, apacket::payload_type data) {
|
||||
D("LS(%d): enqueue %zu", s->id, data.size());
|
||||
|
||||
Range r(std::move(data));
|
||||
|
@ -394,7 +394,7 @@ static asocket* create_host_service_socket(const char* name, const char* serial,
|
|||
}
|
||||
#endif /* ADB_HOST */
|
||||
|
||||
static int remote_socket_enqueue(asocket* s, std::string data) {
|
||||
static int remote_socket_enqueue(asocket* s, apacket::payload_type data) {
|
||||
D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
|
||||
apacket* p = get_apacket();
|
||||
|
||||
|
@ -476,8 +476,7 @@ void connect_to_remote(asocket* s, const char* destination) {
|
|||
p->msg.arg0 = s->id;
|
||||
|
||||
// adbd expects a null-terminated string.
|
||||
p->payload = destination;
|
||||
p->payload.push_back('\0');
|
||||
p->payload.assign(destination, destination + strlen(destination) + 1);
|
||||
p->msg.data_length = p->payload.size();
|
||||
|
||||
if (p->msg.data_length > s->get_max_payload()) {
|
||||
|
@ -612,7 +611,7 @@ char* skip_host_serial(char* service) {
|
|||
|
||||
#endif // ADB_HOST
|
||||
|
||||
static int smart_socket_enqueue(asocket* s, std::string data) {
|
||||
static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
|
||||
#if ADB_HOST
|
||||
char* service = nullptr;
|
||||
char* serial = nullptr;
|
||||
|
@ -623,7 +622,8 @@ static int smart_socket_enqueue(asocket* s, std::string data) {
|
|||
D("SS(%d): enqueue %zu", s->id, data.size());
|
||||
|
||||
if (s->smart_socket_data.empty()) {
|
||||
s->smart_socket_data = std::move(data);
|
||||
// TODO: Make this a BlockChain?
|
||||
s->smart_socket_data.assign(data.begin(), data.end());
|
||||
} else {
|
||||
std::copy(data.begin(), data.end(), std::back_inserter(s->smart_socket_data));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
// Layout of this struct must match struct WSABUF (verified via static assert in sysdeps_win32.cpp)
|
||||
struct adb_iovec {
|
||||
size_t iov_len;
|
||||
void* iov_base;
|
||||
};
|
||||
|
||||
ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt);
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/uio.h>
|
||||
using adb_iovec = struct iovec;
|
||||
#define adb_writev writev
|
||||
|
||||
#endif
|
||||
|
||||
#pragma GCC poison writev
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <android-base/errors.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/utf8.h>
|
||||
|
@ -43,6 +44,8 @@
|
|||
#include "adb.h"
|
||||
#include "adb_utils.h"
|
||||
|
||||
#include "sysdeps/uio.h"
|
||||
|
||||
extern void fatal(const char *fmt, ...);
|
||||
|
||||
/* forward declarations */
|
||||
|
@ -57,6 +60,7 @@ typedef struct FHClassRec_ {
|
|||
int (*_fh_lseek)(FH, int, int);
|
||||
int (*_fh_read)(FH, void*, int);
|
||||
int (*_fh_write)(FH, const void*, int);
|
||||
int (*_fh_writev)(FH, const adb_iovec*, int);
|
||||
} FHClassRec;
|
||||
|
||||
static void _fh_file_init(FH);
|
||||
|
@ -64,6 +68,7 @@ static int _fh_file_close(FH);
|
|||
static int _fh_file_lseek(FH, int, int);
|
||||
static int _fh_file_read(FH, void*, int);
|
||||
static int _fh_file_write(FH, const void*, int);
|
||||
static int _fh_file_writev(FH, const adb_iovec*, int);
|
||||
|
||||
static const FHClassRec _fh_file_class = {
|
||||
_fh_file_init,
|
||||
|
@ -71,6 +76,7 @@ static const FHClassRec _fh_file_class = {
|
|||
_fh_file_lseek,
|
||||
_fh_file_read,
|
||||
_fh_file_write,
|
||||
_fh_file_writev,
|
||||
};
|
||||
|
||||
static void _fh_socket_init(FH);
|
||||
|
@ -78,6 +84,7 @@ static int _fh_socket_close(FH);
|
|||
static int _fh_socket_lseek(FH, int, int);
|
||||
static int _fh_socket_read(FH, void*, int);
|
||||
static int _fh_socket_write(FH, const void*, int);
|
||||
static int _fh_socket_writev(FH, const adb_iovec*, int);
|
||||
|
||||
static const FHClassRec _fh_socket_class = {
|
||||
_fh_socket_init,
|
||||
|
@ -85,6 +92,7 @@ static const FHClassRec _fh_socket_class = {
|
|||
_fh_socket_lseek,
|
||||
_fh_socket_read,
|
||||
_fh_socket_write,
|
||||
_fh_socket_writev,
|
||||
};
|
||||
|
||||
#define assert(cond) \
|
||||
|
@ -248,57 +256,88 @@ typedef std::unique_ptr<struct FHRec_, fh_deleter> unique_fh;
|
|||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
static void _fh_file_init( FH f ) {
|
||||
static void _fh_file_init(FH f) {
|
||||
f->fh_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
static int _fh_file_close( FH f ) {
|
||||
CloseHandle( f->fh_handle );
|
||||
static int _fh_file_close(FH f) {
|
||||
CloseHandle(f->fh_handle);
|
||||
f->fh_handle = INVALID_HANDLE_VALUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _fh_file_read( FH f, void* buf, int len ) {
|
||||
DWORD read_bytes;
|
||||
static int _fh_file_read(FH f, void* buf, int len) {
|
||||
DWORD read_bytes;
|
||||
|
||||
if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
|
||||
D( "adb_read: could not read %d bytes from %s", len, f->name );
|
||||
if (!ReadFile(f->fh_handle, buf, (DWORD)len, &read_bytes, NULL)) {
|
||||
D("adb_read: could not read %d bytes from %s", len, f->name);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
} else if (read_bytes < (DWORD)len) {
|
||||
f->eof = 1;
|
||||
}
|
||||
return (int)read_bytes;
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
static int _fh_file_write( FH f, const void* buf, int len ) {
|
||||
DWORD wrote_bytes;
|
||||
static int _fh_file_write(FH f, const void* buf, int len) {
|
||||
DWORD wrote_bytes;
|
||||
|
||||
if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
|
||||
D( "adb_file_write: could not write %d bytes from %s", len, f->name );
|
||||
if (!WriteFile(f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL)) {
|
||||
D("adb_file_write: could not write %d bytes from %s", len, f->name);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
} else if (wrote_bytes < (DWORD)len) {
|
||||
f->eof = 1;
|
||||
}
|
||||
return (int)wrote_bytes;
|
||||
return wrote_bytes;
|
||||
}
|
||||
|
||||
static int _fh_file_lseek( FH f, int pos, int origin ) {
|
||||
DWORD method;
|
||||
DWORD result;
|
||||
static int _fh_file_writev(FH f, const adb_iovec* iov, int iovcnt) {
|
||||
if (iovcnt <= 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_SET: method = FILE_BEGIN; break;
|
||||
case SEEK_CUR: method = FILE_CURRENT; break;
|
||||
case SEEK_END: method = FILE_END; break;
|
||||
DWORD wrote_bytes = 0;
|
||||
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
ssize_t rc = _fh_file_write(f, iov[i].iov_base, iov[i].iov_len);
|
||||
if (rc == -1) {
|
||||
return wrote_bytes > 0 ? wrote_bytes : -1;
|
||||
} else if (rc == 0) {
|
||||
return wrote_bytes;
|
||||
}
|
||||
|
||||
wrote_bytes += rc;
|
||||
|
||||
if (static_cast<size_t>(rc) < iov[i].iov_len) {
|
||||
return wrote_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return wrote_bytes;
|
||||
}
|
||||
|
||||
static int _fh_file_lseek(FH f, int pos, int origin) {
|
||||
DWORD method;
|
||||
DWORD result;
|
||||
|
||||
switch (origin) {
|
||||
case SEEK_SET:
|
||||
method = FILE_BEGIN;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
method = FILE_CURRENT;
|
||||
break;
|
||||
case SEEK_END:
|
||||
method = FILE_END;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = SetFilePointer( f->fh_handle, pos, NULL, method );
|
||||
result = SetFilePointer(f->fh_handle, pos, NULL, method);
|
||||
if (result == INVALID_SET_FILE_POINTER) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
|
@ -308,7 +347,6 @@ static int _fh_file_lseek( FH f, int pos, int origin ) {
|
|||
return (int)result;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/***** *****/
|
||||
|
@ -317,12 +355,11 @@ static int _fh_file_lseek( FH f, int pos, int origin ) {
|
|||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
int adb_open(const char* path, int options)
|
||||
{
|
||||
FH f;
|
||||
int adb_open(const char* path, int options) {
|
||||
FH f;
|
||||
|
||||
DWORD desiredAccess = 0;
|
||||
DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
DWORD desiredAccess = 0;
|
||||
DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
switch (options) {
|
||||
case O_RDONLY:
|
||||
|
@ -340,8 +377,8 @@ int adb_open(const char* path, int options)
|
|||
return -1;
|
||||
}
|
||||
|
||||
f = _fh_alloc( &_fh_file_class );
|
||||
if ( !f ) {
|
||||
f = _fh_alloc(&_fh_file_class);
|
||||
if (!f) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -349,21 +386,21 @@ int adb_open(const char* path, int options)
|
|||
if (!android::base::UTF8ToWide(path, &path_wide)) {
|
||||
return -1;
|
||||
}
|
||||
f->fh_handle = CreateFileW( path_wide.c_str(), desiredAccess, shareMode,
|
||||
NULL, OPEN_EXISTING, 0, NULL );
|
||||
f->fh_handle =
|
||||
CreateFileW(path_wide.c_str(), desiredAccess, shareMode, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
|
||||
if (f->fh_handle == INVALID_HANDLE_VALUE) {
|
||||
const DWORD err = GetLastError();
|
||||
_fh_close(f);
|
||||
D( "adb_open: could not open '%s': ", path );
|
||||
D("adb_open: could not open '%s': ", path);
|
||||
switch (err) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
D( "file not found" );
|
||||
D("file not found");
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
D( "path not found" );
|
||||
D("path not found");
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
|
||||
|
@ -374,18 +411,17 @@ int adb_open(const char* path, int options)
|
|||
}
|
||||
}
|
||||
|
||||
snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
|
||||
D( "adb_open: '%s' => fd %d", path, _fh_to_int(f) );
|
||||
snprintf(f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path);
|
||||
D("adb_open: '%s' => fd %d", path, _fh_to_int(f));
|
||||
return _fh_to_int(f);
|
||||
}
|
||||
|
||||
/* ignore mode on Win32 */
|
||||
int adb_creat(const char* path, int mode)
|
||||
{
|
||||
FH f;
|
||||
int adb_creat(const char* path, int mode) {
|
||||
FH f;
|
||||
|
||||
f = _fh_alloc( &_fh_file_class );
|
||||
if ( !f ) {
|
||||
f = _fh_alloc(&_fh_file_class);
|
||||
if (!f) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -393,23 +429,21 @@ int adb_creat(const char* path, int mode)
|
|||
if (!android::base::UTF8ToWide(path, &path_wide)) {
|
||||
return -1;
|
||||
}
|
||||
f->fh_handle = CreateFileW( path_wide.c_str(), GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
f->fh_handle = CreateFileW(path_wide.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
|
||||
if (f->fh_handle == INVALID_HANDLE_VALUE) {
|
||||
const DWORD err = GetLastError();
|
||||
_fh_close(f);
|
||||
D( "adb_creat: could not open '%s': ", path );
|
||||
D("adb_creat: could not open '%s': ", path);
|
||||
switch (err) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
D( "file not found" );
|
||||
D("file not found");
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
D( "path not found" );
|
||||
D("path not found");
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
|
||||
|
@ -419,57 +453,64 @@ int adb_creat(const char* path, int mode)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
|
||||
D( "adb_creat: '%s' => fd %d", path, _fh_to_int(f) );
|
||||
snprintf(f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path);
|
||||
D("adb_creat: '%s' => fd %d", path, _fh_to_int(f));
|
||||
return _fh_to_int(f);
|
||||
}
|
||||
|
||||
|
||||
int adb_read(int fd, void* buf, int len)
|
||||
{
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
int adb_read(int fd, void* buf, int len) {
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
|
||||
if (f == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return f->clazz->_fh_read( f, buf, len );
|
||||
return f->clazz->_fh_read(f, buf, len);
|
||||
}
|
||||
|
||||
|
||||
int adb_write(int fd, const void* buf, int len)
|
||||
{
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
int adb_write(int fd, const void* buf, int len) {
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
|
||||
if (f == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return f->clazz->_fh_write(f, buf, len);
|
||||
}
|
||||
|
||||
ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt) {
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
|
||||
int adb_lseek(int fd, int pos, int where)
|
||||
{
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
if (f == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return f->clazz->_fh_writev(f, iov, iovcnt);
|
||||
}
|
||||
|
||||
int adb_lseek(int fd, int pos, int where) {
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
|
||||
if (!f) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return f->clazz->_fh_lseek(f, pos, where);
|
||||
}
|
||||
|
||||
|
||||
int adb_close(int fd)
|
||||
{
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
int adb_close(int fd) {
|
||||
FH f = _fh_from_int(fd, __func__);
|
||||
|
||||
if (!f) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
D( "adb_close: %s", f->name);
|
||||
D("adb_close: %s", f->name);
|
||||
_fh_close(f);
|
||||
return 0;
|
||||
}
|
||||
|
@ -582,7 +623,7 @@ static void _fh_socket_init(FH f) {
|
|||
f->fh_socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
static int _fh_socket_close( FH f ) {
|
||||
static int _fh_socket_close(FH f) {
|
||||
if (f->fh_socket != INVALID_SOCKET) {
|
||||
/* gently tell any peer that we're closing the socket */
|
||||
if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
|
||||
|
@ -603,13 +644,13 @@ static int _fh_socket_close( FH f ) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _fh_socket_lseek( FH f, int pos, int origin ) {
|
||||
static int _fh_socket_lseek(FH f, int pos, int origin) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _fh_socket_read(FH f, void* buf, int len) {
|
||||
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
|
||||
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
|
||||
if (result == SOCKET_ERROR) {
|
||||
const DWORD err = WSAGetLastError();
|
||||
// WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
|
||||
|
@ -621,11 +662,11 @@ static int _fh_socket_read(FH f, void* buf, int len) {
|
|||
_socket_set_errno(err);
|
||||
result = -1;
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int _fh_socket_write(FH f, const void* buf, int len) {
|
||||
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
|
||||
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
|
||||
if (result == SOCKET_ERROR) {
|
||||
const DWORD err = WSAGetLastError();
|
||||
// WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
|
||||
|
@ -639,13 +680,44 @@ static int _fh_socket_write(FH f, const void* buf, int len) {
|
|||
} else {
|
||||
// According to https://code.google.com/p/chromium/issues/detail?id=27870
|
||||
// Winsock Layered Service Providers may cause this.
|
||||
CHECK_LE(result, len) << "Tried to write " << len << " bytes to "
|
||||
<< f->name << ", but " << result
|
||||
<< " bytes reportedly written";
|
||||
CHECK_LE(result, len) << "Tried to write " << len << " bytes to " << f->name << ", but "
|
||||
<< result << " bytes reportedly written";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Make sure that adb_iovec is compatible with WSABUF.
|
||||
static_assert(sizeof(adb_iovec) == sizeof(WSABUF), "");
|
||||
static_assert(SIZEOF_MEMBER(adb_iovec, iov_len) == SIZEOF_MEMBER(WSABUF, len), "");
|
||||
static_assert(offsetof(adb_iovec, iov_len) == offsetof(WSABUF, len), "");
|
||||
|
||||
static_assert(SIZEOF_MEMBER(adb_iovec, iov_base) == SIZEOF_MEMBER(WSABUF, buf), "");
|
||||
static_assert(offsetof(adb_iovec, iov_base) == offsetof(WSABUF, buf), "");
|
||||
|
||||
static int _fh_socket_writev(FH f, const adb_iovec* iov, int iovcnt) {
|
||||
if (iovcnt <= 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WSABUF* wsabuf = reinterpret_cast<WSABUF*>(const_cast<adb_iovec*>(iov));
|
||||
DWORD bytes_written = 0;
|
||||
int result = WSASend(f->fh_socket, wsabuf, iovcnt, &bytes_written, 0, nullptr, nullptr);
|
||||
if (result == SOCKET_ERROR) {
|
||||
const DWORD err = WSAGetLastError();
|
||||
// WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
|
||||
// that to reduce spam and confusion.
|
||||
if (err != WSAEWOULDBLOCK) {
|
||||
D("send fd %d failed: %s", _fh_to_int(f),
|
||||
android::base::SystemErrorCodeToString(err).c_str());
|
||||
}
|
||||
_socket_set_errno(err);
|
||||
result = -1;
|
||||
}
|
||||
CHECK_GE(static_cast<DWORD>(std::numeric_limits<int>::max()), bytes_written);
|
||||
return static_cast<int>(bytes_written);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/***** *****/
|
||||
|
@ -654,23 +726,15 @@ static int _fh_socket_write(FH f, const void* buf, int len) {
|
|||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
static int _winsock_init;
|
||||
|
||||
static void
|
||||
_init_winsock( void )
|
||||
{
|
||||
// TODO: Multiple threads calling this may potentially cause multiple calls
|
||||
// to WSAStartup() which offers no real benefit.
|
||||
if (!_winsock_init) {
|
||||
WSADATA wsaData;
|
||||
int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
|
||||
static int _init_winsock(void) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, []() {
|
||||
WSADATA wsaData;
|
||||
int rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (rc != 0) {
|
||||
fatal("adb: could not initialize Winsock: %s",
|
||||
android::base::SystemErrorCodeToString(rc).c_str());
|
||||
}
|
||||
_winsock_init = 1;
|
||||
|
||||
// Note that we do not call atexit() to register WSACleanup to be called
|
||||
// at normal process termination because:
|
||||
|
@ -685,9 +749,12 @@ _init_winsock( void )
|
|||
// setupapi.dll which tries to load wintrust.dll which tries to load
|
||||
// crypt32.dll which calls atexit() which tries to acquire the C
|
||||
// Runtime lock that the other thread holds.
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _winsock_init = _init_winsock();
|
||||
|
||||
// Map a socket type to an explicit socket protocol instead of using the socket
|
||||
// protocol of 0. Explicit socket protocols are used by most apps and we should
|
||||
// do the same to reduce the chance of exercising uncommon code-paths that might
|
||||
|
@ -715,8 +782,6 @@ int network_loopback_client(int port, int type, std::string* error) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!_winsock_init) _init_winsock();
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
@ -765,8 +830,6 @@ static int _network_server(int port, int type, u_long interface_address, std::st
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!_winsock_init) _init_winsock();
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
@ -843,8 +906,6 @@ int network_connect(const std::string& host, int port, int type, int timeout, st
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!_winsock_init) _init_winsock();
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
@ -912,52 +973,49 @@ int network_connect(const std::string& host, int port, int type, int timeout, st
|
|||
return fd;
|
||||
}
|
||||
|
||||
int adb_register_socket(SOCKET s) {
|
||||
FH f = _fh_alloc( &_fh_socket_class );
|
||||
int adb_register_socket(SOCKET s) {
|
||||
FH f = _fh_alloc(&_fh_socket_class);
|
||||
f->fh_socket = s;
|
||||
return _fh_to_int(f);
|
||||
}
|
||||
|
||||
#undef accept
|
||||
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
|
||||
{
|
||||
FH serverfh = _fh_from_int(serverfd, __func__);
|
||||
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t* addrlen) {
|
||||
FH serverfh = _fh_from_int(serverfd, __func__);
|
||||
|
||||
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
|
||||
if (!serverfh || serverfh->clazz != &_fh_socket_class) {
|
||||
D("adb_socket_accept: invalid fd %d", serverfd);
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unique_fh fh(_fh_alloc( &_fh_socket_class ));
|
||||
unique_fh fh(_fh_alloc(&_fh_socket_class));
|
||||
if (!fh) {
|
||||
PLOG(ERROR) << "adb_socket_accept: failed to allocate accepted socket "
|
||||
"descriptor";
|
||||
return -1;
|
||||
}
|
||||
|
||||
fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
|
||||
fh->fh_socket = accept(serverfh->fh_socket, addr, addrlen);
|
||||
if (fh->fh_socket == INVALID_SOCKET) {
|
||||
const DWORD err = WSAGetLastError();
|
||||
LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd <<
|
||||
" failed: " + android::base::SystemErrorCodeToString(err);
|
||||
_socket_set_errno( err );
|
||||
LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd
|
||||
<< " failed: " + android::base::SystemErrorCodeToString(err);
|
||||
_socket_set_errno(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int fd = _fh_to_int(fh.get());
|
||||
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name );
|
||||
D( "adb_socket_accept on fd %d returns fd %d", serverfd, fd );
|
||||
snprintf(fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name);
|
||||
D("adb_socket_accept on fd %d returns fd %d", serverfd, fd);
|
||||
fh.release();
|
||||
return fd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) {
|
||||
FH fh = _fh_from_int(fd, __func__);
|
||||
|
||||
int adb_setsockopt( int fd, int level, int optname, const void* optval, socklen_t optlen )
|
||||
{
|
||||
FH fh = _fh_from_int(fd, __func__);
|
||||
|
||||
if ( !fh || fh->clazz != &_fh_socket_class ) {
|
||||
if (!fh || fh->clazz != &_fh_socket_class) {
|
||||
D("adb_setsockopt: invalid fd %d", fd);
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -967,13 +1025,13 @@ int adb_setsockopt( int fd, int level, int optname, const void* optval, soc
|
|||
// to set SOL_SOCKET, SO_SNDBUF/SO_RCVBUF, ignore it since the OS has
|
||||
// auto-tuning.
|
||||
|
||||
int result = setsockopt( fh->fh_socket, level, optname,
|
||||
reinterpret_cast<const char*>(optval), optlen );
|
||||
if ( result == SOCKET_ERROR ) {
|
||||
int result =
|
||||
setsockopt(fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen);
|
||||
if (result == SOCKET_ERROR) {
|
||||
const DWORD err = WSAGetLastError();
|
||||
D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n",
|
||||
fd, level, optname, android::base::SystemErrorCodeToString(err).c_str());
|
||||
_socket_set_errno( err );
|
||||
D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n", fd, level,
|
||||
optname, android::base::SystemErrorCodeToString(err).c_str());
|
||||
_socket_set_errno(err);
|
||||
result = -1;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -335,7 +335,7 @@ static void device_tracker_close(asocket* socket) {
|
|||
delete tracker;
|
||||
}
|
||||
|
||||
static int device_tracker_enqueue(asocket* socket, std::string) {
|
||||
static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
|
||||
/* you can't read from a device tracker, close immediately */
|
||||
device_tracker_close(socket);
|
||||
return -1;
|
||||
|
@ -344,7 +344,7 @@ static int device_tracker_enqueue(asocket* socket, std::string) {
|
|||
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
|
||||
asocket* peer = tracker->socket.peer;
|
||||
|
||||
std::string data;
|
||||
apacket::payload_type data;
|
||||
data.resize(4 + string.size());
|
||||
char buf[5];
|
||||
snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "sysdeps/memory.h"
|
||||
|
||||
// Essentially std::vector<char>, except without zero initialization or reallocation.
|
||||
struct Block {
|
||||
using iterator = char*;
|
||||
|
||||
Block() {}
|
||||
|
||||
explicit Block(size_t size) { allocate(size); }
|
||||
|
||||
template <typename Iterator>
|
||||
Block(Iterator begin, Iterator end) : Block(end - begin) {
|
||||
std::copy(begin, end, data_);
|
||||
}
|
||||
|
||||
Block(const Block& copy) = delete;
|
||||
Block(Block&& move) {
|
||||
std::swap(data_, move.data_);
|
||||
std::swap(capacity_, move.capacity_);
|
||||
std::swap(size_, move.size_);
|
||||
}
|
||||
|
||||
Block& operator=(const Block& copy) = delete;
|
||||
Block& operator=(Block&& move) {
|
||||
clear();
|
||||
|
||||
std::swap(data_, move.data_);
|
||||
std::swap(capacity_, move.capacity_);
|
||||
std::swap(size_, move.size_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Block() { clear(); }
|
||||
|
||||
void resize(size_t new_size) {
|
||||
if (!data_) {
|
||||
allocate(new_size);
|
||||
} else {
|
||||
CHECK_GE(capacity_, new_size);
|
||||
size_ = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputIt>
|
||||
void assign(InputIt begin, InputIt end) {
|
||||
clear();
|
||||
allocate(end - begin);
|
||||
std::copy(begin, end, data_);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
free(data_);
|
||||
capacity_ = 0;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
size_t capacity() const { return capacity_; }
|
||||
size_t size() const { return size_; }
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
char* data() { return data_; }
|
||||
const char* data() const { return data_; }
|
||||
|
||||
char* begin() { return data_; }
|
||||
const char* begin() const { return data_; }
|
||||
|
||||
char* end() { return data() + size_; }
|
||||
const char* end() const { return data() + size_; }
|
||||
|
||||
char& operator[](size_t idx) { return data()[idx]; }
|
||||
const char& operator[](size_t idx) const { return data()[idx]; }
|
||||
|
||||
bool operator==(const Block& rhs) const {
|
||||
return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void allocate(size_t size) {
|
||||
CHECK(data_ == nullptr);
|
||||
CHECK_EQ(0ULL, capacity_);
|
||||
CHECK_EQ(0ULL, size_);
|
||||
if (size != 0) {
|
||||
data_ = static_cast<char*>(malloc(size));
|
||||
capacity_ = size;
|
||||
size_ = size;
|
||||
}
|
||||
}
|
||||
|
||||
char* data_ = nullptr;
|
||||
size_t capacity_ = 0;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
struct amessage {
|
||||
uint32_t command; /* command identifier constant */
|
||||
uint32_t arg0; /* first argument */
|
||||
uint32_t arg1; /* second argument */
|
||||
uint32_t data_length; /* length of payload (0 is allowed) */
|
||||
uint32_t data_check; /* checksum of data payload */
|
||||
uint32_t magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
struct apacket {
|
||||
using payload_type = Block;
|
||||
amessage msg;
|
||||
payload_type payload;
|
||||
};
|
||||
|
||||
struct Range {
|
||||
explicit Range(apacket::payload_type data) : data_(std::move(data)) {}
|
||||
|
||||
Range(const Range& copy) = delete;
|
||||
Range& operator=(const Range& copy) = delete;
|
||||
|
||||
Range(Range&& move) = default;
|
||||
Range& operator=(Range&& move) = default;
|
||||
|
||||
size_t size() const { return data_.size() - begin_offset_ - end_offset_; };
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
void drop_front(size_t n) {
|
||||
CHECK_GE(size(), n);
|
||||
begin_offset_ += n;
|
||||
}
|
||||
|
||||
void drop_end(size_t n) {
|
||||
CHECK_GE(size(), n);
|
||||
end_offset_ += n;
|
||||
}
|
||||
|
||||
char* data() { return &data_[0] + begin_offset_; }
|
||||
|
||||
apacket::payload_type::iterator begin() { return data_.begin() + begin_offset_; }
|
||||
apacket::payload_type::iterator end() { return data_.end() - end_offset_; }
|
||||
|
||||
apacket::payload_type data_;
|
||||
size_t begin_offset_ = 0;
|
||||
size_t end_offset_ = 0;
|
||||
};
|
Loading…
Reference in New Issue