ALLJOYN源码阅读笔记

总体来说,代码分2个部分:后台的DAEMON和暴露给上层的接口。 其中DAEMON我们可以看成是一条后台BUS,负责与应用通信和管理远程连接;  我们可以用暴露出来的上层接口编写Server或Client应用挂到后台BUS上并通信。

 

熟悉对象几个重要的类和对象:Busattachment  Bus Internal  BusController   BusObject ALLJoynObj  DbusObj ProxyBusObject  Router  DaemonRouter ClientRouter  Transport  TransportList DaemonTransport ClientTransport BusEndpointLocalEndpoint  RemoteEndpoint  TCPEndpoint BTEndpoint  DaemonEndpoint     ClientEndpoint  InterfaceDescription  

 

 

DAEMON和上层接口(就是两个Busattachment对象之间的通信)

最TOP的对象是Busattachment,我们看注释:BusAttachment isthe top-level object responsible for connecting to and optionally managing amessage bus. 这个BusAttachment非常重要,它有两个构造函数,即作DAEMON和上层的接口。 作DAEMON时我们称为daemonconstructor,体现注释里面connect 和 manage; 作应用接口时我们称为clientconstructor,只体现connect.

 

在DAEMON部分,TOP的两个对象是BusController   和继承于Busattachment的BUS。其中BUS下面有BusEndpoint来负责数据传输。

                                             LocalEndpoint

                                                              

BUS(Busattachment)-----Internal-----DaemonRouter                                     DaemonEndpoint

RemopeEndpoint   TCPEndpoint

                                                               BTEndpoint  

                                                                              VirtualEndpoint

setbuscontroller

                 

                &Bus

 

BusController     Dbusobj(BusObject)---components---InterfaceDescription,MethodContext

 

                Alljoynobj(BusObject)---components---InterfaceDescription,MethodContext

 

                                                                                                                             

 

在上层接口部分,只有Busattachment

Busattachment-----Internal-----ClientRouter---  LocalEndpoint

                                                                ClientEndpoint

DAEMON和上层接口通过Endpoint(基于QCC_AF_UNIXSocket) 通信,下面我们看

LocalEndpoint,

                          MethodTable

 

LocalEndpoint    ProxyBusObject* dbusObj

 

                          ProxyBusObject*alljoynObj

在DAEMON和上层接口都有自己的LocalEndpoint,上层接口访问ProxyBusObject*dbusObj

中的代理函数,会由CallMsg-MarshalMessage-PushMessage组包并通过ClientEndpoint发送给DAEMON的DaemonEndpoint。

 

DAEMON则由HandleMethodCall来处理,处理函数在MethodTable中。 (上面提到的Dbusobj中的各个Method等会在registerbusobject时install到LocalEndpoint的MethodTable)

 

同样上层接口可能通过RemopeEndpoint - PushMessage  到远端的平台上的DAEMON。

 

DAEMON初始化流程

从JNI的DaemonMain函数开始,

DaemonMain

                          DaemonConfig

daemon

                   TransportFactoryContainer

 


                                                                        transportList

Bus ajBus();构造Busattachment-Internal-    localEndpoint

                                        ……

                                                    

DBus::CreateInterfaces  ifaceDescriptions 

alljoyn::CreateInterfaces

 

 

BusControrller ajBusController();构造BusControrller-dbusObj

                                                                                      -alljoynObj

BusControrller.init

      

       dbusObj.Init    add InterfaceDescription的handle到components

                     bus.RegisterBusObject

                            LocalEndpoint::RegisterBusObject

                    LocalEndpoint::OnBusConnected      AddAlarm

              DeferredCallbacks::AlarmTriggered                 trigger

                       DBusObj::ObjectRegistered

                                   busController->ObjectRegistered

                                          AllJoynObj::Init  add InterfaceDescription

                                                

dispatcher.Start

                                   ProxyBusObject* dbusObj(proxy Interface)

ProxyBusObject*alljoynObj(proxy Interface)

 

                                                     

   BusAttachment::Start                                     LocalEndpoint::Start

                                                     DaemonTransport::Start

busInternal->transportList.Start  TCPTransport::Start

BTTransport::Start

                                                                                  router.RegisterEndpoint                  

                               

                               Thread::Start->TcpTransport::run->while/socket.accept

bus.StartListen

             

   TCPTransport::StartListen              alert

   DaemonTransport::StartListen  ("unix:abstract=alljoyn":listen本地上层接口Busattachment)

BTTransport::StartListen

  

