static void local_socket_close_locked(asocket *s) { D("entered. LS(%d) fd=%d\n", s->id, s->fd); if(s->peer) { D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", s->id, s->peer->id, s->peer->fd); s->peer->peer = 0; // tweak to avoid deadlock if (s->peer->close == local_socket_close) { local_socket_close_locked(s->peer); } else { s->peer->close(s->peer); } s->peer = 0; } /* If we are already closing, or if there are no ** pending packets, destroy immediately */ if (s->closing || s->pkt_first == NULL) { int id = s->id; local_socket_destroy(s); D("LS(%d): closed\n", id); return; } /* otherwise, put on the closing list */ D("LS(%d): closing\n", s->id); s->closing = 1; fdevent_del(&s->fde, FDE_READ); remove_socket(s); D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd); insert_local_socket(s, &local_socket_closing_list); }
static void local_socket_close_locked(asocket *s) { D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd); if(s->peer) { D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", s->id, s->peer->id, s->peer->fd); /* Note: it's important to call shutdown before disconnecting from * the peer, this ensures that remote sockets can still get the id * of the local socket they're connected to, to send a CLOSE() * protocol event. */ if (s->peer->shutdown) s->peer->shutdown(s->peer); s->peer->peer = 0; // tweak to avoid deadlock if (s->peer->close == local_socket_close) { local_socket_close_locked(s->peer); } else { s->peer->close(s->peer); } s->peer = 0; } /* If we are already closing, or if there are no ** pending packets, destroy immediately */ if (s->closing || s->pkt_first == NULL) { int id = s->id; local_socket_destroy(s); D("LS(%d): closed\n", id); return; } /* otherwise, put on the closing list */ D("LS(%d): closing\n", s->id); s->closing = 1; fdevent_del(&s->fde, FDE_READ); remove_socket(s); D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd); insert_local_socket(s, &local_socket_closing_list); }
static void FdEventCallback(int fd, unsigned events, void* userdata) { FdHandler* handler = reinterpret_cast<FdHandler*>(userdata); ASSERT_EQ(0u, (events & ~(FDE_READ | FDE_WRITE))) << "unexpected events: " << events; if (events & FDE_READ) { ASSERT_EQ(fd, handler->read_fd_); char c; ASSERT_EQ(1, read(fd, &c, 1)); handler->queue_.push(c); fdevent_add(&handler->write_fde_, FDE_WRITE); } if (events & FDE_WRITE) { ASSERT_EQ(fd, handler->write_fd_); ASSERT_FALSE(handler->queue_.empty()); char c = handler->queue_.front(); handler->queue_.pop(); ASSERT_EQ(1, write(fd, &c, 1)); if (handler->queue_.empty()) { fdevent_del(&handler->write_fde_, FDE_WRITE); } } }
static void local_socket_close(asocket* s) { D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd); std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock); if (s->peer) { D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); /* Note: it's important to call shutdown before disconnecting from * the peer, this ensures that remote sockets can still get the id * of the local socket they're connected to, to send a CLOSE() * protocol event. */ if (s->peer->shutdown) { s->peer->shutdown(s->peer); } s->peer->peer = nullptr; s->peer->close(s->peer); s->peer = nullptr; } /* If we are already closing, or if there are no ** pending packets, destroy immediately */ if (s->closing || s->has_write_error || s->pkt_first == NULL) { int id = s->id; local_socket_destroy(s); D("LS(%d): closed", id); return; } /* otherwise, put on the closing list */ D("LS(%d): closing", s->id); s->closing = 1; fdevent_del(&s->fde, FDE_READ); remove_socket(s); D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd); insert_local_socket(s, &local_socket_closing_list); CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE); }
static void local_socket_event_func(int fd, unsigned ev, void* _s) { asocket* s = reinterpret_cast<asocket*>(_s); D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev); /* put the FDE_WRITE processing before the FDE_READ ** in order to simplify the code. */ if (ev & FDE_WRITE) { apacket* p; while ((p = s->pkt_first) != nullptr) { while (p->len > 0) { int r = adb_write(fd, p->ptr, p->len); if (r == -1) { /* returning here is ok because FDE_READ will ** be processed in the next iteration loop */ if (errno == EAGAIN) { return; } } else if (r > 0) { p->ptr += r; p->len -= r; continue; } D(" closing after write because r=%d and errno is %d", r, errno); s->has_write_error = true; s->close(s); return; } if (p->len == 0) { s->pkt_first = p->next; if (s->pkt_first == 0) { s->pkt_last = 0; } put_apacket(p); } } /* if we sent the last packet of a closing socket, ** we can now destroy it. */ if (s->closing) { D(" closing because 'closing' is set after write"); s->close(s); return; } /* no more packets queued, so we can ignore ** writable events again and tell our peer ** to resume writing */ fdevent_del(&s->fde, FDE_WRITE); s->peer->ready(s->peer); } if (ev & FDE_READ) { apacket* p = get_apacket(); char* x = p->data; const size_t max_payload = s->get_max_payload(); size_t avail = max_payload; int r = 0; int is_eof = 0; while (avail > 0) { r = adb_read(fd, x, avail); D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r, r < 0 ? errno : 0, avail); if (r == -1) { if (errno == EAGAIN) { break; } } else if (r > 0) { avail -= r; x += r; continue; } /* r = 0 or unhandled error */ is_eof = 1; break; } D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof, s->fde.force_eof); if ((avail == max_payload) || (s->peer == 0)) { put_apacket(p); } else { p->len = max_payload - avail; // s->peer->enqueue() may call s->close() and free s, // so save variables for debug printing below. unsigned saved_id = s->id; int saved_fd = s->fd; r = s->peer->enqueue(s->peer, p); D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r); if (r < 0) { /* error return means they closed us as a side-effect ** and we must return immediately. ** ** note that if we still have buffered packets, the ** socket will be placed on the closing socket list. ** this handler function will be called again ** to process FDE_WRITE events. */ return; } if (r > 0) { /* if the remote cannot accept further events, ** we disable notification of READs. They'll ** be enabled again when we get a call to ready() */ fdevent_del(&s->fde, FDE_READ); } } /* Don't allow a forced eof if data is still there */ if ((s->fde.force_eof && !r) || is_eof) { D(" closing because is_eof=%d r=%d s->fde.force_eof=%d", is_eof, r, s->fde.force_eof); s->close(s); return; } } if (ev & FDE_ERROR) { /* this should be caught be the next read or write ** catching it here means we may skip the last few ** bytes of readable data. */ D("LS(%d): FDE_ERROR (fd=%d)", s->id, s->fd); return; } }
static void jdwp_process_event( int socket, unsigned events, void* _proc ) { JdwpProcess* proc = _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\n", strerror(errno)); goto CloseProcess; } if (len == 0) { /* end of stream ? */ D("weird end-of-stream from unknown JDWP process\n"); goto CloseProcess; } p += len; proc->in_len += len; size -= len; } /* 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'\n", proc, temp); goto CloseProcess; } /* all is well, keep reading to detect connection closure */ D("Adding pid %d to jdwp process list\n", proc->pid); jdwp_process_list_updated(); } 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]; for (;;) { int len = recv(socket, buf, sizeof(buf), 0); if (len <= 0) { if (len < 0 && errno == EINTR) continue; if (len < 0 && errno == EAGAIN) return; else { D("terminating JDWP %d connection: %s\n", proc->pid, strerror(errno)); break; } } else { D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n", proc->pid, len ); } } CloseProcess: if (proc->pid >= 0) D( "remove pid %d to jdwp process list\n", proc->pid ); jdwp_process_free(proc); return; } } if (events & FDE_WRITE) { D("trying to write to JDWP pid controli (count=%d first=%d) %d\n", 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)]; int flags; 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_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; ((int*)CMSG_DATA(cmsg))[0] = fd; flags = fcntl(proc->socket,F_GETFL,0); if (flags == -1) { D("failed to get cntl flags for socket %d: %s\n", proc->pid, strerror(errno)); goto CloseProcess; } if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) { D("failed to remove O_NONBLOCK flag for socket %d: %s\n", proc->pid, strerror(errno)); 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\n", proc->pid, strerror(errno)); goto CloseProcess; } D("sent file descriptor %d to JDWP process %d\n", fd, proc->pid); for (n = 1; n < proc->out_count; n++) proc->out_fds[n-1] = proc->out_fds[n]; if (fcntl(proc->socket, F_SETFL, flags) == -1) { D("failed to set O_NONBLOCK flag for socket %d: %s\n", proc->pid, strerror(errno)); goto CloseProcess; } if (--proc->out_count == 0) fdevent_del( proc->fde, FDE_WRITE ); } } }
static void jdwp_process_event(int socket, unsigned events, void* _proc) { JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc); CHECK_EQ(socket, proc->socket); if (events & FDE_READ) { if (proc->pid < 0) { ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0)); if (rc != sizeof(proc->pid)) { D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno)); 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 { // We already have the PID, if we can read from the socket, we've probably hit EOF. D("terminating JDWP connection %d", proc->pid); goto CloseProcess; } } if (events & FDE_WRITE) { D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size()); CHECK(!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 = nullptr; 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_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; ((int*)CMSG_DATA(cmsg))[0] = fd; int ret = TEMP_FAILURE_RETRY(sendmsg(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); proc->out_fds.pop_back(); if (proc->out_fds.empty()) { fdevent_del(proc->fde, FDE_WRITE); } } return; CloseProcess: proc->RemoveFromList(); jdwp_process_list_updated(); }
static void local_socket_event_func(int fd, unsigned ev, void *_s) { asocket *s = _s; D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev); /* put the FDE_WRITE processing before the FDE_READ ** in order to simplify the code. */ if(ev & FDE_WRITE){ //check if in the array bool bFound = false; int i = 0; for(i = 0; i < FD_ARRAY_SIZE; ++i){ if(fd_write_array[i] == fd){ //Do not need to update array bFound = true; break; } } if(bFound == false){ if(fd_write_idx > FD_ARRAY_SIZE - 1){ //Out of range, so we have to print fd directly XLOGD("Too many write adb socket fd=%d, ", fd); }else{ fd_write_array[fd_write_idx] = fd; fd_write_idx++; } } apacket *p; while((p = s->pkt_first) != 0) { while(p->len > 0) { int r = adb_write(fd, p->ptr, p->len); if(r > 0) { p->ptr += r; p->len -= r; write_data += r; continue; } if(r < 0) { /* returning here is ok because FDE_READ will ** be processed in the next iteration loop */ if(errno == EAGAIN) return; if(errno == EINTR) continue; } D(" closing after write because r=%d and errno is %d\n", r, errno); XLOGW(" closing after write because r=%d and errno is %d\n", r, errno); s->close(s); return; } clock_t this_write_time = clock(); double cpu_time_used = ((double) (this_write_time - last_write_time)) / CLOCKS_PER_SEC; if( cpu_time_used > 10.0 ) { char output_log[512]; char tmp[16]; sprintf(output_log, "%s", "adb socket write list "); int i = 0; for(i = 0; i < fd_write_idx; ++ i){ sprintf(tmp, "(%d) ", fd_write_array[i]); strcat(output_log, tmp); //XLOGD("adb socket write fd=%d, ", fd_write_array[i]); fd_write_array[i] = 0; } XLOGD("%s\n", output_log); XLOGD("write_data=%d\n", write_data); last_write_time = this_write_time; write_data = 0; fd_write_idx = 0; } if(p->len == 0) { s->pkt_first = p->next; if(s->pkt_first == 0) s->pkt_last = 0; put_apacket(p); } } /* if we sent the last packet of a closing socket, ** we can now destroy it. */ if (s->closing) { D(" closing because 'closing' is set after write\n"); XLOGW(" closing because 'closing' is set after write\n"); s->close(s); return; } /* no more packets queued, so we can ignore ** writable events again and tell our peer ** to resume writing */ fdevent_del(&s->fde, FDE_WRITE); s->peer->ready(s->peer); } if(ev & FDE_READ){ //check if in the array bool bFound = false; int i = 0; for(i = 0; i < FD_ARRAY_SIZE; ++i){ if(fd_read_array[i] == fd){ //Do not need to update array bFound = true; break; } } if(bFound == false){ if(fd_read_idx > FD_ARRAY_SIZE - 1){ //Out of range, so we have to print directly XLOGD("Too many read adb socket fd=%d, ", fd); }else{ fd_read_array[fd_read_idx] = fd; fd_read_idx++; } } apacket *p = get_apacket(); unsigned char *x = p->data; size_t avail = MAX_PAYLOAD; int r; int is_eof = 0; clock_t time1 = clock(); while(avail > 0) { r = adb_read(fd, x, avail); D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail); if(r > 0) { avail -= r; x += r; read_data += r; continue; } if(r < 0) { if(errno == EAGAIN) break; if(errno == EINTR) continue; } /* r = 0 or unhandled error */ is_eof = 1; break; } clock_t this_read_time = clock(); double cpu_time_used = ((double) (this_read_time - last_read_time)) / CLOCKS_PER_SEC; if( cpu_time_used > 5.0 ) { char output_log[512]; char tmp[16]; sprintf(output_log, "%s", "adb socket read list "); int i = 0; for(i = 0; i < fd_read_idx; ++ i){ sprintf(tmp, "(%d) ", fd_read_array[i]); strcat(output_log, tmp); //XLOGD("adb socket read fd=%d, ", fd_read_array[i]); fd_read_array[i] = 0; } XLOGD("%s\n", output_log); XLOGD("read_data=%d\n", read_data); last_read_time = this_read_time; read_data = 0; fd_read_idx = 0; } D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n", s->id, s->fd, r, is_eof, s->fde.force_eof); clock_t time2 = clock(); if ( time2 - time1 > max_read_time ){ max_read_time = time2 - time1; } if((avail == MAX_PAYLOAD) || (s->peer == 0)) { put_apacket(p); } else { p->len = MAX_PAYLOAD - avail; r = s->peer->enqueue(s->peer, p); D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r); clock_t time3 = clock(); if( time3 - time2 > max_send_time){ max_send_time = time3 - time2; } if(r < 0) { /* error return means they closed us as a side-effect ** and we must return immediately. ** ** note that if we still have buffered packets, the ** socket will be placed on the closing socket list. ** this handler function will be called again ** to process FDE_WRITE events. */ return; } if(r > 0) { /* if the remote cannot accept further events, ** we disable notification of READs. They'll ** be enabled again when we get a call to ready() */ fdevent_del(&s->fde, FDE_READ); } } if( cpu_time_used > 5.0 ) { double read_time = ((double) max_read_time) / CLOCKS_PER_SEC; double send_time = ((double) max_send_time) / CLOCKS_PER_SEC; XLOGD("max_read_time=%f max_send_time=%f \n", read_time, send_time); max_read_time = 0; max_send_time = 0; } /* Don't allow a forced eof if data is still there */ if((s->fde.force_eof && !r) || is_eof) { D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); XLOGD(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); s->close(s); } } if(ev & FDE_ERROR){ /* this should be caught be the next read or write ** catching it here means we may skip the last few ** bytes of readable data. */ // s->close(s); D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd); XLOGD("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd); return; } }