分类: LINUX
2011-06-17 12:48:55
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
直接贴代码
-------------------------------------------------------------------------------------
(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