`
donsun
  • 浏览: 29976 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Symbian移动端SSL改造方案调研——基于主线程创建活动对象与SSL服务器交互模型

阅读更多


Symbian移动端SSL改造方案调研

——基于主线程创建活动对象与SSL服务器交互模型

 

1    目录
1    目录    2
2    概述    3
2.1    名词    3
2.2    备选方案    3
3    可行性分析    4
3.1    活动对象与活动规划器    4
3.1.1    动机    5
3.1.2    活动对象    5
3.1.3    活动规划器    6
4    解决方案    6
4.1    概述    7
4.1.1    活动对象管理SSL事务模型    8
4.1.2    图解    9
4.2    详细设计    9
4.2.1    类图    10
4.2.2    顺序图    13
4.2.3    交互过程详解    14
4.3    小结    17
5    附录资源    17
5.1    UML设计Jude文件    17
6    参考资料    17

 

2    概述

Symbian便携端应用基于安全方面的考虑,实施通信协议层安全增强型升级,具体方案的确定上受到移动电话端网络连接方式提供商及手机操作系统提供商的开发接口(API)方面的一些限制与模式上的兼容问题(主要是线程中打开SSL通信失败问题),考虑到兼容原有模式的基础上制定最佳解决方案。
该项目移动设备端采用Symbian 7.0,UIQ界面开发。

2.1    名词

  • Symbian:

Symbian也被称作EPOC系统,这是最早由Psion公司开发的一个专门应用于手机等移动设备的操作系统。目前由诺基亚、爱立信、松下、三星、索尼爱立信和西门子等手机巨头共同拥护,占据了智能手机操作系统市场70%以上的份额,目前的最高版本为Symbian 9.0

  • 活动对象(Active Object):

Symbian中实现非线程非抢占式多任务“并行”处理的一种机制,活动对象部署于与当前线程绑定的活动规划器(Active Scheduler)中,活动规划其负责维护部署于其中的所有活动对象,使之“并行”,并实现异步请求的相应,Symbian OS 基于微内核结构。各种服务的使用都通过异步接口。活动对象和活动规划器针对异步服务的使用提供了方便的框架:某个活动对象发起一些异步请求,并处理该请求。有一个变量用于指出服务器何时已完成该请求。活动规划器追踪那些活动对象,当其发现有一 个请求已完成时,它会调用所分配的活动对象的RunL()方法,而后者会去处理该服务器响应。

  • UIQ:

UIQ Series:UIQ Series操作平台的特性是它的多媒体性,功能全面。UIQ界面上可支持手写操作,不过切换和关闭任务比较麻烦。UIQ Series是Symbian OS 的系统架构上,专门为高阶的多媒体手机而设计,使用起来非常类似 PDA 操作,不过目前只有少数的机种采用 UIQ 系统。

2.2    备选方案

  1. 主线程启动子线程子线程直接创建SSL连接,访问服务器
  2. 主线程启动活动对象连接SSL服务器
  3. 主线程启动子线程,子线程启动活动对象连接SSL服务器
  4. 主线程启动活动对象获得SSL连接传递给子线程连接服务器

本文将针对方案B做具体可行性分析及实施细则描述。

3    可行性分析

基于Symbian7.0 UIQ界面中SSL通讯已经封装完整的CSecureSocket类的考虑,并且相关实例还算比较全面的前提下,为了更方便可靠的实现SSL层通讯,决定ABCD四种方案均建立与CsecureSocket的类库基础之上,但同时引入的问题也非常明显,似乎CsecureSocket是专门为活动对象而设计的,Symbian官方提供的实例程序也是建立在活动对象封装的基础之上的,脱离活动对象以后,沿用现有便携端非加密的连接方式中的方法在处理SSL协议握手或异步通信时都会出现问题。
由于SSL通信层的升级改造的基础是旧版本已经实现的功能,即主线程启动子线程,子线程创建Socket连接,处理异步网络访问。显而易见,基于线程的方式将原来的系统改造为SSL传输层的改动是最小的,如图:1-1


 如上图描述的方案,改动量是最小的,但是Symbian 7.0封装过的CSecureSocket 类放在线程中使用时,没有办法正常的通信。只有在活动对象中才能使用,正如Symbian官方提供的实例程序一样,也许是Symbian官方一直力推活动对象(Active)的原因吧。
综上原因导致了SSL改造方案必然涉及到对活动对象内部机制的了解,以及如何在主线程中与活动对象进行交互通信,子线程如何使用活动对象以及子线程与活动对象之间的通信等问题。

3.1    活动对象与活动规划器

活动对象和一个活动规划器共同提供了非抢先式多任务,可用于替代 Symbian OS 中的多线程。使用活动对象可获得的好处是:与使用线程相比较,它编程简洁,且CPU的效率更高,表现上看去与多线程效果相当。

3.1.1    动机

事件驱动环境中的一些任务(如各种 UI 应用中的一些任务)处理来自系统的一些事件。程序代码往往调用某个异步方法,它处理一个请求。当该请求完成之后,客户端得到提示,处理结果,且很有可能发起一个新的请求。
如果用一些线程来实现某些任务,针对每一个事件源都必须有一个线程。例如,某个线程可处理键按下。当按下某个键后,它可能会去请求服务器发出一个提示。然后该线程就会被挂
起,直到服务器唤醒该客户端线程去处理那次按键。同时,可能还存在着另一个线程,它以 某个异步(或阻断同步)方法以某种类似方式从 socket 读取数据。
各种活动对象提供了事件处理的便捷方式。当发出一个异步请求并当服务器完成该请求时,活动对象的内部属性得到了传递,以取得响应代码。活动规划器关注该活动对象的运行,及当该请求在服务器端得到完成后对结果的处理。
有很多理由解释在 Symbian OS 中为什么用活动对象,而不是线程,来处理各种事件。例 如:

 

  • 线程间的通信比活动对象间的通信缓慢且困难些(活动对象在同一个线程中运行,因此它们不需要任何特殊方法来共享数据)。
  • 线程间的场景切换消耗CPU周期,从而使其性能表现下降。活动对象并不像线程那样会被中断,因此并不需要在各个切换间储存并恢复CPU及内存映射单元(Memory Mapping Unit,MMU)的状态。这一点在移动终端资源本就紧张的现状下尤为重要。
  • 许多资源不能在线程间共享。由于活动对象用一个线程运行,它们可以共享资源。
  • 在线程间访问内存或访问其他共享内存通常需要对同步更新提供保护。这由信号量(semaphores)完成,这可能导致代码的复杂化,并造成性能下降。活动对象不用担心同步问题,因为它们是以某种非抢先方式调度的。

当然,活动对象并不是万能的,在某些应用中也存在很多的问题,例如:

  • 活动对象不是多线程,不可能实现真正的并行处理。
  • 活动规划器的最小轮询执行指令片断是方法级的,设计不当会导致RunL过于复杂。
  • 不适合管理异步事务同步,需要写很多的Switch / case 增加维护负担。
  • 子线程启动活动对象需要显式安装和启动活动规划器,子线程在启动活动规划器后控制权进入活动规划器,直至活动规划器推出才可以恢复。

3.1.2    活动对象

Symbian OS 基于微内核结构。各种服务的使用都通过异步接口。活动对象和活动规划器针对异步服务的使用提供了方便的框架:某个活动对象发起一些异步请求,并处理该请求。有一个变量用于指出服务器何时已完成该请求。活动规划器追踪那些活动对象,当其发现有一个请求已完成时,它会调用所分配的活动对象的RunL()方法,而后者会去处理该服务器响应。

3.1.3    活动规划器

Symbian OS 中的每个进程都有一个线程,即主线程。这个主线程为这个进程创建一些额外的线程。如果用到了活动对象,就必须为这个线程实例化活动规划器,然后启动它以便对活动对象进行调度。Symbian OS 的用户界面应用就是具有一个主线程的进程。应用框架为这个主线程安装一个活动对象。在活动规划器中还有许多的活动对象,他们处理应用事件(键盘按压和屏幕更新请求)并实现对应用程序员可能重置了的一些方法的回调。程序员可以使用由应用框架所提供的默认的活动规划器。
然而,如果程序员创建了自己的某个线程,默认情况下并不存在一个针对该线程的活动规划器。可执行程序(.exe)具有一个主线程,如各种应用一样,但是该线程并没有任何的活动规划器。要在这样的线程中使用活动对象,程序员必须安装活动规划器,运行它,然后删除它。

3.1.3.1    使用自己的活动规划器

要在某个不具备活动规划器的线程中使用一些活动对象,程序员必须:

  1. 用方法 CActiveScheduler::Install()为那个线程创建并安装一个活动规划器。
  2. 创建活动对象并用方法 CActiveScheduler::Add()将它们添加到那个活动规划器中。
  3. 用这些活动对象发起一个或多个异步请求。
  4. 用方法 CActiveScheduler::Start()启动那个活动规划器。

该活动规划器的方法start()在其停止方法被调用前并不会返回。这就是为何在这个规划器中必须有一些活动对象来处理某些任务的原因。当这些任务得到处理之后,一个活动对象必须以方法 CActiveScheduler::Stop()停止该活动规划器。 然后早先被调用的该活动规划器方法CActiveScheduler::Start()返回。在启动活动规划器之前其中必须有一些发出了一个异步请求的活动对象。这是因为:这个活动规划器只运行这样一些活动对象,这些活动对象的服务供应商已经提示其完成。当该活动规划器被启动时,如果并不存在任何等待中的未完成请求,这个线程将被永远挂起。

4    解决方案

活动对象进行SSL异步处理,是Symbian提供商所推荐的方式,也是最为稳妥的改造方案,考虑到系统升级对原有系统架构模式的改动最小化的因素,尝试性的提出SSL通信方式在活动对象(Active Object)内的封装方案,即构建一个通用的活动对象,这个活动对象被主线程创建,活动对象的功能仅仅是SSL通信,从创建到握手,请求,接收直至关闭,全由这个活动对象以异步的方式处理。该过程中通过回调方法的方式传递给主“线程”(这里采用这个提法,用以区分活动对象以外的处理过程)通信状态,控制界面元素(UI)更新,并且由通用的回调方法获取连接握手完成后的各个步骤详细业务参数,实现在活动对象内仅仅封装通信方式逻辑过过程,业务流程及逻辑在活动对象以外,通过回到方法的方式控制活动对象行为。

4.1    概述

活动对象处理异步事务的优势就是没有线程级别的资源开销,利用这个优势,我们构建了如下解决方案,如图:1-2

4.1.1    活动对象管理SSL事务模型



 4.1.2    图解

A.   等待
该过程界面会出现暂短的无相应,原因在于活动对象执行耗时操作
B.   活动对象
封装以后的活动对象,用于通过SSL访问安全连接,异步发送接受数据,业务逻辑无关
C. 调用过程
主线线程调用活动对象的过程,进入活动对象任务循环
D. 主线程
用户应用程序主线程,封装业务处理方法及与活动对象交互的回调方法,控制活动对象生命周期
E. 子过程
活动对象内每一个独立的子过程,包括初始化和销毁关闭连接等操作
F. 反馈状态
接受数据过程中的状态反馈给UI的过程,主要是下载/上载数据进度情况
G. 细节描述
功能实施细节描述
H. 迭代过程
主要指基于SSL的数据异步发送接受过程,这个过程按照活动对象以外的主线程的业务情况重复执行,直至完成
I. 回调过程
活动对象用于获取执行状态与控制的途径,以及返回执行结果更新UI的方法

4.2    详细设计

首先需要封装一个操作CSecureSocket类的活动对象,用于通过SSL与服务器异步通信,在通信的过程中,通过注册回调函数的方式与主线程的业务通信,主线程的业务通信功能同时可以控制活动对象的生命周期,这样我们就需要封装如下两个类:

  • CSecEngine
  • CAppUIBase
  • Task
  • CAppUILogin

4.2.1    类图


 4.2.1.1     类功能描述

通过CSecEngine,CAppUIBase,CTask,CAppUILogin类的协作演了一个最基本的用户登录操作的实现方式,其主要交互功能由CSecEngine类回调(CallBack)CAppUIBase类的实现类的接口的方式呈现,CAppUILogin是CAppUIBase的继承类,在实现了父类的虚方法后,框架在初始化该类的同时会将指向CAppUILogin实例的指针引用向基类溯型后注册入CSecEngine类中,以处理异步触发的事件回调已经任务交互和SSL访问事务管理。

4.2.1.1.1    CSecEngine

这是一个封装后的活动对象,派生自CActive,用于集成通用的SSL传输层异步事务处理,采用这样的通用传输层的设计是为了更好的剥离开业务对象与业务逻辑同网络传输的耦合关系。
该类封装了最基本的SSL传输的异步操作,并保存有当前用户界面UI的指针引用,即指向CAppUIBase类型的指针,从而在活动对象中异步的更新UI,触发事件以及主线程对活动对象行为的控制,并可随时中止当前活动。

4.2.1.1.2    CAppUIBase

所有UI对象的基类型,主要用于定义与活动对象CSecEngine交互的接口,子类要想和活动对象交互并且实现控制活动对象行为的功能就必须实现该类提供的所有抽象函数。

  • CAppUIBase主要接口虚函数定义
序号 方法名称 描述 返回值含义
1 CallBackInitSuccess 当 SSL初始化完成,并且Socket连接创建成功时回调该方法 继续执行=true
用户中止=false
2 CallBackSocketConnectSuccess 当SSL创建成功时,回调该方法 继续执行=true
用户中止=false
3 CallBackHandshakeSuccess 当SSL握手成功时,回调该方法 继续执行=true
用户中止=false
4 CallBackSendSuccess 当发送请求成功时,回调该方法 继续执行=true
用户中止=false
5 CallBackRecving 当SSL请求发送成功时,并且开始接受数据的时候,每一次填充满缓冲区数据后,回调这个方法,此方法会 在接收数据时被调用多次,直至完成。 继续执行=true
用户中止=false
6 CallBackRecvSuccess 当过程5中的数据反复接受完成以后,回调该方法。 继续执行=true
用户中止=false
7 CallBackCloseSuccess 当SSL成功关闭后回调该方法 继续执行=true
用户中止=false
8 CallBackGetNextTask 这是一个重要的方法,当第一个请求发送完成,即步骤4,5,6依次完成以后,会调用该回调方法,询问 UI(封装业务逻辑层)是否有任务需要继续执行,如果有,CallBackGetNextTask可以通过返回值的方式传递给CSecEngine下一个 任务具体描述CTask *,CTask的具体描述,参见CTask描述章节。
CSecEngine会在CallBackGetNextTask返回值为NULL的时候中止该活动对象,并且异步的关闭SSL连接,稍后UI对象会收到 CallBackCloseSuccess回调事件,完整事务处理结束。
有任务=*pTask
无任务=NULL

 

注:上表中的虚函数皆为RunL触发的异步函数

4.2.1.1.3    CTask

CTask是一个非常简单的值对象,用于CallBackGetNextTask方法的任务对象传递,目前由于调查深度有限,仅仅能够考虑到的结构如下:

4.2.1.1.3.1    CTask定义
序号 属性 描述
1 RequestBuf 请求缓冲区,保存请求数据内容
2 ResponseBuf 接受数据缓冲区,用户返回接受数据内容
3 ResponseBufLength 接受数据缓冲区长度,用于边界检查
4 RecvBufSize 每次接收数据缓冲区大小,用于计算进度,更新UI

 

4.2.1.1.4    CAppUILogin

这是一个实例类,用于演示主线程UI与SSL活动对象CSecEngine的交互过程,CAppUILogin必须实现CallBackInitSuccess, CallBackSocketConnectSuccess, CallBackHandshakeSuccess, CallBackSendSuccess, CallBackRecving, CallBackRecvSuccess, CallBackCloseSuccess, CallBackGetNextTask等接口,做到与SSL服务器进行异步交互。具体的实现方式在这里不作更详尽的描述了。

4.2.2    顺序图


 4.2.3    交互过程详解

序列交互对象为三个,分别为:ActiveScheduler, CAppUIBase, CSecEngine,其中CAppUIBase和CSecEngine不用过多的阐述了,这里为了说明活动对象的运行过程,涉及异步的操作描述引入了一个框架提供的ActiveScheduler,即为活动规划器,用于管理一个或多个活动对象的,具体关系如下:


 4.2.3.1    步骤



 初始化CSecEngine 活动对象,注册UI回调接口,以实现活动对象与UI交互,并控制业务流程。


连接SSL,开始进入CSecEngine活动对象异步事务处理轮询,对于CAppUIBase来说,仅仅做好回调监控和流程任务控制即可,CSecEngine会根据回调函数的返回值判断执行情况以及何时退出事务处理。

 由活动规划器出发的异步事件处理,该过程实现对页面的反馈,以及获取CAppUIBase的控制信息,判断是否退出,同时进行下一轮的异步消息处理。


 回调方式通知CAppUIBase当前活动对象处理情况,并根据返回值类型判断是否中断。

 由CAppUIBase回调方法返回的控制值如果为0,则退出当前CSecEngine处理。


 当发送了异步事件处理请求后,通过SetActive()方法,将活动对象内部的iStatus设置为KRequestPending状态,标志该事件为处理完成,由活动规划器(ActiveScheduler)跟踪该事件的处理,并且在该事件处理完成后调用当前活动对象的RunL()方法完成该事件处理。

 当Socket连接建立成功以后,活动规划器会调用CSecEngine::RunL()方法,由活动规划器出发的异步事件处理,该过程实现对页面的反馈,以及获取CAppUIBase的控制信息,判断是否退出,同时进行下一轮的异步消息处理。
该过程发送下一步的异步请求(SSL安全连接握手)Handshake,通过SetActive()方式立即返回将控制权返还活动规划器。

 回调CAppUIBase::CallBackSocketConnectSuccess()方法通知Socket连接已经创建,更新UI提示信息,并且获得用户操作是否中止标志。

 如果用户选择中止操作,上述方法调用返回值为0,活动对象清理已使用资源,最后调用CActive::Cancel()方法,结束活动对象。

 通过CActive::SetActive()方法跟踪事件处理结果,活动对象等待,并进入活动规划器的事件循环中。

 当握手(Handshake)成功以后,活动规划器会调用CSecEngine::RunL()方法,该过程实现对页面的反馈,以及获取CAppUIBase的控制信息,判断是否退出,同时进行下一轮的异步消息处理。
该过程发送下一步的请求-发送SSL请求(Send)操作,通过SetActive()方式立即返回将控制权返还活动规划器。

 回调CAppUIBase::CallBackHandshakeSuccess()方法通知UI SSL握手成功,更新UI提示信息,并且获得用户操作是否中止标志。

 如果用户选择中止操作,上述方法调用返回值为0,活动对象清理已使用资源,最后调用CActive::Cancel()方法,结束活动对象。

 通过CActive::SetActive()方法跟踪事件处理结果,活动对象等待,并进入活动规划器的事件循环中。


 进入发送接受过程,该过程步骤虽然比较多,但是逻辑非常简单,主要就是异步的发送请求,异步的接受数据,整个过程根据设置接受缓冲区大小重复接收的次数会有所差异,缓冲区越大,接收的次数就越少,缓冲区越小接收数据的次数就越多,下载进度条的算法也要做相应调整。
其次,这个过程根据业务的要求,可能会重复多次,直至CAppUIBase::CAllBackGetNextTask()函数返回值为NULL时结束该过程。
接收过程结束后会关闭SSL连接,当执行SetActive()后,方法返回。


 SSL连接关闭后,调用该函数,通知整个活动对象生命周期结束。

 SSL连接关闭后,CSecEngine通过回调的方式通知CAppUIBase,整个数据下载过程完成,可以进行用户交互操作了。

 退出活动对象。

 

4.3    小结

本章讨论了一个基于活动对象处理SSL事务的公共方法,将业务逻辑和控制功能与UI更新功能置于该活动对象之外,期望实现可以公共使用的脱离业务实体的交互对象。并采用活动规划器的异步事件功能,实现类似于辅助工作线程的表现逻辑。其中的设想为组内成员讨论结果,个人经修改整理得出,由于个人能力有限,其中不免有遗漏与错误的地方,还望不吝赐教。

5    附录资源

5.1    UML设计Jude文件

对不起,无法上传,有意者请留言。

6    参考资料

  • Symbian OS:活动对象与活动调度器

          http://www.sf.org.cn/Article/symbiandev/200602/17059.html

  • SSL (Secure Socket Layer)

          http://baike.baidu.com/view/16147.htm?fr=ala0_1

  • RSA

          http://baike.baidu.com/view/7520.htm?fr=ala0_1_1

 

 






  • 大小: 46.5 KB
  • 大小: 183.1 KB
  • 大小: 172.1 KB
  • 大小: 1.3 KB
  • 大小: 1.4 KB
  • 大小: 1.2 KB
  • 大小: 1.5 KB
  • 大小: 1.6 KB
  • 大小: 1.6 KB
  • 大小: 1.1 KB
  • 大小: 1.4 KB
  • 大小: 1.1 KB
  • 大小: 176.3 KB
  • 大小: 67.5 KB
  • 大小: 117.8 KB
  • 大小: 57.8 KB
  • 大小: 3.1 KB
  • 大小: 3.1 KB
  • 大小: 2.5 KB
  • 大小: 5.1 KB
  • 大小: 2.9 KB
  • 大小: 6.7 KB
  • 大小: 2.5 KB
  • 大小: 7.3 KB
  • 大小: 2.9 KB
  • 大小: 6.7 KB
  • 大小: 2.2 KB
  • 大小: 7 KB
  • 大小: 3.2 KB
  • 大小: 6 KB
  • 大小: 75.7 KB
  • 大小: 2.2 KB
  • 大小: 4.9 KB
  • 大小: 2.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics