📄 sockets.c
字号:
*/typedef struct aremotesocket { asocket socket; adisconnect disconnect;} aremotesocket;static int remote_socket_enqueue(asocket *s, apacket *p){ D("Calling remote_socket_enqueue\n"); p->msg.command = A_WRTE; p->msg.arg0 = s->peer->id; p->msg.arg1 = s->id; p->msg.data_length = p->len; send_packet(p, s->transport); return 1;}static void remote_socket_ready(asocket *s){ D("Calling remote_socket_ready\n"); apacket *p = get_apacket(); p->msg.command = A_OKAY; p->msg.arg0 = s->peer->id; p->msg.arg1 = s->id; send_packet(p, s->transport);}static void remote_socket_close(asocket *s){ D("Calling remote_socket_close\n"); apacket *p = get_apacket(); p->msg.command = A_CLSE; if(s->peer) { p->msg.arg0 = s->peer->id; s->peer->peer = 0; s->peer->close(s->peer); } p->msg.arg1 = s->id; send_packet(p, s->transport); D("RS(%d): closed\n", s->id); remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); free(s);}static void remote_socket_disconnect(void* _s, atransport* t){ asocket* s = _s; asocket* peer = s->peer; D("remote_socket_disconnect RS(%d)\n", s->id); if (peer) { peer->peer = NULL; peer->close(peer); } remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); free(s);}asocket *create_remote_socket(unsigned id, atransport *t){ asocket *s = calloc(1, sizeof(aremotesocket)); adisconnect* dis = &((aremotesocket*)s)->disconnect; if(s == 0) fatal("cannot allocate socket"); s->id = id; s->enqueue = remote_socket_enqueue; s->ready = remote_socket_ready; s->close = remote_socket_close; s->transport = t; dis->func = remote_socket_disconnect; dis->opaque = s; add_transport_disconnect( t, dis ); D("RS(%d): created\n", s->id); return s;}void connect_to_remote(asocket *s, const char *destination){ D("Connect_to_remote call \n"); apacket *p = get_apacket(); int len = strlen(destination) + 1; if(len > (MAX_PAYLOAD-1)) { fatal("destination oversized"); } D("LS(%d): connect('%s')\n", s->id, destination); p->msg.command = A_OPEN; p->msg.arg0 = s->id; p->msg.data_length = len; strcpy((char*) p->data, destination); send_packet(p, s->transport);}/* this is used by magic sockets to rig local sockets to send the go-ahead message when they connect */static void local_socket_ready_notify(asocket *s){ s->ready = local_socket_ready; s->close = local_socket_close; adb_write(s->fd, "OKAY", 4); s->ready(s);}/* this is used by magic sockets to rig local sockets to send the failure message if they are closed before connected (to avoid closing them without a status message) */static void local_socket_close_notify(asocket *s){ s->ready = local_socket_ready; s->close = local_socket_close; sendfailmsg(s->fd, "closed"); s->close(s);}unsigned unhex(unsigned char *s, int len){ unsigned n = 0, c; while(len-- > 0) { switch((c = *s++)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c -= '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c = c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c = c - 'A' + 10; break; default: return 0xffffffff; } n = (n << 4) | c; } return n;}static int smart_socket_enqueue(asocket *s, apacket *p){ unsigned len;#if ADB_HOST char *service = NULL; char* serial = NULL; transport_type ttype = kTransportAny;#endif D("SS(%d): enqueue %d\n", s->id, p->len); if(s->pkt_first == 0) { s->pkt_first = p; s->pkt_last = p; } else { if((s->pkt_first->len + p->len) > MAX_PAYLOAD) { D("SS(%d): overflow\n", s->id); put_apacket(p); goto fail; } memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len); s->pkt_first->len += p->len; put_apacket(p); p = s->pkt_first; } /* don't bother if we can't decode the length */ if(p->len < 4) return 0; len = unhex(p->data, 4); if((len < 1) || (len > 1024)) { D("SS(%d): bad size (%d)\n", s->id, len); goto fail; } D("SS(%d): len is %d\n", s->id, len ); /* can't do anything until we have the full header */ if((len + 4) > p->len) { D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len); return 0; } p->data[len + 4] = 0; D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));#if ADB_HOST service = (char *)p->data + 4; if(!strncmp(service, "host-serial:", strlen("host-serial:"))) { char* serial_end; service += strlen("host-serial:"); // serial number should follow "host:" serial_end = strchr(service, ':'); if (serial_end) { *serial_end = 0; // terminate string serial = service; service = serial_end + 1; } } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) { ttype = kTransportUsb; service += strlen("host-usb:"); } else if (!strncmp(service, "host-local:", strlen("host-local:"))) { ttype = kTransportLocal; service += strlen("host-local:"); } else if (!strncmp(service, "host:", strlen("host:"))) { ttype = kTransportAny; service += strlen("host:"); } else { service = NULL; } if (service) { asocket *s2; /* some requests are handled immediately -- in that ** case the handle_host_request() routine has sent ** the OKAY or FAIL message and all we have to do ** is clean up. */ if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) { /* XXX fail message? */ D( "SS(%d): handled host service '%s'\n", s->id, service ); goto fail; } if (!strncmp(service, "transport", strlen("transport"))) { D( "SS(%d): okay transport\n", s->id ); p->len = 0; return 0; } /* try to find a local service with this name. ** if no such service exists, we'll fail out ** and tear down here. */ s2 = create_host_service_socket(service, serial); if(s2 == 0) { D( "SS(%d): couldn't create host service '%s'\n", s->id, service ); sendfailmsg(s->peer->fd, "unknown host service"); goto fail; } /* we've connected to a local host service, ** so we make our peer back into a regular ** local socket and bind it to the new local ** service socket, acknowledge the successful ** connection, and close this smart socket now ** that its work is done. */ adb_write(s->peer->fd, "OKAY", 4); s->peer->ready = local_socket_ready; s->peer->close = local_socket_close; s->peer->peer = s2; s2->peer = s->peer; s->peer = 0; D( "SS(%d): okay\n", s->id ); s->close(s); /* initial state is "ready" */ s2->ready(s2); return 0; }#else /* !ADB_HOST */ if (s->transport == NULL) { char* error_string = "unknown failure"; s->transport = acquire_one_transport (CS_ANY, kTransportAny, NULL, &error_string); if (s->transport == NULL) { sendfailmsg(s->peer->fd, error_string); goto fail; } }#endif if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) { /* if there's no remote we fail the connection ** right here and terminate it */ sendfailmsg(s->peer->fd, "device offline (x)"); goto fail; } /* instrument our peer to pass the success or fail ** message back once it connects or closes, then ** detach from it, request the connection, and ** tear down */ s->peer->ready = local_socket_ready_notify; s->peer->close = local_socket_close_notify; s->peer->peer = 0; /* give him our transport and upref it */ s->peer->transport = s->transport; connect_to_remote(s->peer, (char*) (p->data + 4)); s->peer = 0; s->close(s); return 1;fail: /* we're going to close our peer as a side-effect, so ** return -1 to signal that state to the local socket ** who is enqueueing against us */ s->close(s); return -1;}static void smart_socket_ready(asocket *s){ D("SS(%d): ready\n", s->id);}static void smart_socket_close(asocket *s){ D("SS(%d): closed\n", s->id); if(s->pkt_first){ put_apacket(s->pkt_first); } if(s->peer) { s->peer->peer = 0; s->peer->close(s->peer); } free(s);}asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act)){ D("Creating smart socket \n"); asocket *s = calloc(1, sizeof(asocket)); if(s == 0) fatal("cannot allocate socket"); s->id = 0; s->enqueue = smart_socket_enqueue; s->ready = smart_socket_ready; s->close = smart_socket_close; s->extra = action_cb; D("SS(%d): created %p\n", s->id, action_cb); return s;}void smart_socket_action(asocket *s, const char *act){}void connect_to_smartsocket(asocket *s){ D("Connecting to smart socket \n"); asocket *ss = create_smart_socket(smart_socket_action); s->peer = ss; ss->peer = s; s->ready(s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -