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; } if (proc->fde != NULL) { fdevent_destroy(proc->fde); proc->fde = NULL; } proc->pid = -1; for (n = 0; n < proc->out_count; n++) { adb_close(proc->out_fds[n]); } proc->out_count = 0; free(proc); jdwp_process_list_updated(); } }
~JdwpProcess() { if (this->socket >= 0) { adb_shutdown(this->socket); this->socket = -1; } if (this->fde) { fdevent_destroy(this->fde); this->fde = nullptr; } out_fds.clear(); }
static void remote_kick(atransport *t) { int fd = t->sfd; t->sfd = -1; adb_shutdown(fd); adb_close(fd); #if ADB_HOST int nn; std::lock_guard<std::mutex> lock(local_transports_lock); for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) { if (local_transports[nn] == t) { local_transports[nn] = NULL; break; } } #endif }
bool ReadOrderlyShutdown(int fd) { char buf[16]; // Only call this function if you're sure that the peer does // orderly/graceful shutdown of the socket, closing the socket so that // adb_read() will return 0. If the peer keeps the socket open, adb_read() // will never return. int result = adb_read(fd, buf, sizeof(buf)); if (result == -1) { // If errno is EAGAIN, that means this function was called on a // nonblocking socket and it would have blocked (which would be bad // because we'd probably block the main thread where nonblocking IO is // done). Don't do that. If you have a nonblocking socket, use the // fdevent APIs to get called on FDE_READ, and then call this function // if you really need to, but it shouldn't be needed for server sockets. CHECK_NE(errno, EAGAIN); // Note that on Windows, orderly shutdown sometimes causes // recv() == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET. That // can be ignored. return false; } else if (result == 0) { // Peer has performed an orderly/graceful shutdown. return true; } else { // Unexpectedly received data. This is essentially a protocol error // because you should not call this function unless you expect no more // data. We don't repeatedly call adb_read() until we get zero because // we don't know how long that would take, but we do know that the // caller wants to close the socket soon. VLOG(RWX) << "ReadOrderlyShutdown(" << fd << ") unexpectedly read " << dump_hex(buf, result); // Shutdown the socket to prevent the caller from reading or writing to // it which doesn't make sense if we just read and discarded some data. adb_shutdown(fd); errno = EINVAL; return false; } }
int handle_host_request(const char* service, TransportType type, const char* serial, int reply_fd, asocket* s) { if (strcmp(service, "kill") == 0) { fprintf(stderr, "adb server killed by remote request\n"); fflush(stdout); SendOkay(reply_fd); // On Windows, if the process exits with open sockets that // shutdown(SD_SEND) has not been called on, TCP RST segments will be // sent to the peers which will cause their next recv() to error-out // with WSAECONNRESET. In the case of this code, that means the client // may not read the OKAY sent above. adb_shutdown(reply_fd); exit(0); } #if ADB_HOST // "transport:" is used for switching transport with a specified serial number // "transport-usb:" is used for switching transport to the only USB transport // "transport-local:" is used for switching transport to the only local transport // "transport-any:" is used for switching transport to the only transport if (!strncmp(service, "transport", strlen("transport"))) { TransportType type = kTransportAny; if (!strncmp(service, "transport-usb", strlen("transport-usb"))) { type = kTransportUsb; } else if (!strncmp(service, "transport-local", strlen("transport-local"))) { type = kTransportLocal; } else if (!strncmp(service, "transport-any", strlen("transport-any"))) { type = kTransportAny; } else if (!strncmp(service, "transport:", strlen("transport:"))) { service += strlen("transport:"); serial = service; } std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t != nullptr) { s->transport = t; SendOkay(reply_fd); } else { SendFail(reply_fd, error); } return 1; } // return a list of all connected devices if (!strncmp(service, "devices", 7)) { bool long_listing = (strcmp(service+7, "-l") == 0); if (long_listing || service[7] == 0) { D("Getting device list..."); std::string device_list = list_transports(long_listing); D("Sending device list..."); return SendOkay(reply_fd, device_list); } return 1; } if (!strcmp(service, "features")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t != nullptr) { SendOkay(reply_fd, FeatureSetToString(t->features())); } else { SendFail(reply_fd, error); } return 0; } // remove TCP transport if (!strncmp(service, "disconnect:", 11)) { const std::string address(service + 11); if (address.empty()) { kick_all_tcp_devices(); return SendOkay(reply_fd, "disconnected everything"); } std::string serial; std::string host; int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; std::string error; if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) { return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s", address.c_str(), error.c_str())); } atransport* t = find_transport(serial.c_str()); if (t == nullptr) { return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'", serial.c_str())); } kick_transport(t); return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str())); } // Returns our value for ADB_SERVER_VERSION. if (!strcmp(service, "version")) { return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION)); } // These always report "unknown" rather than the actual error, for scripts. if (!strcmp(service, "get-serialno")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t) { return SendOkay(reply_fd, t->serial ? t->serial : "unknown"); } else { return SendFail(reply_fd, error); } } if (!strcmp(service, "get-devpath")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t) { return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown"); } else { return SendFail(reply_fd, error); } } if (!strcmp(service, "get-state")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t) { return SendOkay(reply_fd, t->connection_state_name()); } else { return SendFail(reply_fd, error); } } // Indicates a new emulator instance has started. if (!strncmp(service, "emulator:", 9)) { int port = atoi(service+9); local_connect(port); /* we don't even need to send a reply */ return 0; } if (!strcmp(service, "reconnect")) { if (s->transport != nullptr) { kick_transport(s->transport); } return SendOkay(reply_fd, "done"); } #endif // ADB_HOST int ret = handle_forward_request(service, type, serial, reply_fd); if (ret >= 0) return ret - 1; return -1; }
int handle_host_request(const char* service, TransportType type, const char* serial, int reply_fd, asocket* s) { if (strcmp(service, "kill") == 0) { fprintf(stderr, "adb server killed by remote request\n"); fflush(stdout); SendOkay(reply_fd); // At least on Windows, if we exit() without shutdown(SD_SEND) or // closesocket(), the client's next recv() will error-out with // WSAECONNRESET and they'll never read the OKAY. adb_shutdown(reply_fd); exit(0); } #if ADB_HOST // "transport:" is used for switching transport with a specified serial number // "transport-usb:" is used for switching transport to the only USB transport // "transport-local:" is used for switching transport to the only local transport // "transport-any:" is used for switching transport to the only transport if (!strncmp(service, "transport", strlen("transport"))) { TransportType type = kTransportAny; if (!strncmp(service, "transport-usb", strlen("transport-usb"))) { type = kTransportUsb; } else if (!strncmp(service, "transport-local", strlen("transport-local"))) { type = kTransportLocal; } else if (!strncmp(service, "transport-any", strlen("transport-any"))) { type = kTransportAny; } else if (!strncmp(service, "transport:", strlen("transport:"))) { service += strlen("transport:"); serial = service; } std::string error_msg; atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg); if (t != nullptr) { s->transport = t; SendOkay(reply_fd); } else { SendFail(reply_fd, error_msg); } return 1; } // return a list of all connected devices if (!strncmp(service, "devices", 7)) { bool long_listing = (strcmp(service+7, "-l") == 0); if (long_listing || service[7] == 0) { D("Getting device list..."); std::string device_list = list_transports(long_listing); D("Sending device list..."); return SendOkay(reply_fd, device_list); } return 1; } if (!strcmp(service, "features")) { std::string error_msg; atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg); if (t != nullptr) { SendOkay(reply_fd, android::base::Join(t->features(), '\n')); } else { SendFail(reply_fd, error_msg); } return 0; } if (!strncmp(service, "check-feature:", strlen("check-feature:"))) { std::string error_msg; atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg); if (t && t->CanUseFeature(service + strlen("check-feature:"))) { // We could potentially extend this to reply with the feature // version if that becomes necessary. SendOkay(reply_fd, "1"); } else { // Empty response means unsupported feature. SendOkay(reply_fd, ""); } return 0; } // remove TCP transport if (!strncmp(service, "disconnect:", 11)) { const std::string address(service + 11); if (address.empty()) { kick_all_tcp_devices(); return SendOkay(reply_fd, "disconnected everything"); } std::string serial; std::string host; int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; std::string error; if (!parse_host_and_port(address, &serial, &host, &port, &error)) { return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s", address.c_str(), error.c_str())); } atransport* t = find_transport(serial.c_str()); if (t == nullptr) { return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'", serial.c_str())); } kick_transport(t); return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str())); } // returns our value for ADB_SERVER_VERSION if (!strcmp(service, "version")) { return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION)); } // These always report "unknown" rather than the actual error, for scripts. if (!strcmp(service, "get-serialno")) { std::string ignored; atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored); return SendOkay(reply_fd, (t && t->serial) ? t->serial : "unknown"); } if (!strcmp(service, "get-devpath")) { std::string ignored; atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored); return SendOkay(reply_fd, (t && t->devpath) ? t->devpath : "unknown"); } if (!strcmp(service, "get-state")) { std::string ignored; atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored); return SendOkay(reply_fd, t ? t->connection_state_name() : "unknown"); } // indicates a new emulator instance has started if (!strncmp(service, "emulator:", 9)) { int port = atoi(service+9); local_connect(port); /* we don't even need to send a reply */ return 0; } #endif // ADB_HOST int ret = handle_forward_request(service, type, serial, reply_fd); if (ret >= 0) return ret - 1; return -1; }