上层接口的Busattachment

Busattachment的client初始化比较简单。

newBusAttachment

Busattachment构造Busattachment-Internal- ClientTransport

 

BusAttachment::Start

              busInternal->transportList.Start

                    

LocalEndpoint::Start ProxyBusObject* dbusObj      -RemoteEndpoint*b2bEp

                               ProxyBusObject* alljoynObj

BusAttachment::Connect

            ClientTransport::Connect

                   Socket(QCC_AF_UNIX,QCC_SOCK_STREAM, sockFd)

                   m_endpoint->Start->RemoteEndpoint::Start-> ClientRouter::RegisterEndpoint

 

关于BLUETOOTH的ENDPOINT的一点说明

前面讲DAEMON和应用都是一个BUS或Busattachment,但是如果加入BT ENDPOINT时,和BLUEZ通信,所以DAEMON中包含一个BT的Busattachmentclient, 见BTAccessor::BTAccessor中bzBus("BlueZTransport")。

另外,DAEMON要和BLUEZ建立联系,所以DAEMON应包含BLUEZ的权限,setuid(BLUETOOTH_UID);

 

 

代码目录

我们涉及到的代码主要在/alljoyn/core/src     /alljoyn/core/daemon     /common/src     /common/os/posix这几个目录下面,其中/common/os/posix 是基于我们平台的定时器Timer,互斥Mutex,线程Thread ,socket, event;   /common/src主要是XML配置解析, LOG设置 ,string, 以及对/common/os/posix中的Thread ,socket部分封装;

/alljoyn/core/daemo/和/alljoyn/core/src就是协议的主要部分,其中上层接口的Busattachment对象只涉及/alljoyn/core/src的代码,而DAEMON涉及/alljoyn/core/src和/alljoyn/core/daemon两个部分的代码。

 

我们看/alljoyn/core/src下面的主要文件BusAttachment.cc  ProxyBusObject.cc  LocalTransport.cc  BusObject.cc Message.cc  Message_Parse.cc  Message_Gen.cc  MsgArg.cc   SignalTable.cc  BusEndpoint.cc  ClientRouter.cc   ClientTransport.cc        RemoteEndpoint.cc  Transport.cc   TransportList.cc  Auth***.cc

BusAttachment.cc是总的对象入口,上层接口主要调用这里面的接口;

BusObject.cc  ProxyBusObject.cc远程的代理,从ProxyBusObject访问远程接口。

Message.cc  Message_Parse.cc  Message_Gen.cc MsgArg.cc是两个ENDPOINT之间的消息数据的打包解包。

其他的文件包含Transport或Endpoint字符信息的函数都是负责物理数据包的发送接收。

Auth打头的文件是安全验证接口。

 

/alljoyn/core/daemo/主要是DAEMON特有的接口。AllJoynObj.cc  Bus.cc BusController.cc

DaemonRouter.cc  DaemonTransport.cc  DBusObj.cc NameTable.cc  TCPTransport.cc VirtualEndpoint.cc  daemon-main.cc  Packet.cc BT***.cc  P2P***.cc

我们BusAttachment  DAEMON比BusAttachment  Client看多出来的就是BusController和DBusObj, AllJoynObj。Bus.cc是BusAttachment  做DAEMON时的实现,AllJoynObj.cc和DBusObj.cc是BUS提供的服务的具体哪些函数的实现。

daemon-main.cc是DAEMON的初始化入口,Packet.cc是ENDPOINT的数据打包。

DaemonTransport.cc是和上层接口BusAttachment  Client的通信ENDPOINT。

TCPTransport.cc是和远程平台上DAEMON的通信ENDPOINT。WIFI基于此ENDPOINT。

BT和WIFI DIRECT ENDPOINT的函数较多。

当然DAEMON包括/alljoyn/core/src下面的函数,主要功能也是和上面一致的。

 

/alljoyn/core/daemo/ns这下面的几个函数主要负责物理上远程DAEMON的UDP探测。

 

一次调用流程(上层应用与DAEMON的通信)

上层应用和DAEMON之间需要通信,下面我们看从上层接口和DAEMON通过SOCKET的一次完整调用流程,比如从BusAttachment::RequestName到DBusobj里面的函数原型RequestName:

 

CLIENT:       BusAttachment::RequestName  -> dbusObj.MethodCall ->

bus->GetInternal().GetRouter().PushMessage ->ClientRouter::PushMessage -> nonLocalEndpoint->PushMessage -> RemoteEndpoint::PushMessage  -> txQueue.push_front

