天天看点

ADB push 文件通讯过程的host端分析

http://blog.chinaunix.net/uid-20514606-id-375756.html

adb push 文件时host端(server+client)通讯的流程,分析如下:

绿色表示Cleint端

兰色表示Server端                                                                            

红色表示Device端

------------------------------------------------------------------------------

(1) (server)    

     ( socket_loopback_server(tcp:5037 loopback server 监听client连接)

------------------------------------------------------------------------------

(2)                                         (目前为client)

                             ( int fd = _adb_connect(service); )

                          执行socket_loopback_client 去连接server

------------------------------------------------------------------------------

 (3) (server)   

     如果有client 连接交由ss_listener_event_func 处理

    adb_socket_accept 接受连接后进行如下处理:

    * 设置socket buff 大小

    * 用create_local_socket 创建asocket 对象

          并初始化enqueue,ready,close  函数指针local_socket_xxx

          设置asocket 的id, 设置asocket 的fd 为accpeted socket fd 

                                                                    (使用该fd 与client 通讯)

    * 设置epoll 等待该accepted socket fd   上FDE READ,WRITE事件

           处理函数为local_socket_event_func 

           (注意这时并为设置等待FDE EVENT !!!)

    * 用connect_to_smartsocket 创建一个smart asocket

          ( 注意是smart 不是remote!)

          asocket id 为0  (这是个细节)

          并设置enqueue ,ready ,close 函数为smart_socket_xxx

          设置local ,smart asocket 互为对方peer

          调用下local socket ready,这样local_socket_event_func

             就可以等待到client 发数据过来的fde read event了

------------------------------------------------------------------------------

(4)                          (client)

                             (_adb_connect("sync:"))=>

                             * switch_socket_transport 发送:

                               'xxxx'(msglen)+ 'host:transport-any'

                             * 然后readx 读socket_loopback_client

                                返回的fd  来等待server 应答

------------------------------------------------------------------------------                                                                          

(5) (server)   

      local_socket_event_func 的 fde read  分支读到client 发来的

      'xxxx'(msglen)+ 'host:transport-any'  ,调用

      smart_socket_enqueue (不是remot socket 入队)

        *  收完msg len 指定长度的msg

        * 开始handle_host_request(service='transport-any'

                                  , ttype=kTransportAny

                                  , serial=nll

                                  , s->peer->fd  local socekt 's fd

                                  , s smart asocket 

                    通过acquire_one_transport(CS_ANY, type=kTransportAny,serial,error_string);

                    去从transport_list 上获得一个transport 

                       transport_list  是在 usb_init  =>device_poll_thread  中发现usb device

                       插入,或者local_init 通过client_socket_thread 通过ip+port 连上device 后

                       通过register_xxx_transport ,xxx指 usb 或socket,注册时link 到list上的

                       所以注意如果想用tcp 连接时  getenv("ADBHOST") ,要设置ip 地址

                       不过现在仍然假定使用usb transport 并且device 已经插入成功

                       获得一个atransport  成功后,给client 发OKAY

                       并把smart asocket 的atransport 设置为获得的atransport 

         *  handle_host_request 返回时判断service 中用'transport' 字样就

            return 0; 退出enqueue     

-------------------------------------------------------------------------------------

(6)                    (client)

                       等到server 发来的okay ,开始通过

                       loopback client socket fd 发

                       'xxxx'(len)+ 'sync:' 

-------------------------------------------------------------------------------------

(7) (server)   

local_socket_event_func 中如果enqueue 返回>0 才会

delete FDE_READ,前面(5)楼enqueue 退出为return 0,

所以条件不满足, 仍然可以触发

又到了local_socket_event_func 的 fde read  分支!!!

收到'xxxx'(msglen)+ 'sync:'  调用

smart_socket_enqueue 入队

          由于msg 中没有任何host 字样就直接去设置

          local asocket 的ready ,改为local_socket_ready_notify,

                  主要为回应client OKAY 做个过度,所有又设回

                  local_socket_ready (notify 做了下二传手的作用)

          close 设为local_socket_close_notify 重设为local_socket_close_notify

                  和上面一样主要是回应 client  "closed",然后设回

          s->peer->peer = 0;  将local asocket 的peer端由smart socket 改为0       

             (local asocket 与smart socket 现在断开了)

          connect_to_remote(smart ascoket,'sync:'); 去向目前还挂在

          smart asocket 上的usb transport 发6大message 之一个的

          A_OPEN 去open sync service

          (注意smart asocket 获得见5楼倒数第3行,虽然和loc sock断开了,不过还有利用价值) 

-------------------------------------------------------------------------------------

(8) 

(device)

device 收到open sycn 后打开sync service 

然后给host 端发A_OKAY

(具体见ADB push 文件通讯包的device端分析 )

-------------------------------------------------------------------------------------

(9)

(server)

server 端 收到A_OKAY 后handle_packet  处理A_OKAY

(具体ADB push 文件通讯包的device端分析)

因为前面local asocket 与smart ascoket 断开时设置

* s->peer->peer = 0 ;  (peer的peer 一定不要昏,见前面(7)楼解释)

* 所以create_remote_socket(device asocket id, usb atransport->transport register时获得)

                 * 设置 新创建的remote asocket 的enqueue,ready,close ,disconnet 等func pt

* 将刚才和smart asocket 断开的local asocket 连到remote asocket

      (就是这句s->peer->peer = s;)

*  调ready   (那个ready ???  ;)  )

    local_socket_ready_notify ,这个ready 2传下到

    local_socket_ready(close)  ,然后给client 回个OKAY ,  

    然后再s->ready(s); (那个ready???)

    local_sokcet_ready ,设置fde_read, (这句很关键!!!)

    回头看下client ,它发完sync  还挂着adb_status 等OKAY,

    现在轮到client 了

-------------------------------------------------------------------------------------    

(10)                              (目前为client)   

                                    adb connet sync:成功返回loopback

                                    client socket fd 后开始发文件了

                                    sync_send(fd=> loop back client sfd

                                          *  发ID_SEND + filename +file mode 's len

                                          *  write_data_file

                                                 发ID_DATA + size + file data (最大64K)

                                          (这里和下面是交叉执行)       

-------------------------------------------------------------------------------------

(11)

(server)

(9)楼提到的关键句s->ready(s) 起作用了

加上client 的write ,激发了

local_socket_event_func 去处理分支FDE_READ

     * 读loopbake server socket  fd 获得client 发来的数据

     * s->peer->enqueue =>现在enqueue 是remote 了, 不是smart 

        这就是前面local, smart 断开时做的

        (见上面处理A_OKAY 时create_remote_socket 做的)

        enqueue => remote_socket_enqueue   

                          向device 发A_WRTE (通过usb transport 

                          send_packet出去)

local_socket_event_func => FDE_READ => adb_read(fd, x, avail) 

的avail 是4096,所以实际usb 上一次write max 4096

-------------------------------------------------------------------------------------

(12)

(device)

由于ADB push 文件通讯包的device 端分析中已经

讲过device 端,所以省略

但是每次device 处理A_write 后都回A_OKAY

-------------------------------------------------------------------------------------

(server)

又回到server 端处理A_OKAY,和上面(9)楼一样处理

一直又处理到(12)楼

直到文件内容发完

-------------------------------------------------------------------------------------

(13)                              (目前为client)     

                                    发ID_DONE + mtime

                                    然后等server 回OKAY

-------------------------------------------------------------------------------------                                    

(目前为server)

这部分和(11)楼处理过程一样,因为省略分析devcie 端

但也是由s->ready  + client 写sfd 激发local_socket_event_func 开始的

最后server 通过local_socket_ready_notify 回应 client OKAY

-------------------------------------------------------------------------------------

(14)                             (client)    

                                   收到OKAY  

                                   sync_quit =>

                                   发ID_QUIT

-------------------------------------------------------------------------------------

(15)

(server)

已经基本没client 的事情了

server local_socket_event_func 上最后一 次 去处理分支FDE_READ

 r = adb_read(fd, x, avail);  r 返回0

 is_eof成立

执行 s->close(s); =>local_socket_close_notify

 直接贴代码

  1. static void local_socket_close_notify(asocket *s)
  2. {
  3.     s->ready = local_socket_ready;
  4.     s->close = local_socket_close;
  5.     sendfailmsg(s->fd, "closed");
  6.     s->close(s); ===> local_socket_ready 发A_CLSE 
  7. }

 -------------------------------------------------------------------------------------

(16)

如device 端分析中最后收到A_CLSE

结束

其他

server 端对非host 命令的转发类似与一个单刀双掷开关

                      fd(loopback sfd) <---------------->  (client)

                             |                                                                     

                            fde (local_socket_event_func)

                         (2) |(1)

  (device handle)             \                     (server handle)  

 (remote enqueue)  <------>    <----------------->(smart enqueue)

 开始连着client ,接收到非host 命令,发A_OPEN 打开device service 后

 开关连到(2)一头,以后enqueue 就是remote 了,就发给了device

  两路 :一路client 经过(1) 到server handle

       另一路client 经过(2)到device handle