adb源码分析2

注册完三个通信函数和连个线程之后,就调用函数install_listener在5037端口进行监听,然后将这个服务添加到链表中(可提供多个服务,这个我不关注),并将输入流重定向到/dev/null,打印 adb start ,向之前打开的管道写端写入 OK\N,通知服务已经启动。进入fdevent_loop,fdevent_process进行处理,这两个函数后面进行分析。回过头来看adb command发送的adb shell命令。

前文讲到子进程execl了adb命令,我们回过头来看看父进程做什么

chartemp[3];

temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';

// wait for the "OK\n" message

adb_close(fd[1]);

intret = adb_read(fd[0], temp, 3);

intsaved_errno = errno;

adb_close(fd[0]);

if(ret < 0) {

fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);

return-1;

}

if(ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {

fprintf(stderr, "ADB server didn't ACK\n" );

return-1;

}



首先父进程关闭了管道写端,准备从管道读端读取数据,当adb-server启动后向写端写入OK\n 读端从阻塞返回,launch_server返回。再次进行__adb_connect 之后调用SendProtocolString 发送 000dhost:features,成功返回文件描述符,adb_connect返回到adb_query,
, 之后读取四个字节长度,然后根据长度读取数据z,这里返回000c也就是12, 后面返回的是shell_v2,cmd
协议版本和命令类型。adb_query返回之后adb_get_feature_set返回, FeatureSet
为 shell_v2,cmd.

之后调用CanUseFeature 对一下版本是否匹配。 最后解析参数调用RemoteShell函数进行处理。

然后发送RemoteShell :shell,v2,TERM=xterm:

之后就是从STDIN中读取数据 写入到5037端口的链接。 这部分看完了,再回来看adb-server收到接到adb的链接请求后如何处理。

if(ev &FDE_READ) {

sockaddr_storagess;

sockaddr* addrp =reinterpret_cast(&ss);

socklen_talen =sizeof(ss);

intfd = adb_socket_accept(_fd,addrp,&alen);

if(fd <0)return;

intrcv_buf_size =CHUNK_SIZE;

adb_setsockopt(fd,SOL_SOCKET,SO_RCVBUF,&rcv_buf_size,sizeof(rcv_buf_size));

asocket* s = create_local_socket(fd);

if(s) {

connect_to_smartsocket(s);

return;

}

adb_close(fd);

}

adb-server在ss_listener_event_func观察可读事件,当链接建立后进入这个函数,讲请求接进来后 重新设置缓冲区。

创建一对asocket一个代表服务端,一个代表客户端(其实是一个从接进来的链接中读取数据,一个写入数据)。

我们来看看怎么处理的,这个流程各种回调,响应式变成,好无聊


create_local_socket 创建客户端asocket 设置回调函数local_socket_enqueue  local_socket_ready local_socket_close 链入local_socket_list

connect_to_smartsocket 创建服务端asocket,设置回调函数smart_socket_enqueue smart_socket_ready  smart_socket_close,设置local和smatrserver互为对端。

下面称服务端asocket和客户端socket分别为local_asocket,server_asocket,

最后执行local_asocket.ready(local_asocket),

static voidlocal_socket_ready(asocket* s) {

/* far side is ready for data, pay attention to

readable events */

fdevent_add(&s->fde,FDE_READ);

}


其实就是观察这个socket可写状态(可写回调local_socket_event_func),因为客户端马上写了个000dhost:features(前边是长度,后边是命令)。所以该函数会马上回调。

这时候关注读事件部分

if(ev &FDE_READ) {

这时候还没有设置transport 当前的max_payload= 256*1024,从客户端套接字读取数据到apacket->data,执行server_asocket.enqueue
(server_asocket,p),注意这里p存了从套接字中读取的数据,server_asocket.enqueue函数就是smart_socket_enqueue函数,可以猜测smart_socket_enqueue是写入数据到usb,然后返回数据后写出到fd,这里稍后分析,再看smart_socket_enqueue 返回后,就卸载了可读事件的回调,因为之后要写入数据了。


现在分析smart_socket_enqueue函数:获取数据前四位长度。解析命令,之后对不同命令进行处理,这里的命令是host:features,这里将

type设置成kTransportAny,server设置成features,调用handle_host_request处理请求,在adb.cpp中,


if(!strncmp(service, "transport", strlen("transport"))) {

TransportType type = kTransportAny;

atransport* t = acquire_one_transport(type, serial,nullptr, &error);
。。。
s->transport = t;
SendOkay(reply_fd);

通过acquire_one_transport获取一个transport, 从transport_list中找出合适的atransport,根据类型(还记得我们之前打开的套接字对用于和usb通信的那套通信框架吗,atransport就描述了该结构)对于不同的类型还有写限制。 返回到handle_host_request
,获取了atransport后,设置server_asocke的transport为 (选定通信通道),调用SendOkay(reply_fd);这里的reply_fd就是链接如5037端口的套接字,SendOkay就是向套接字中写入OKAY.

这里我们不在关心协议细节的东西,我们来查看如何通信。假如命令是transport直接返回,由此可见transport是用于找到通信介质。这种命令不需要写入usb,就直接返回了。再看features命令,调用SendOkay(reply_fd, FeatureSetToString(t->features()));函数。

static intSendOkay(intfd,conststd::string& s) {

SendOkay(fd);

SendProtocolString(fd, s);

return0;

}

除了发送ok以为,还发送了 SendProtocolString 发送协议信息。到这里还没有看到如何和adbd通信。 整个流程还没有跑通,

关键点就在transport初始化的时候,会初始化一些信息 feure也是其中初始化的数据。 所以features 也是不需要和手机通信的,处理完成这些不用和手机进行通信的请求后就是handle_forward_request 转发请求, 也是获取相应的atransport 然后install_listeren,

以RemoteShell :shell,v2,TERM=xterm:这条命令为例子 第一个参数是RemoteShell,第二个参数是shell,v2,TERM=xterm: 三个参数是transport

创建新的 alistener

connect_to=shell,v2,TERM=xterm:
name = RemoteShell









最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容