------(Thread switch)>  RemoteEndpoint::TxThread::Run ->msg->Deliver -> sink.PushBytes -> SocketStream::PushBytes-> Send(套接字接口)

 

DAEMON:        Recv -> SocketStream::PullBytes ->source.PullBytes  -> msg->Unmarshal->RemoteEndpoint::RxThread::Run  ->router.PushMessage  ->DaemonRouter::PushMessage

->LocalEndpoint::PushMessage->LocalEndpoint::DoPushMessage ->LocalEndpoint::HandleMethodCall ->entry->object->CallMethodHandler->DBusObj::RequestName

 

 

DISCOVERY  (DAEMON与DAEMON通信)

不光应用与DAEMON之间需要通信,DAEMON与远程的DAEMON也需要通信,下面我们看这个DAEMON之间的通信,在应用调用BusAttachment::FindAdvertisedName时会查找远程DAEMON上的服务(我们假设应用分别在两台不同宿主机上)。首先从应用的:FindAdvertisedName到DAEMON内的AllJoynObj::FindAdvertisedName同上述的应用与DAEMON通信流程一样,不再叙述。接着DAEMON的AllJoynObj ::FindAdvertisedName会查找内部transList.GetTransport,依次调用EnableDiscovery,以下都以TCP为例。

AllJoynObj::FindAdvertisedName  ->  trans->EnableDiscovery  -> TCPTransport::EnableDiscovery  -> TCPTransport::QueueEnableDiscovery-> m_listenRequests.push(listenRequest)------(aler:thread switch)> TCPTransport::RunListenMachine->TCPTransport::EnableDiscoveryInstance

                     DoStartListen:createsocket and listen port 9955

              IpNameService::FindAdvertisedName-> IpNameServiceImpl::QueueProtocolMessage--

---alert->IpNameServiceImpl::Run -> LazyUpdateInterfaces()  -> Socket(这里是UDP,有类似IFCONFIG命令,发送到远程9956端口,探测)

IpNameServiceImpl::SendOutboundMessages-> SendProtocolMessage -> SendTo(用上面的UDP port9956发送探测)

 

RecvFrom -> HandleProtocolMessage-> TCPTransport::FoundCallback::Found

 

注:在应用调用FindAdvertisedName或AdvertisedName时都会有这个UDP的探测,并且这个过程在底层是一直定时轮休的,这样的一个linux网络机制不难理解。 

 

AllJoynObj::JoinSessionThread::RunJoin  -> trans->Connect   ->  TCPTransport::Connect(new一个TCP  Socket ,并connect到远程的Port9955)   -> new TCPEndpoint -> DaemonRouter::RegisterEndpoint->

                                                                AllJoynObj::AddBusToBusEndpoint->AddVirtualEndpoint

       ExchangeNames (注:应该是A Connect B,BConnect C,这里会主动让B和C建立联系)

AllJoynObj::SendAttachSession  -> ProxyBusObject::SetB2BEndpoint

 

建立通信的两个步骤就是Advertised和Join,TCP连接建立之后,会AddVirtualEndpoint,在应用发送数据时,下面的ROUTER会由VirtualEndpoint回找到TCP。

两个应用之间的完整数据路由

Client  APP :

ProxyBusObject remoteObj; 

remoteObj.MethodCall  -> bus->GetInternal().GetRouter().PushMessage 

-> ClientRouter::PushMessage -> send (UNIX file system socket)

 

Client DAEMON: 

recv  -> RxThread::Run ->DaemonRouter::PushMessage -> SendThroughEndpoint ->VirtualEndpoint::PushMessage  -> send(WIFIexample)

      

Service  DAEMON:

recv  -> RxThread::Run ->DaemonRouter::PushMessage  ->SendThroughEndpoint ->

RemoteEndpoint::PushMessage ->send(UNIX file system socket)

 

Service  APP:

Recv ---do object method----send(UNIX file system socket)

 

Service  DAEMON:

Recv -> RemoteEndpoint::RxThread::Run ->DaemonRouter::PushMessage -> SendThroughEndpoint -> VirtualEndpoint::PushMessage->  send(WIFI example)

 

Client DAEMON:

recv  -> RxThread::Run ->DaemonRouter::PushMessage  ->SendThroughEndpoint ->

RemoteEndpoint::PushMessage ->send(UNIX file system socket)

 

Client  APP :

Recv ---  the registered ReplyHandler or MethodCall return;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值