// This test checks if we can close local socket in the following situation: // The socket is not closed and has some packets. When it fails to write to // the socket's file handler because the other end is closed, we check if the // socket is closed. TEST_F(LocalSocketTest, write_error_when_having_packets) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); int cause_close_fd[2]; ASSERT_EQ(0, adb_socketpair(cause_close_fd)); CloseWithPacketArg arg; arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; PrepareThread(); adb_thread_t thread; ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc), &arg, &thread)); // Wait until the fdevent_loop() starts. adb_sleep_ms(100); EXPECT_EQ(3u, fdevent_installed_count()); ASSERT_EQ(0, adb_close(socket_fd[0])); TerminateThread(thread); }
static void wait_for_state(int fd, void* cookie) { state_info* sinfo = reinterpret_cast<state_info*>(cookie); D("wait_for_state %d", sinfo->state); std::string error_msg = "unknown error"; atransport* t = acquire_one_transport(sinfo->state, sinfo->transport_type, sinfo->serial, &error_msg); if (t != nullptr) { SendOkay(fd); } else { SendFail(fd, error_msg); } if (sinfo->serial) free(sinfo->serial); free(sinfo); adb_close(fd); D("wait_for_state is done"); }
static void wait_for_state(int fd, void *cookie) { struct state_info *sinfo = cookie; char *err = "unknown error"; D("wait_for_state %d\n", sinfo->state); atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); if (t != 0) { writex(fd, "OKAY", 4); } else { sendfailmsg(fd, err); } if (sinfo->serial) free(sinfo->serial); free(sinfo); adb_close(fd); D("wait_for_state is done\n"); }
static void remote_kick(atransport *t) { int fd = t->sfd; t->sfd = -1; adb_shutdown(fd); adb_close(fd); #if ADB_HOST if(HOST) { int nn; adb_mutex_lock( &local_transports_lock ); for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) { if (local_transports[nn] == t) { local_transports[nn] = NULL; break; } } adb_mutex_unlock( &local_transports_lock ); } #endif }
// This test checks when a local socket doesn't enable FDE_READ/FDE_WRITE/FDE_ERROR, it // can still be closed when some error happens on its file handler. // This test successes on linux but fails on mac because of different implementation of // poll(). I think the function tested here is useful to make adb server more stable on // linux. TEST_F(LocalSocketTest, close_with_no_events_installed) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); CloseNoEventsArg arg; arg.socket_fd = socket_fd[1]; pthread_t thread; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(CloseNoEventsThreadFunc), &arg)); // Wait until the fdevent_loop() starts. sleep(1); ASSERT_EQ(2u, fdevent_installed_count()); ASSERT_EQ(0, adb_close(socket_fd[0])); // Wait until the socket is closed. sleep(1); ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); }
static void listener_event_func(int _fd, unsigned ev, void* _l) { alistener* listener = reinterpret_cast<alistener*>(_l); asocket *s; if (ev & FDE_READ) { int fd = adb_socket_accept(_fd, nullptr, nullptr); if (fd < 0) { return; } s = create_local_socket(fd); if (s) { s->transport = listener->transport; connect_to_remote(s, listener->connect_to.c_str()); return; } adb_close(fd); } }
static void connect_device(const std::string& host, std::string* response) { if (host.empty()) { *response = "empty host name"; return; } std::vector<std::string> pieces = android::base::Split(host, ":"); const std::string& hostname = pieces[0]; int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; if (pieces.size() > 1) { if (sscanf(pieces[1].c_str(), "%d", &port) != 1) { *response = android::base::StringPrintf("bad port number %s", pieces[1].c_str()); return; } } // This may look like we're putting 'host' back together, // but we're actually inserting the default port if necessary. std::string serial = android::base::StringPrintf("%s:%d", hostname.c_str(), port); int fd = socket_network_client_timeout(hostname.c_str(), port, SOCK_STREAM, 10); if (fd < 0) { *response = android::base::StringPrintf("unable to connect to %s:%d", hostname.c_str(), port); return; } D("client: connected on remote on fd %d\n", fd); close_on_exec(fd); disable_tcp_nagle(fd); int ret = register_socket_transport(fd, serial.c_str(), port, 0); if (ret < 0) { adb_close(fd); *response = android::base::StringPrintf("already connected to %s", serial.c_str()); } else { *response = android::base::StringPrintf("connected to %s", serial.c_str()); } }
void start_device_log(void) { struct tm now; time_t t; tzset(); time(&t); localtime_r(&t, &now); char timestamp[PATH_MAX]; strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now); std::string path = android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp, getpid()); int fd = unix_open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640); if (fd == -1) { return; } // redirect stdout and stderr to the log file dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid()); adb_close(fd); }
int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie) { syncmsg msg; char buf[257]; int len; len = strlen(path); if(len > 1024) goto fail; msg.req.id = ID_LIST; msg.req.namelen = htoll(len); if(writex(fd, &msg.req, sizeof(msg.req)) || writex(fd, path, len)) { goto fail; } for(;;) { if(readx(fd, &msg.dent, sizeof(msg.dent))) break; if(msg.dent.id == ID_DONE) return 0; if(msg.dent.id != ID_DENT) break; len = ltohl(msg.dent.namelen); if(len > 256) break; if(readx(fd, buf, len)) break; buf[len] = 0; func(ltohl(msg.dent.mode), ltohl(msg.dent.size), ltohl(msg.dent.time), buf, cookie); } fail: adb_close(fd); return -1; }
static int write_data_file(int fd, const char *path, syncsendbuf *sbuf) { int lfd, err = 0; lfd = adb_open(path, O_RDONLY); if(lfd < 0) { fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno)); return -1; } sbuf->id = ID_DATA; for(;;) { int ret; ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX); if(!ret) break; if(ret < 0) { if(errno == EINTR) continue; fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno)); break; } sbuf->size = htoll(ret); if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){ err = -1; break; } total_bytes += ret; STATUS(); } adb_close(lfd); return err; }
static void ss_listener_event_func(int _fd, unsigned ev, void *_l) { asocket *s; if(ev & FDE_READ) { struct sockaddr addr; socklen_t alen; int fd; alen = sizeof(addr); fd = adb_socket_accept(_fd, &addr, &alen); if(fd < 0) return; adb_socket_setbufsize(fd, CHUNK_SIZE); s = create_local_socket(fd); if(s) { connect_to_smartsocket(s); return; } adb_close(fd); } }
static char *_send_shellcommand(transport_type transport, char* serial, char* cmd) { int fd; if((fd=_adb_connect(cmd))<0) { return NULL; } char buf[4096<<2]; char *ptr=buf; int left=sizeof(buf); int len = 0; while(left>0) { int n = adb_read(fd, ptr, left); if(n>0) { ptr += n; left -= n; len += n; } else if(n<=0) { break; } } adb_close(fd); return strndup(buf, len); }
static void server_socket_thread(void* arg) { int serverfd, fd; sockaddr_storage ss; sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss); socklen_t alen; int port = (int) (uintptr_t) arg; adb_thread_setname("server socket"); D("transport: server_socket_thread() starting"); serverfd = -1; for(;;) { if(serverfd == -1) { std::string error; serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error); if(serverfd < 0) { D("server: cannot bind socket yet: %s", error.c_str()); adb_sleep_ms(1000); continue; } close_on_exec(serverfd); } alen = sizeof(ss); D("server: trying to get new connection from %d", port); fd = adb_socket_accept(serverfd, addrp, &alen); if(fd >= 0) { D("server: new connection on fd %d", fd); close_on_exec(fd); disable_tcp_nagle(fd); if (register_socket_transport(fd, "host", port, 1) != 0) { adb_close(fd); } } } D("transport: server_socket_thread() exiting"); }
// This test checks if we can close local socket in the following situation: // The socket is not closed and has some packets. When it fails to write to // the socket's file handler because the other end is closed, we check if the // socket is closed. TEST_F(LocalSocketTest, write_error_when_having_packets) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); int cause_close_fd[2]; ASSERT_EQ(0, adb_socketpair(cause_close_fd)); CloseWithPacketArg arg; arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; pthread_t thread; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(CloseWithPacketThreadFunc), &arg)); // Wait until the fdevent_loop() starts. sleep(1); ASSERT_EQ(3u, fdevent_installed_count()); ASSERT_EQ(0, adb_close(socket_fd[0])); // Wait until the socket is closed. sleep(1); ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); }
bool AdbClient::adb_connect(const char *service) { char tmp[5]; int len; len = strlen(service); if((len < 1) || (len > 1024)) { __adb_error = "service name too long"; return false; } snprintf(tmp, sizeof tmp, "%04x", len); if (memcmp(service,"host",4) != 0 && !switch_socket_transport()) { return false; } if(!writex(tmp, 4) || !writex(service, len)) { __adb_error = "write failure during connection"; adb_close(); return false; } return adb_status(); }
static void listener_event_func(int _fd, unsigned ev, void *_l) { alistener *l = _l; asocket *s; if(ev & FDE_READ) { struct sockaddr addr; socklen_t alen; int fd; alen = sizeof(addr); fd = adb_socket_accept(_fd, &addr, &alen); if(fd < 0) return; s = create_local_socket(fd); if(s) { s->transport = l->transport; connect_to_remote(s, l->connect_to); return; } adb_close(fd); } }
/* A worker thread that monitors host connections, and registers a transport for * every new host connection. This thread replaces server_socket_thread on * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD * pipe to communicate with adbd daemon inside the guest. This is done in order * to provide more robust communication channel between ADB host and guest. The * main issue with server_socket_thread approach is that it runs on top of TCP, * and thus is sensitive to network disruptions. For instance, the * ConnectionManager may decide to reset all network connections, in which case * the connection between ADB host and guest will be lost. To make ADB traffic * independent from the network, we use here 'adb' QEMUD service to transfer data * between the host, and the guest. See external/qemu/android/adb-*.* that * implements the emulator's side of the protocol. Another advantage of using * QEMUD approach is that ADB will be up much sooner, since it doesn't depend * anymore on network being set up. * The guest side of the protocol contains the following phases: * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service * is opened, and it becomes clear whether or not emulator supports that * protocol. * - Wait for the ADB host to create connection with the guest. This is done by * sending an 'accept' request to the adb QEMUD service, and waiting on * response. * - When new ADB host connection is accepted, the connection with adb QEMUD * service is registered as the transport, and a 'start' request is sent to the * adb QEMUD service, indicating that the guest is ready to receive messages. * Note that the guest will ignore messages sent down from the emulator before * the transport registration is completed. That's why we need to send the * 'start' request after the transport is registered. */ static void *qemu_socket_thread(void * arg) { /* 'accept' request to the adb QEMUD service. */ static const char _accept_req[] = "accept"; /* 'start' request to the adb QEMUD service. */ static const char _start_req[] = "start"; /* 'ok' reply from the adb QEMUD service. */ static const char _ok_resp[] = "ok"; const int port = (int) (uintptr_t) arg; int res, fd; char tmp[256]; char con_name[32]; D("transport: qemu_socket_thread() starting\n"); /* adb QEMUD service connection request. */ snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port); /* Connect to the adb QEMUD service. */ fd = qemu_pipe_open(con_name); if (fd < 0) { /* This could be an older version of the emulator, that doesn't * implement adb QEMUD service. Fall back to the old TCP way. */ D("adb service is not available. Falling back to TCP socket.\n"); adb_thread_create(server_socket_thread, arg); return 0; } for(;;) { /* * Wait till the host creates a new connection. */ /* Send the 'accept' request. */ res = adb_write(fd, _accept_req, strlen(_accept_req)); if ((size_t)res == strlen(_accept_req)) { /* Wait for the response. In the response we expect 'ok' on success, * or 'ko' on failure. */ res = adb_read(fd, tmp, sizeof(tmp)); if (res != 2 || memcmp(tmp, _ok_resp, 2)) { D("Accepting ADB host connection has failed.\n"); adb_close(fd); } else { /* Host is connected. Register the transport, and start the * exchange. */ register_socket_transport(fd, "host", port, 1); adb_write(fd, _start_req, strlen(_start_req)); } /* Prepare for accepting of the next ADB host connection. */ fd = qemu_pipe_open(con_name); if (fd < 0) { D("adb service become unavailable.\n"); return 0; } } else { D("Unable to send the '%s' request to ADB service.\n", _accept_req); return 0; } } D("transport: qemu_socket_thread() exiting\n"); return 0; }
static void remote_close(atransport *t) { adb_close(t->fd); }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg * m = addTMessage(); int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, m)) { fatal_errno("cannot read transport registration socket"); } t = m->transport; if(m->action == 0){ D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != CS_NOPERM) { // adb_thread_t * output_thread_ptr = (adb_thread_t*)malloc(sizeof(adb_thread_t)); // adb_thread_t * input_thread_ptr = (adb_thread_t*)malloc(sizeof(adb_thread_t)); /* initial references are the two threads */ t->ref_count = 2; if(adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); struct msg { atransport * t; }; struct msg m = { t }; send_js_msg("spawn-io-threads", &m); /*char i_tag[1024]; char o_tag[1024]; sprintf(i_tag, "I: %s_%d", t->serial, get_guid()); sprintf(o_tag, "O: %s_%d", t->serial, get_guid());*/ //dump_thread_tag(); /*if(adb_thread_create(input_thread_ptr, input_thread, t, i_tag)){ fatal_errno("cannot create input thread"); } if(adb_thread_create(output_thread_ptr, output_thread, t, o_tag)){ fatal_errno("cannot create output thread"); }*/ } /* put us on the master device list */ adb_mutex_lock(&transport_lock); t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; update_transports(); }
int adb_connect(const char *service) { // first query the adb server's version int fd = _adb_connect("host:version"); D("adb_connect: service %s\n", service); if(fd == -2 && __adb_server_name) { fprintf(stderr,"** Cannot start server on remote host\n"); return fd; } else if(fd == -2) { fprintf(stdout,"* daemon not running. starting it now on port %d *\n", __adb_server_port); start_server: if(launch_server(__adb_server_port)) { fprintf(stderr,"* failed to start daemon *\n"); return -1; } else { fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ adb_sleep_ms(3000); // fall through to _adb_connect } else { // if server was running, check its version to make sure it is not out of date char buf[100]; size_t n; int version = ADB_SERVER_VERSION - 1; // if we have a file descriptor, then parse version result if(fd >= 0) { if(!ReadFdExactly(fd, buf, 4)) goto error; buf[4] = 0; n = strtoul(buf, 0, 16); if(n > sizeof(buf)) goto error; if(!ReadFdExactly(fd, buf, n)) goto error; adb_close(fd); if (sscanf(buf, "%04x", &version) != 1) goto error; } else { // if fd is -1, then check for "unknown host service", // which would indicate a version of adb that does not support the version command if (strcmp(__adb_error, "unknown host service") != 0) return fd; } if(version != ADB_SERVER_VERSION) { printf("adb server is out of date. killing...\n"); fd = _adb_connect("host:kill"); adb_close(fd); /* XXX can we better detect its death? */ adb_sleep_ms(2000); goto start_server; } } // if the command is start-server, we are done. if (!strcmp(service, "host:start-server")) return 0; fd = _adb_connect(service); if(fd == -1) { D("_adb_connect error: %s", __adb_error); } else if(fd == -2) { fprintf(stderr,"** daemon still not running\n"); } D("adb_connect: return fd %d\n", fd); return fd; error: adb_close(fd); return -1; }
void restart_usb_service(int fd, void *cookie) { android::base::SetProperty("service.adb.tcp.port", "0"); WriteFdExactly(fd, "restarting in USB mode\n"); adb_close(fd); }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). */ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); if (stdout_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); } if (stderr_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); } ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); char args[64]; snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port); ret = CreateProcess( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }
int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) { syncmsg msg; int len; int lfd = -1; char *buffer = send_buffer.data; unsigned id; unsigned long long size = 0; len = strlen(rpath); if(len > 1024) return -1; if (show_progress) { // Determine remote file size. syncmsg stat_msg; stat_msg.req.id = ID_STAT; stat_msg.req.namelen = htoll(len); if (writex(fd, &stat_msg.req, sizeof(stat_msg.req)) || writex(fd, rpath, len)) { return -1; } if (readx(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { return -1; } if (stat_msg.stat.id != ID_STAT) return -1; size = ltohl(stat_msg.stat.size); } msg.req.id = ID_RECV; msg.req.namelen = htoll(len); if(writex(fd, &msg.req, sizeof(msg.req)) || writex(fd, rpath, len)) { return -1; } if(readx(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; if((id == ID_DATA) || (id == ID_DONE)) { adb_unlink(lpath); mkdirs(lpath); lfd = adb_creat(lpath, 0644); if(lfd < 0) { fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); return -1; } goto handle_data; } else { goto remote_error; } for(;;) { if(readx(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; handle_data: len = ltohl(msg.data.size); if(id == ID_DONE) break; if(id != ID_DATA) goto remote_error; if(len > SYNC_DATA_MAX) { fprintf(stderr,"data overrun\n"); adb_close(lfd); return -1; } if(readx(fd, buffer, len)) { adb_close(lfd); return -1; } if(writex(lfd, buffer, len)) { fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); adb_close(lfd); return -1; } total_bytes += len; if (show_progress) { print_transfer_progress(total_bytes, size); } } adb_close(lfd); return 0; remote_error: adb_close(lfd); adb_unlink(lpath); if(id == ID_FAIL) { len = ltohl(msg.data.size); if(len > 256) len = 256; if(readx(fd, buffer, len)) { return -1; } buffer[len] = 0; } else { memcpy(buffer, &id, 4); buffer[4] = 0; // strcpy(buffer,"unknown reason"); } fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); return 0; }
static int sync_send(int fd, const char *lpath, const char *rpath, unsigned mtime, mode_t mode, int show_progress) { syncmsg msg; int len, r; syncsendbuf *sbuf = &send_buffer; char* file_buffer = NULL; int size = 0; char tmp[64]; len = strlen(rpath); if(len > 1024) goto fail; snprintf(tmp, sizeof(tmp), ",%d", mode); r = strlen(tmp); msg.req.id = ID_SEND; msg.req.namelen = htoll(len + r); if(writex(fd, &msg.req, sizeof(msg.req)) || writex(fd, rpath, len) || writex(fd, tmp, r)) { free(file_buffer); goto fail; } if (file_buffer) { write_data_buffer(fd, file_buffer, size, sbuf, show_progress); free(file_buffer); } else if (S_ISREG(mode)) write_data_file(fd, lpath, sbuf, show_progress); #ifdef HAVE_SYMLINKS else if (S_ISLNK(mode)) write_data_link(fd, lpath, sbuf); #endif else goto fail; msg.data.id = ID_DONE; msg.data.size = htoll(mtime); if(writex(fd, &msg.data, sizeof(msg.data))) goto fail; if(readx(fd, &msg.status, sizeof(msg.status))) return -1; if(msg.status.id != ID_OKAY) { if(msg.status.id == ID_FAIL) { len = ltohl(msg.status.msglen); if(len > 256) len = 256; if(readx(fd, sbuf->data, len)) { return -1; } sbuf->data[len] = 0; } else strcpy(sbuf->data, "unknown reason"); fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); return -1; } return 0; fail: fprintf(stderr,"protocol failure\n"); adb_close(fd); return -1; }
int launch_server(int server_port) { #ifdef HAVE_WIN32_PROC /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); ret = CreateProcess( program_path, /* program path */ "adb fork-server server", /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #elif defined(HAVE_FORKEXEC) char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); // child process int result = execl(path, "adb", "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #else #error "cannot implement background server start on this platform" #endif return 0; }
int adb_connect(const std::string& service, std::string* error) { // first query the adb server's version int fd = _adb_connect("host:version", error); D("adb_connect: service %s", service.c_str()); if (fd == -2 && __adb_server_name) { fprintf(stderr,"** Cannot start server on remote host\n"); // error is the original network connection error return fd; } else if (fd == -2) { fprintf(stdout,"* daemon not running. starting it now on port %d *\n", __adb_server_port); start_server: if (launch_server(__adb_server_port)) { fprintf(stderr,"* failed to start daemon *\n"); // launch_server() has already printed detailed error info, so just // return a generic error string about the overall adb_connect() // that the caller requested. *error = "cannot connect to daemon"; return -1; } else { fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ adb_sleep_ms(3000); // fall through to _adb_connect } else { // if server was running, check its version to make sure it is not out of date int version = ADB_SERVER_VERSION - 1; // if we have a file descriptor, then parse version result if (fd >= 0) { std::string version_string; if (!ReadProtocolString(fd, &version_string, error)) { goto error; } adb_close(fd); if (sscanf(&version_string[0], "%04x", &version) != 1) { *error = android::base::StringPrintf( "cannot parse version string: %s", version_string.c_str()); return -1; } } else { // if fd is -1, then check for "unknown host service", // which would indicate a version of adb that does not support the // version command, in which case we should fall-through to kill it. if (*error != "unknown host service") { return fd; } } if (version != ADB_SERVER_VERSION) { printf("adb server is out of date. killing...\n"); fd = _adb_connect("host:kill", error); if (fd >= 0) { adb_close(fd); } else { // If we couldn't connect to the server or had some other error, // report it, but still try to start the server. fprintf(stderr, "error: %s\n", error->c_str()); } /* XXX can we better detect its death? */ adb_sleep_ms(2000); goto start_server; } } // if the command is start-server, we are done. if (service == "host:start-server") { return 0; } fd = _adb_connect(service, error); if (fd == -1) { D("_adb_connect error: %s", error->c_str()); } else if(fd == -2) { fprintf(stderr,"** daemon still not running\n"); } D("adb_connect: return fd %d", fd); return fd; error: adb_close(fd); return -1; }
static void reconnect_service(int fd, void* arg) { WriteFdExactly(fd, "done"); adb_close(fd); atransport* t = static_cast<atransport*>(arg); kick_transport(t); }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg m; int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, &m)) { fatal_errno("cannot read transport registration socket"); } t = m.transport; if (m.action == 0) { D("transport: %s removing and free'ing %d", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); transport_list.remove(t); adb_mutex_unlock(&transport_lock); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); delete t; update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != kCsNoPerm) { /* initial references are the two threads */ t->ref_count = 2; if (adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); if (!adb_thread_create(write_transport_thread, t)) { fatal_errno("cannot create write_transport thread"); } if (!adb_thread_create(read_transport_thread, t)) { fatal_errno("cannot create read_transport thread"); } } adb_mutex_lock(&transport_lock); pending_list.remove(t); transport_list.push_front(t); adb_mutex_unlock(&transport_lock); update_transports(); }
void restart_usb_service(int fd, void *cookie) { property_set("service.adb.tcp.port", "0"); WriteFdExactly(fd, "restarting in USB mode\n"); adb_close(fd); }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg m; adb_thread_t output_thread_ptr; adb_thread_t input_thread_ptr; int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, &m)) { fatal_errno("cannot read transport registration socket"); } t = m.transport; //action0 ÒƳý action1 ²åÈë if(m.action == 0) { D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != CS_NOPERM) { /* initial references are the two threads */ t->ref_count = 2; if(adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); if(adb_thread_create(&input_thread_ptr, input_thread, t)){ fatal_errno("cannot create input thread"); } if(adb_thread_create(&output_thread_ptr, output_thread, t)){ fatal_errno("cannot create output thread"); } } adb_mutex_lock(&transport_lock); /* remove from pending list */ t->next->prev = t->prev; t->prev->next = t->next; /* put us on the master device list */ t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; update_transports(); }