⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include "sysdeps.h"#define   TRACE_TAG  TRACE_TRANSPORT#include "adb.h"static void transport_unref(atransport *t);static atransport transport_list = {    .next = &transport_list,    .prev = &transport_list,};ADB_MUTEX_DEFINE( transport_lock );#if ADB_TRACEstatic void  dump_hex( const unsigned char*  ptr, size_t  len ){    int  nn, len2 = len;    if (len2 > 16) len2 = 16;    for (nn = 0; nn < len2; nn++)        D("%02x", ptr[nn]);    D("  ");    for (nn = 0; nn < len2; nn++) {        int  c = ptr[nn];        if (c < 32 || c > 127)            c = '.';        D("%c", c);    }    D("\n");    fflush(stdout);}#endifvoidkick_transport(atransport*  t){    if (t && !t->kicked)    {        int  kicked;        adb_mutex_lock(&transport_lock);        kicked = t->kicked;        if (!kicked)            t->kicked = 1;        adb_mutex_unlock(&transport_lock);        if (!kicked)            t->kick(t);    }}voidrun_transport_disconnects(atransport*  t){    adisconnect*  dis = t->disconnects.next;    D("run_transport_disconnects: %p (%s)\n", t, t->serial ? t->serial : "unknown" );    while (dis != &t->disconnects) {        adisconnect*  next = dis->next;        dis->func( dis->opaque, t );        dis = next;    }}static intread_packet(int  fd, apacket** ppacket){    char *p = (char*)ppacket;  /* really read a packet address */    int   r;    int   len = sizeof(*ppacket);    while(len > 0) {        r = adb_read(fd, p, len);        if(r > 0) {            len -= r;            p   += r;        } else {            D("read_packet: %d error %d %d\n", fd, r, errno);            if((r < 0) && (errno == EINTR)) continue;            return -1;        }    }#if ADB_TRACE    if (ADB_TRACING)    {        unsigned  command = (*ppacket)->msg.command;        int       len     = (*ppacket)->msg.data_length;        char      cmd[5];        int       n;        for (n = 0; n < 4; n++) {            int  b = (command >> (n*8)) & 255;            if (b >= 32 && b < 127)                cmd[n] = (char)b;            else                cmd[n] = '.';        }        cmd[4] = 0;        D("read_packet: %d ok: [%08x %s] %08x %08x (%d) ",          fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len);        dump_hex((*ppacket)->data, len);    }#endif    return 0;}static intwrite_packet(int  fd, apacket** ppacket){    char *p = (char*) ppacket;  /* we really write the packet address */    int r, len = sizeof(ppacket);#if ADB_TRACE    if (ADB_TRACING)    {        unsigned  command = (*ppacket)->msg.command;        int       len     = (*ppacket)->msg.data_length;        char      cmd[5];        int       n;        for (n = 0; n < 4; n++) {            int  b = (command >> (n*8)) & 255;            if (b >= 32 && b < 127)                cmd[n] = (char)b;            else                cmd[n] = '.';        }        cmd[4] = 0;        D("write_packet: %d [%08x %s] %08x %08x (%d) ",          fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len);        dump_hex((*ppacket)->data, len);    }#endif    len = sizeof(ppacket);    while(len > 0) {        r = adb_write(fd, p, len);        if(r > 0) {            len -= r;            p += r;        } else {            D("write_packet: %d error %d %d\n", fd, r, errno);            if((r < 0) && (errno == EINTR)) continue;            return -1;        }    }    return 0;}static void transport_socket_events(int fd, unsigned events, void *_t){    if(events & FDE_READ){        apacket *p = 0;        if(read_packet(fd, &p)){            D("failed to read packet from transport socket on fd %d\n", fd);        } else {            handle_packet(p, (atransport *) _t);        }    }}void send_packet(apacket *p, atransport *t){    unsigned char *x;    unsigned sum;    unsigned count;    p->msg.magic = p->msg.command ^ 0xffffffff;    count = p->msg.data_length;    x = (unsigned char *) p->data;    sum = 0;    while(count-- > 0){        sum += *x++;    }    p->msg.data_check = sum;    print_packet("send", p);    if (t == NULL) {        fatal_errno("Transport is null");        D("Transport is null \n");    }    if(write_packet(t->transport_socket, &p)){        fatal_errno("cannot enqueue packet on transport socket");    }}/* The transport is opened by transport_register_func before** the input and output threads are started.**** The output thread issues a SYNC(1, token) message to let** the input thread know to start things up.  In the event** of transport IO failure, the output thread will post a** SYNC(0,0) message to ensure shutdown.**** The transport will not actually be closed until both** threads exit, but the input thread will kick the transport** on its way out to disconnect the underlying device.*/static void *output_thread(void *_t){    atransport *t = _t;    apacket *p;    D("from_remote: starting thread for transport %p, on fd %d\n", t, t->fd );    D("from_remote: transport %p SYNC online (%d)\n", t, t->sync_token + 1);    p = get_apacket();    p->msg.command = A_SYNC;    p->msg.arg0 = 1;    p->msg.arg1 = ++(t->sync_token);    p->msg.magic = A_SYNC ^ 0xffffffff;    if(write_packet(t->fd, &p)) {        put_apacket(p);        D("from_remote: failed to write SYNC apacket to transport %p", t);        goto oops;    }    D("from_remote: data pump  for transport %p\n", t);    for(;;) {        p = get_apacket();        if(t->read_from_remote(p, t) == 0){            D("from_remote: received remote packet, sending to transport %p\n",              t);            if(write_packet(t->fd, &p)){                put_apacket(p);                D("from_remote: failed to write apacket to transport %p", t);                goto oops;            }        } else {            D("from_remote: remote read failed for transport %p\n", p);            put_apacket(p);            break;        }    }    D("from_remote: SYNC offline for transport %p\n", t);    p = get_apacket();    p->msg.command = A_SYNC;    p->msg.arg0 = 0;    p->msg.arg1 = 0;    p->msg.magic = A_SYNC ^ 0xffffffff;    if(write_packet(t->fd, &p)) {        put_apacket(p);        D("from_remote: failed to write SYNC apacket to transport %p", t);    }oops:    D("from_remote: thread is exiting for transport %p\n", t);    kick_transport(t);    transport_unref(t);    return 0;}static void *input_thread(void *_t){    atransport *t = _t;    apacket *p;    int active = 0;    D("to_remote: starting input_thread for %p, reading from fd %d\n",       t, t->fd);    for(;;){        if(read_packet(t->fd, &p)) {            D("to_remote: failed to read apacket from transport %p on fd %d\n",                t, t->fd );            break;        }        if(p->msg.command == A_SYNC){            if(p->msg.arg0 == 0) {                D("to_remote: transport %p SYNC offline\n", t);                put_apacket(p);                break;            } else {                if(p->msg.arg1 == t->sync_token) {                    D("to_remote: transport %p SYNC online\n", t);                    active = 1;                } else {                    D("to_remote: trandport %p ignoring SYNC %d != %d\n",                      t, p->msg.arg1, t->sync_token);                }            }        } else {            if(active) {                D("to_remote: transport %p got packet, sending to remote\n", t);                t->write_to_remote(p, t);            } else {                D("to_remote: transport %p ignoring packet while offline\n", t);            }        }        put_apacket(p);    }    // this is necessary to avoid a race condition that occured when a transport closes    // while a client socket is still active.    close_all_sockets(t);    D("to_remote: thread is exiting for transport %p, fd %d\n", t, t->fd);    kick_transport(t);    transport_unref(t);    return 0;}static int transport_registration_send = -1;static int transport_registration_recv = -1;static fdevent transport_registration_fde;#if ADB_HOSTstatic int list_transports_msg(char*  buffer, size_t  bufferlen){    char  head[5];    int   len;    len = list_transports(buffer+4, bufferlen-4);    snprintf(head, sizeof(head), "%04x", len);    memcpy(buffer, head, 4);    len += 4;    return len;}/* this adds support required by the 'track-devices' service. * this is used to send the content of "list_transport" to any * number of client connections that want it through a single * live TCP connection */typedef struct device_tracker  device_tracker;struct device_tracker {    asocket          socket;    int              update_needed;    device_tracker*  next;};/* linked list of all device trackers */static device_tracker*   device_tracker_list;static voiddevice_tracker_remove( device_tracker*  tracker ){    device_tracker**  pnode = &device_tracker_list;    device_tracker*   node  = *pnode;    adb_mutex_lock( &transport_lock );    while (node) {        if (node == tracker) {            *pnode = node->next;            break;        }        pnode = &node->next;        node  = *pnode;    }    adb_mutex_unlock( &transport_lock );}static voiddevice_tracker_close( asocket*  socket ){    device_tracker*  tracker = (device_tracker*) socket;    asocket*         peer    = socket->peer;    D( "device tracker %p removed\n", tracker);    if (peer) {        peer->peer = NULL;        peer->close(peer);    }    device_tracker_remove(tracker);    free(tracker);}static intdevice_tracker_enqueue( asocket*  socket, apacket*  p ){    /* you can't read from a device tracker, close immediately */    put_apacket(p);    device_tracker_close(socket);    return -1;}static intdevice_tracker_send( device_tracker*  tracker,                     const char*      buffer,                     int              len ){    apacket*  p = get_apacket();    asocket*  peer = tracker->socket.peer;    memcpy(p->data, buffer, len);    p->len = len;    return peer->enqueue( peer, p );}static voiddevice_tracker_ready( asocket*  socket ){    device_tracker*  tracker = (device_tracker*) socket;    /* we want to send the device list when the tracker connects    * for the first time, even if no update occured */    if (tracker->update_needed > 0) {        char  buffer[1024];        int   len;        tracker->update_needed = 0;        len = list_transports_msg(buffer, sizeof(buffer));        device_tracker_send(tracker, buffer, len);    }}asocket*create_device_tracker(void){    device_tracker*  tracker = calloc(1,sizeof(*tracker));    if(tracker == 0) fatal("cannot allocate device tracker");    D( "device tracker %p created\n", tracker);    tracker->socket.enqueue = device_tracker_enqueue;    tracker->socket.ready   = device_tracker_ready;    tracker->socket.close   = device_tracker_close;    tracker->update_needed  = 1;    tracker->next       = device_tracker_list;    device_tracker_list = tracker;    return &tracker->socket;}/* call this function each time the transport list has changed */void  update_transports(void){    char             buffer[1024];    int              len;    device_tracker*  tracker;    len = list_transports_msg(buffer, sizeof(buffer));    tracker = device_tracker_list;    while (tracker != NULL) {        device_tracker*  next = tracker->next;        /* note: this may destroy the tracker if the connection is closed */        device_tracker_send(tracker, buffer, len);        tracker = next;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -