diff options
author | Josh Gao <jmgao@google.com> | 2016-05-13 15:28:34 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2016-06-02 15:38:16 -0700 |
commit | d038fee6bdf08bf5fe72571d02fad3caf7216f4d (patch) | |
tree | 95f234c04dc0de2824c7aa8b0ce594bb3c91e531 /jdwp_service.cpp | |
parent | 980ec2e76be0f647c930c7a420a1da719dd1c9ee (diff) | |
download | adb-d038fee6bdf08bf5fe72571d02fad3caf7216f4d.tar.gz |
adb: refactor jdwp_service.cpp.
Refactor jdwp_service.cpp to be more idiomatic C++.
Bug: http://b/28347842
Change-Id: I8c463069fe489819cb7c248f4aff2689877bfe45
Diffstat (limited to 'jdwp_service.cpp')
-rw-r--r-- | jdwp_service.cpp | 693 |
1 files changed, 287 insertions, 406 deletions
diff --git a/jdwp_service.cpp b/jdwp_service.cpp index 3c812cc..7a44801 100644 --- a/jdwp_service.cpp +++ b/jdwp_service.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -/* implement the "debug-ports" and "track-debug-ports" device services */ +#if !ADB_HOST #define TRACE_TAG JDWP @@ -24,22 +24,29 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/socket.h> +#include <sys/un.h> #include <unistd.h> +#include <list> +#include <memory> +#include <vector> + #include "adb.h" +#include "adb_io.h" #include "adb_utils.h" /* here's how these things work. when adbd starts, it creates a unix server socket - named @vm-debug-control (@ is a shortcut for "first byte is zero" + named @jdwp-control (@ is a shortcut for "first byte is zero" to use the private namespace instead of the file system) when a new JDWP daemon thread starts in a new VM process, it creates - a connection to @vm-debug-control to announce its availability. + a connection to @jdwp-control to announce its availability. - JDWP thread @vm-debug-control + JDWP thread @jdwp-control | | |-------------------------------> | | hello I'm in process <pid> | @@ -72,7 +79,7 @@ to the JDWP process with the help of sendmsg() - JDWP thread @vm-debug-control + JDWP thread @jdwp-control | | | <----------------------| | OK, try this file descriptor | @@ -116,249 +123,191 @@ ** for each JDWP process, we record its pid and its connected socket **/ -#define MAX_OUT_FDS 4 +// PIDs are transmitted as 4 hex digits in ascii. +static constexpr size_t PID_LEN = 4; -#if !ADB_HOST +static void jdwp_process_event(int socket, unsigned events, void* _proc); +static void jdwp_process_list_updated(void); -#include <sys/socket.h> -#include <sys/un.h> +struct JdwpProcess; +static std::list<std::unique_ptr<JdwpProcess>> _jdwp_list; struct JdwpProcess { - JdwpProcess* next; - JdwpProcess* prev; - int pid; - int socket; - fdevent* fde; + explicit JdwpProcess(int socket) { + this->socket = socket; + this->fde = fdevent_create(socket, jdwp_process_event, this); - char in_buff[4]; /* input character to read PID */ - int in_len; /* number from JDWP process */ - - int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */ - int out_count; /* to send to the JDWP process */ -}; - -static JdwpProcess _jdwp_list; - -static int -jdwp_process_list( char* buffer, int bufferlen ) -{ - char* end = buffer + bufferlen; - char* p = buffer; - JdwpProcess* proc = _jdwp_list.next; + if (!this->fde) { + fatal("could not create fdevent for new JDWP process"); + } - for ( ; proc != &_jdwp_list; proc = proc->next ) { - int len; + this->fde->state |= FDE_DONT_CLOSE; - /* skip transient connections */ - if (proc->pid < 0) - continue; - - len = snprintf(p, end-p, "%d\n", proc->pid); - if (p + len >= end) - break; - p += len; + /* start by waiting for the PID */ + fdevent_add(this->fde, FDE_READ); } - p[0] = 0; - return (p - buffer); -} - - -static int -jdwp_process_list_msg( char* buffer, int bufferlen ) -{ - char head[5]; - int len = jdwp_process_list( buffer+4, bufferlen-4 ); - snprintf(head, sizeof head, "%04x", len); - memcpy(buffer, head, 4); - return len + 4; -} - -static void jdwp_process_list_updated(void); - -static void -jdwp_process_free( JdwpProcess* proc ) -{ - if (proc) { - int n; - - proc->prev->next = proc->next; - proc->next->prev = proc->prev; - - if (proc->socket >= 0) { - adb_shutdown(proc->socket); - adb_close(proc->socket); - proc->socket = -1; + ~JdwpProcess() { + if (this->socket >= 0) { + adb_shutdown(this->socket); + adb_close(this->socket); + this->socket = -1; } - if (proc->fde != NULL) { - fdevent_destroy(proc->fde); - proc->fde = NULL; + if (this->fde) { + fdevent_destroy(this->fde); + this->fde = nullptr; } - proc->pid = -1; - for (n = 0; n < proc->out_count; n++) { - adb_close(proc->out_fds[n]); - } - proc->out_count = 0; + out_fds.clear(); + } - free(proc); + void RemoveFromList() { + if (this->pid >= 0) { + D("removing pid %d from jdwp process list", this->pid); + } else { + D("removing transient JdwpProcess from list"); + } - jdwp_process_list_updated(); + auto pred = [this](const auto& proc) { return proc.get() == this; }; + _jdwp_list.remove_if(pred); } -} + int pid = -1; + int socket = -1; + fdevent* fde = nullptr; -static void jdwp_process_event(int, unsigned, void*); /* forward */ + std::vector<unique_fd> out_fds; + char in_buf[PID_LEN + 1]; + ssize_t in_len = 0; +}; +static size_t jdwp_process_list(char* buffer, size_t bufferlen) { + std::string temp; -static JdwpProcess* -jdwp_process_alloc( int socket ) -{ - JdwpProcess* proc = reinterpret_cast<JdwpProcess*>( - calloc(1, sizeof(*proc))); + for (auto& proc : _jdwp_list) { + /* skip transient connections */ + if (proc->pid < 0) { + continue; + } - if (proc == NULL) { - D("not enough memory to create new JDWP process"); - return NULL; + std::string next = std::to_string(proc->pid) + "\n"; + if (temp.length() + next.length() > bufferlen) { + D("truncating JDWP process list (max len = %zu)", bufferlen); + break; + } + temp.append(next); } - proc->socket = socket; - proc->pid = -1; - proc->next = proc; - proc->prev = proc; + memcpy(buffer, temp.data(), temp.length()); + return temp.length(); +} - proc->fde = fdevent_create( socket, jdwp_process_event, proc ); - if (proc->fde == NULL) { - D("could not create fdevent for new JDWP process" ); - free(proc); - return NULL; +static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) { + // Message is length-prefixed with 4 hex digits in ASCII. + static constexpr size_t header_len = 4; + if (bufferlen < header_len) { + fatal("invalid JDWP process list buffer size: %zu", bufferlen); } - proc->fde->state |= FDE_DONT_CLOSE; - proc->in_len = 0; - proc->out_count = 0; - - /* append to list */ - proc->next = &_jdwp_list; - proc->prev = proc->next->prev; - - proc->prev->next = proc; - proc->next->prev = proc; - - /* start by waiting for the PID */ - fdevent_add(proc->fde, FDE_READ); - - return proc; + char head[header_len + 1]; + size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len); + snprintf(head, sizeof head, "%04zx", len); + memcpy(buffer, head, header_len); + return len + header_len; } - -static void -jdwp_process_event( int socket, unsigned events, void* _proc ) -{ - JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc); +static void jdwp_process_event(int socket, unsigned events, void* _proc) { + JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc); if (events & FDE_READ) { if (proc->pid < 0) { /* read the PID as a 4-hexchar string */ - char* p = proc->in_buff + proc->in_len; - int size = 4 - proc->in_len; - char temp[5]; - while (size > 0) { - int len = recv( socket, p, size, 0 ); - if (len < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - return; - /* this can fail here if the JDWP process crashes very fast */ - D("weird unknown JDWP process failure: %s", - strerror(errno)); + if (proc->in_len < 0) { + fatal("attempting to read JDWP pid again?"); + } - goto CloseProcess; - } - if (len == 0) { /* end of stream ? */ - D("weird end-of-stream from unknown JDWP process"); - goto CloseProcess; + char* p = proc->in_buf + proc->in_len; + size_t size = PID_LEN - proc->in_len; + + ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, p, size, 0)); + if (rc < 0) { + if (errno == EAGAIN) { + return; } - p += len; - proc->in_len += len; - size -= len; + + D("failed to read jdwp pid: %s", strerror(errno)); + goto CloseProcess; + } + + proc->in_len += rc; + if (proc->in_len != PID_LEN) { + return; } - /* we have read 4 characters, now decode the pid */ - memcpy(temp, proc->in_buff, 4); - temp[4] = 0; - if (sscanf( temp, "%04x", &proc->pid ) != 1) { - D("could not decode JDWP %p PID number: '%s'", proc, temp); + proc->in_buf[PID_LEN] = '\0'; + proc->in_len = -1; + + if (sscanf(proc->in_buf, "%04x", &proc->pid) != 1) { + D("could not decode JDWP %p PID number: '%s'", proc, p); goto CloseProcess; } /* all is well, keep reading to detect connection closure */ D("Adding pid %d to jdwp process list", proc->pid); jdwp_process_list_updated(); - } - else - { + } else { /* the pid was read, if we get there it's probably because the connection * was closed (e.g. the JDWP process exited or crashed) */ - char buf[32]; + char buf[32]; - for (;;) { - int len = recv(socket, buf, sizeof(buf), 0); + while (true) { + int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0)); - if (len <= 0) { - if (len < 0 && errno == EINTR) - continue; - if (len < 0 && errno == EAGAIN) + if (len == 0) { + D("terminating JDWP %d connection: EOF", proc->pid); + break; + } else if (len < 0) { + if (len < 0 && errno == EAGAIN) { return; - else { - D("terminating JDWP %d connection: %s", proc->pid, - strerror(errno)); - break; } - } - else { - D( "ignoring unexpected JDWP %d control socket activity (%d bytes)", - proc->pid, len ); + + D("terminating JDWP %d connection: EOF", proc->pid); + break; + } else { + D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid, + len); } } - CloseProcess: - if (proc->pid >= 0) { - D( "remove pid %d to jdwp process list", proc->pid ); - } - jdwp_process_free(proc); - return; + goto CloseProcess; } } if (events & FDE_WRITE) { - D("trying to write to JDWP pid controli (count=%d first=%d) %d", - proc->pid, proc->out_count, proc->out_fds[0]); - if (proc->out_count > 0) { - int fd = proc->out_fds[0]; - int n, ret; - struct cmsghdr* cmsg; - struct msghdr msg; - struct iovec iov; - char dummy = '!'; - char buffer[sizeof(struct cmsghdr) + sizeof(int)]; - - iov.iov_base = &dummy; - iov.iov_len = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - msg.msg_control = buffer; + D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size()); + if (!proc->out_fds.empty()) { + int fd = proc->out_fds.back().get(); + struct cmsghdr* cmsg; + struct msghdr msg; + struct iovec iov; + char dummy = '!'; + char buffer[sizeof(struct cmsghdr) + sizeof(int)]; + + iov.iov_base = &dummy; + iov.iov_len = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + msg.msg_control = buffer; msg.msg_controllen = sizeof(buffer); cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = msg.msg_controllen; + cmsg->cmsg_len = msg.msg_controllen; cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_type = SCM_RIGHTS; ((int*)CMSG_DATA(cmsg))[0] = fd; if (!set_file_block_mode(proc->socket, true)) { @@ -366,74 +315,59 @@ jdwp_process_event( int socket, unsigned events, void* _proc ) goto CloseProcess; } - for (;;) { - ret = sendmsg(proc->socket, &msg, 0); - if (ret >= 0) { - adb_close(fd); - break; - } - if (errno == EINTR) - continue; - D("sending new file descriptor to JDWP %d failed: %s", - proc->pid, strerror(errno)); + int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0)); + if (ret < 0) { + D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno)); goto CloseProcess; } - D("sent file descriptor %d to JDWP process %d", - fd, proc->pid); + adb_close(fd); - for (n = 1; n < proc->out_count; n++) - proc->out_fds[n-1] = proc->out_fds[n]; + D("sent file descriptor %d to JDWP process %d", fd, proc->pid); + + proc->out_fds.pop_back(); if (!set_file_block_mode(proc->socket, false)) { VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket; goto CloseProcess; } - if (--proc->out_count == 0) - fdevent_del( proc->fde, FDE_WRITE ); + if (proc->out_fds.empty()) { + fdevent_del(proc->fde, FDE_WRITE); + } } } -} + return; -int -create_jdwp_connection_fd(int pid) -{ - JdwpProcess* proc = _jdwp_list.next; +CloseProcess: + proc->RemoveFromList(); + jdwp_process_list_updated(); +} +int create_jdwp_connection_fd(int pid) { D("looking for pid %d in JDWP process list", pid); - for ( ; proc != &_jdwp_list; proc = proc->next ) { + + for (auto& proc : _jdwp_list) { if (proc->pid == pid) { - goto FoundIt; - } - } - D("search failed !!"); - return -1; + int fds[2]; -FoundIt: - { - int fds[2]; + if (adb_socketpair(fds) < 0) { + D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno)); + return -1; + } + D("socketpair: (%d,%d)", fds[0], fds[1]); - if (proc->out_count >= MAX_OUT_FDS) { - D("%s: too many pending JDWP connection for pid %d", - __FUNCTION__, pid); - return -1; - } + proc->out_fds.emplace_back(fds[1]); + if (proc->out_fds.size() == 1) { + fdevent_add(proc->fde, FDE_WRITE); + } - if (adb_socketpair(fds) < 0) { - D("%s: socket pair creation failed: %s", - __FUNCTION__, strerror(errno)); - return -1; + return fds[0]; } - D("socketpair: (%d,%d)", fds[0], fds[1]); - - proc->out_fds[ proc->out_count ] = fds[1]; - if (++proc->out_count == 1) - fdevent_add( proc->fde, FDE_WRITE ); - - return fds[0]; } + D("search failed !!"); + return -1; } /** VM DEBUG CONTROL SOCKET @@ -442,33 +376,27 @@ FoundIt: **/ /* name of the debug control Unix socket */ -#define JDWP_CONTROL_NAME "\0jdwp-control" -#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME)-1) +#define JDWP_CONTROL_NAME "\0jdwp-control" +#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1) struct JdwpControl { - int listen_socket; - fdevent* fde; + int listen_socket; + fdevent* fde; }; +static JdwpControl _jdwp_control; -static void -jdwp_control_event(int s, unsigned events, void* user); +static void jdwp_control_event(int s, unsigned events, void* user); - -static int -jdwp_control_init( JdwpControl* control, - const char* sockname, - int socknamelen ) -{ - sockaddr_un addr; - socklen_t addrlen; - int s; - int maxpath = sizeof(addr.sun_path); - int pathlen = socknamelen; +static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) { + sockaddr_un addr; + socklen_t addrlen; + int s; + int maxpath = sizeof(addr.sun_path); + int pathlen = socknamelen; if (pathlen >= maxpath) { - D( "vm debug control socket name too long (%d extra chars)", - pathlen+1-maxpath ); + D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath); return -1; } @@ -476,25 +404,22 @@ jdwp_control_init( JdwpControl* control, addr.sun_family = AF_UNIX; memcpy(addr.sun_path, sockname, socknamelen); - s = socket( AF_UNIX, SOCK_STREAM, 0 ); + s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) { - D( "could not create vm debug control socket. %d: %s", - errno, strerror(errno)); + D("could not create vm debug control socket. %d: %s", errno, strerror(errno)); return -1; } - addrlen = (pathlen + sizeof(addr.sun_family)); + addrlen = pathlen + sizeof(addr.sun_family); if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) { - D( "could not bind vm debug control socket: %d: %s", - errno, strerror(errno) ); + D("could not bind vm debug control socket: %d: %s", errno, strerror(errno)); adb_close(s); return -1; } - if ( listen(s, 4) < 0 ) { - D("listen failed in jdwp control socket: %d: %s", - errno, strerror(errno)); + if (listen(s, 4) < 0) { + D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno)); adb_close(s); return -1; } @@ -503,128 +428,109 @@ jdwp_control_init( JdwpControl* control, control->fde = fdevent_create(s, jdwp_control_event, control); if (control->fde == NULL) { - D( "could not create fdevent for jdwp control socket" ); + D("could not create fdevent for jdwp control socket"); adb_close(s); return -1; } /* only wait for incoming connections */ fdevent_add(control->fde, FDE_READ); - close_on_exec(s); D("jdwp control socket started (%d)", control->listen_socket); return 0; } - -static void -jdwp_control_event( int s, unsigned events, void* _control ) -{ - JdwpControl* control = (JdwpControl*) _control; +static void jdwp_control_event(int s, unsigned events, void* _control) { + JdwpControl* control = (JdwpControl*)_control; if (events & FDE_READ) { - sockaddr_storage ss; - sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss); - socklen_t addrlen = sizeof(ss); - int s = -1; - JdwpProcess* proc; - - do { - s = adb_socket_accept(control->listen_socket, addrp, &addrlen); - if (s < 0) { - if (errno == EINTR) - continue; - if (errno == ECONNABORTED) { - /* oops, the JDWP process died really quick */ - D("oops, the JDWP process died really quick"); - return; - } + sockaddr_storage ss; + sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss); + socklen_t addrlen = sizeof(ss); + int s = adb_socket_accept(control->listen_socket, addrp, &addrlen); + if (s < 0) { + if (errno == ECONNABORTED) { + /* oops, the JDWP process died really quick */ + D("oops, the JDWP process died really quick"); + return; + } else { /* the socket is probably closed ? */ - D( "weird accept() failed on jdwp control socket: %s", - strerror(errno) ); + D("weird accept() failed on jdwp control socket: %s", strerror(errno)); return; } } - while (s < 0); - proc = jdwp_process_alloc( s ); - if (proc == NULL) - return; + auto proc = std::make_unique<JdwpProcess>(s); + if (!proc) { + fatal("failed to allocate JdwpProcess"); + } + + _jdwp_list.emplace_back(std::move(proc)); } } - -static JdwpControl _jdwp_control; - /** "jdwp" local service implementation ** this simply returns the list of known JDWP process pids **/ -struct JdwpSocket { - asocket socket; - int pass; +struct JdwpSocket : public asocket { + bool pass; }; -static void -jdwp_socket_close( asocket* s ) -{ - asocket* peer = s->peer; +static void jdwp_socket_close(asocket* s) { + D("LS(%d): closing jdwp socket", s->id); - remove_socket(s); - - if (peer) { - peer->peer = NULL; - peer->close(peer); + if (s->peer) { + D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); + s->peer->peer = nullptr; + s->peer->close(s->peer); + s->peer = nullptr; } + + remove_socket(s); free(s); } -static int -jdwp_socket_enqueue( asocket* s, apacket* p ) -{ +static int jdwp_socket_enqueue(asocket* s, apacket* p) { /* you can't write to this asocket */ + D("LS(%d): JDWP socket received data?", s->id); put_apacket(p); s->peer->close(s->peer); return -1; } +static void jdwp_socket_ready(asocket* s) { + JdwpSocket* jdwp = (JdwpSocket*)s; + asocket* peer = jdwp->peer; -static void -jdwp_socket_ready( asocket* s ) -{ - JdwpSocket* jdwp = (JdwpSocket*)s; - asocket* peer = jdwp->socket.peer; - - /* on the first call, send the list of pids, - * on the second one, close the connection - */ - if (jdwp->pass == 0) { - apacket* p = get_apacket(); + /* on the first call, send the list of pids, + * on the second one, close the connection + */ + if (!jdwp->pass) { + apacket* p = get_apacket(); p->len = jdwp_process_list((char*)p->data, s->get_max_payload()); peer->enqueue(peer, p); - jdwp->pass = 1; - } - else { + jdwp->pass = true; + } else { peer->close(peer); } } -asocket* -create_jdwp_service_socket( void ) -{ +asocket* create_jdwp_service_socket(void) { JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1)); - if (s == NULL) - return NULL; + if (!s) { + fatal("failed to allocate JdwpSocket"); + } - install_local_socket(&s->socket); + install_local_socket(s); - s->socket.ready = jdwp_socket_ready; - s->socket.enqueue = jdwp_socket_enqueue; - s->socket.close = jdwp_socket_close; - s->pass = 0; + s->ready = jdwp_socket_ready; + s->enqueue = jdwp_socket_enqueue; + s->close = jdwp_socket_close; + s->pass = false; - return &s->socket; + return s; } /** "track-jdwp" local service implementation @@ -632,113 +538,88 @@ create_jdwp_service_socket( void ) ** to the client... **/ -struct JdwpTracker { - asocket socket; - JdwpTracker* next; - JdwpTracker* prev; - int need_update; +struct JdwpTracker : public asocket { + bool need_initial; }; -static JdwpTracker _jdwp_trackers_list; - +static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers; -static void -jdwp_process_list_updated(void) -{ - char buffer[1024]; - int len; - JdwpTracker* t = _jdwp_trackers_list.next; +static void jdwp_process_list_updated(void) { + char buffer[1024]; + int len = jdwp_process_list_msg(buffer, sizeof(buffer)); - len = jdwp_process_list_msg(buffer, sizeof(buffer)); - - for ( ; t != &_jdwp_trackers_list; t = t->next ) { - apacket* p = get_apacket(); - asocket* peer = t->socket.peer; + for (auto& t : _jdwp_trackers) { + apacket* p = get_apacket(); memcpy(p->data, buffer, len); p->len = len; - peer->enqueue( peer, p ); + + if (t->peer) { + // The tracker might not have been connected yet. + t->peer->enqueue(t->peer, p); + } } } -static void -jdwp_tracker_close( asocket* s ) -{ - JdwpTracker* tracker = (JdwpTracker*) s; - asocket* peer = s->peer; +static void jdwp_tracker_close(asocket* s) { + D("LS(%d): destroying jdwp tracker service", s->id); - if (peer) { - peer->peer = NULL; - peer->close(peer); + if (s->peer) { + D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); + s->peer->peer = nullptr; + s->peer->close(s->peer); + s->peer = nullptr; } remove_socket(s); - tracker->prev->next = tracker->next; - tracker->next->prev = tracker->prev; - - free(s); + auto pred = [s](const auto& tracker) { return tracker.get() == s; }; + std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred); } -static void -jdwp_tracker_ready( asocket* s ) -{ - JdwpTracker* t = (JdwpTracker*) s; +static void jdwp_tracker_ready(asocket* s) { + JdwpTracker* t = (JdwpTracker*)s; - if (t->need_update) { - apacket* p = get_apacket(); - t->need_update = 0; + if (t->need_initial) { + apacket* p = get_apacket(); + t->need_initial = false; p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload()); s->peer->enqueue(s->peer, p); } } -static int -jdwp_tracker_enqueue( asocket* s, apacket* p ) -{ +static int jdwp_tracker_enqueue(asocket* s, apacket* p) { /* you can't write to this socket */ + D("LS(%d): JDWP tracker received data?", s->id); put_apacket(p); s->peer->close(s->peer); return -1; } +asocket* create_jdwp_tracker_service_socket(void) { + auto t = std::make_unique<JdwpTracker>(); + if (!t) { + fatal("failed to allocate JdwpTracker"); + } -asocket* -create_jdwp_tracker_service_socket( void ) -{ - JdwpTracker* t = reinterpret_cast<JdwpTracker*>(calloc(sizeof(*t), 1)); - - if (t == NULL) - return NULL; + memset(t.get(), 0, sizeof(asocket)); - t->next = &_jdwp_trackers_list; - t->prev = t->next->prev; + install_local_socket(t.get()); + D("LS(%d): created new jdwp tracker service", t->id); - t->next->prev = t; - t->prev->next = t; + t->ready = jdwp_tracker_ready; + t->enqueue = jdwp_tracker_enqueue; + t->close = jdwp_tracker_close; + t->need_initial = true; - install_local_socket(&t->socket); + asocket* result = t.get(); - t->socket.ready = jdwp_tracker_ready; - t->socket.enqueue = jdwp_tracker_enqueue; - t->socket.close = jdwp_tracker_close; - t->need_update = 1; + _jdwp_trackers.emplace_back(std::move(t)); - return &t->socket; + return result; } - -int -init_jdwp(void) -{ - _jdwp_list.next = &_jdwp_list; - _jdwp_list.prev = &_jdwp_list; - - _jdwp_trackers_list.next = &_jdwp_trackers_list; - _jdwp_trackers_list.prev = &_jdwp_trackers_list; - - return jdwp_control_init( &_jdwp_control, - JDWP_CONTROL_NAME, - JDWP_CONTROL_NAME_LEN ); +int init_jdwp(void) { + return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN); } #endif /* !ADB_HOST */ |