freerdp update流程

由于项目需要,研究了一下xfreerdp的图像更新流程。freerdp中有各种各样的函数指针,还有很多宏定义,具体的函数调用,通过阅读源码很难知道!这时候就需要祭出大杀器:systemtap了。
最最基础我知道每次图像更新调用了xf_client.c的函数:xf_hw_begin_paint,xf_hw_end_paint。

通过侦测libfreerdp/core/rdp.c和xf_client.c的两个函数,获得如下信息:
可以看到程序中有两个线程在读取socket中的数据:31762和6454。

     0 gokuapp(6454): << freerdp_check_event_handles
     7 gokuapp(6454):  << freerdp_check_fds
    12 gokuapp(6454):   << rdp_check_fds
//rdp_check_fds中会调用transport_check_fds(transport.c),在transport.c中负责数据的接收。
    17 gokuapp(6454):    << freerdp_shall_disconnect
    22 gokuapp(6454):    >> freerdp_shall_disconnect
//transport接收完数据后,回调rdp_recv_callback,这个函数负责数据的解析。
    70 gokuapp(6454):    << rdp_recv_callback
    75 gokuapp(6454):     << rdp_recv_pdu
//解析到一个fastpath pdu!
    79 gokuapp(6454):      << rdp_recv_fastpath_pdu
//我们推测具体画的动作在这两个函数之间:<<<<<<<
//begin和end之间又做了些什么呢?
    85 gokuapp(6454):       << xf_hw_begin_paint
    88 gokuapp(6454):       >> xf_hw_begin_paint
   107 gokuapp(6454):       << xf_hw_end_paint
   132 gokuapp(6454):       >> xf_hw_end_paint
//我们推测具体画的动作在这两个函数之间:>>>>>>
   134 gokuapp(6454):      >> rdp_recv_fastpath_pdu
   135 gokuapp(6454):     >> rdp_recv_pdu
   137 gokuapp(6454):    >> rdp_recv_callback
   141 gokuapp(6454):    << freerdp_shall_disconnect
   144 gokuapp(6454):    >> freerdp_shall_disconnect
   150 gokuapp(6454):   >> rdp_check_fds
   152 gokuapp(6454):  >> freerdp_check_fds
   156 gokuapp(6454):  << checkChannelErrorEvent
   159 gokuapp(6454):  >> checkChannelErrorEvent
   161 gokuapp(6454): >> freerdp_check_event_handles

     0 gokuapp(31762): << freerdp_check_event_handles
     6 gokuapp(31762):  << freerdp_check_fds
    12 gokuapp(31762):   << rdp_check_fds
    17 gokuapp(31762):    << freerdp_shall_disconnect
    23 gokuapp(31762):    >> freerdp_shall_disconnect
    40 gokuapp(31762):   >> rdp_check_fds
    41 gokuapp(31762):  >> freerdp_check_fds
    46 gokuapp(31762):  << checkChannelErrorEvent
    49 gokuapp(31762):  >> checkChannelErrorEvent
    50 gokuapp(31762): >> freerdp_check_event_handles
     0 gokuapp(31762): << freerdp_shall_disconnect
     3 gokuapp(31762): >> freerdp_shall_disconnect
     0 gokuapp(31762): << freerdp_focus_required
     2 gokuapp(31762): >> freerdp_focus_required
     0 gokuapp(31762): << freerdp_get_event_handles
     4 gokuapp(31762):  << getChannelErrorEventHandle
     6 gokuapp(31762):  >> getChannelErrorEventHandle
     8 gokuapp(31762): >> freerdp_get_event_handles

//上面留下了一个疑问,begin和end之间又做了些什么呢:
int fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
{
    rdpUpdate* update = fastpath->rdp->update;

    IFCALL(update->BeginPaint, update->context);

    while (Stream_GetRemainingLength(s) >= 3)
    {
        if (fastpath_recv_update_data(fastpath, s) < 0)
        {
            WLog_ERR(TAG, "fastpath_recv_update_data() fail");
            return -1;
        }
    }

    IFCALL(update->EndPaint, update->context);

    return 0;
}
这个函数的调用信息如下:
     0 gokuapp(6454): <<fastpath_recv_updates
     6 gokuapp(6454):  <<fastpath_recv_update_data
//首先,读头!
     9 gokuapp(6454):   <<fastpath_read_update_header
    12 gokuapp(6454):   >>fastpath_read_update_header
//然后,根据头的信息,解压数据!
    16 gokuapp(6454):   <<bulk_decompress
    20 gokuapp(6454):    <<bulk_compression_max_size
    23 gokuapp(6454):     <<bulk_compression_level
    25 gokuapp(6454):     >>bulk_compression_level
    27 gokuapp(6454):    >>bulk_compression_max_size
    56 gokuapp(6454):    <<metrics_write_bytes
    58 gokuapp(6454):    >>metrics_write_bytes
    59 gokuapp(6454):   >>bulk_decompress
//解析解压后的数据!
    63 gokuapp(6454):   <<fastpath_recv_update
static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 size, wStream* s)
//根据不同的updateCode解析数据,后面的函数的updatecode是FASTPATH_UPDATETYPE_ORDERS!
    79 gokuapp(6454):    <<fastpath_recv_orders
    82 gokuapp(6454):     <<update_recv_order
    86 gokuapp(6454):      <<update_recv_altsec_order
    91 gokuapp(6454):       <<update_read_frame_marker_order
    93 gokuapp(6454):       >>update_read_frame_marker_order
    94 gokuapp(6454):      >>update_recv_altsec_order
    96 gokuapp(6454):     >>update_recv_order
    98 gokuapp(6454):     <<update_recv_order
   101 gokuapp(6454):      <<update_recv_primary_order
   105 gokuapp(6454):       <<update_read_field_flags
   107 gokuapp(6454):       >>update_read_field_flags
   110 gokuapp(6454):       <<update_read_memblt_order
   114 gokuapp(6454):        <<update_read_coord
   116 gokuapp(6454):        >>update_read_coord
   118 gokuapp(6454):        <<update_read_coord
   120 gokuapp(6454):        >>update_read_coord
   121 gokuapp(6454):       >>update_read_memblt_order
   127 gokuapp(6454):      >>update_recv_primary_order
   128 gokuapp(6454):     >>update_recv_order
   130 gokuapp(6454):     <<update_recv_order
   133 gokuapp(6454):      <<update_recv_primary_order
   136 gokuapp(6454):       <<update_read_field_flags
   137 gokuapp(6454):       >>update_read_field_flags
   139 gokuapp(6454):       <<update_read_memblt_order
   142 gokuapp(6454):        <<update_read_coord
   144 gokuapp(6454):        >>update_read_coord
   145 gokuapp(6454):       >>update_read_memblt_order
   147 gokuapp(6454):      >>update_recv_primary_order
   148 gokuapp(6454):     >>update_recv_order
   150 gokuapp(6454):     <<update_recv_order
   153 gokuapp(6454):      <<update_recv_primary_order
   156 gokuapp(6454):       <<update_read_field_flags
   158 gokuapp(6454):       >>update_read_field_flags
   160 gokuapp(6454):       <<update_read_memblt_order
   162 gokuapp(6454):        <<update_read_coord
   164 gokuapp(6454):        >>update_read_coord
   165 gokuapp(6454):       >>update_read_memblt_order
   166 gokuapp(6454):      >>update_recv_primary_order
   168 gokuapp(6454):     >>update_recv_order
   170 gokuapp(6454):     <<update_recv_order
   172 gokuapp(6454):      <<update_recv_primary_order
   175 gokuapp(6454):       <<update_read_field_flags
   177 gokuapp(6454):       >>update_read_field_flags
   179 gokuapp(6454):       <<update_read_memblt_order
   182 gokuapp(6454):        <<update_read_coord
   183 gokuapp(6454):        >>update_read_coord
   184 gokuapp(6454):       >>update_read_memblt_order
   186 gokuapp(6454):      >>update_recv_primary_order
   187 gokuapp(6454):     >>update_recv_order
   189 gokuapp(6454):     <<update_recv_order
   192 gokuapp(6454):      <<update_recv_primary_order
   194 gokuapp(6454):       <<update_read_field_flags
   196 gokuapp(6454):       >>update_read_field_flags
   198 gokuapp(6454):       <<update_read_memblt_order
   201 gokuapp(6454):        <<update_read_coord
   203 gokuapp(6454):        >>update_read_coord
   205 gokuapp(6454):        <<update_read_coord
   206 gokuapp(6454):        >>update_read_coord
   207 gokuapp(6454):       >>update_read_memblt_order
   209 gokuapp(6454):      >>update_recv_primary_order
   210 gokuapp(6454):     >>update_recv_order
   212 gokuapp(6454):     <<update_recv_order
   215 gokuapp(6454):      <<update_recv_primary_order
   217 gokuapp(6454):       <<update_read_field_flags
   219 gokuapp(6454):       >>update_read_field_flags
   221 gokuapp(6454):       <<update_read_memblt_order
   224 gokuapp(6454):        <<update_read_coord
   226 gokuapp(6454):        >>update_read_coord
   227 gokuapp(6454):       >>update_read_memblt_order
   228 gokuapp(6454):      >>update_recv_primary_order
   229 gokuapp(6454):     >>update_recv_order
   231 gokuapp(6454):     <<update_recv_order
   234 gokuapp(6454):      <<update_recv_primary_order
   237 gokuapp(6454):       <<update_read_field_flags
   238 gokuapp(6454):       >>update_read_field_flags
   241 gokuapp(6454):       <<update_read_memblt_order
   243 gokuapp(6454):        <<update_read_coord
   245 gokuapp(6454):        >>update_read_coord
   246 gokuapp(6454):       >>update_read_memblt_order
   247 gokuapp(6454):      >>update_recv_primary_order
   248 gokuapp(6454):     >>update_recv_order
   250 gokuapp(6454):     <<update_recv_order
   253 gokuapp(6454):      <<update_recv_primary_order
   256 gokuapp(6454):       <<update_read_field_flags
   258 gokuapp(6454):       >>update_read_field_flags
   260 gokuapp(6454):       <<update_read_memblt_order
   263 gokuapp(6454):        <<update_read_coord
   264 gokuapp(6454):        >>update_read_coord
   265 gokuapp(6454):       >>update_read_memblt_order
   267 gokuapp(6454):      >>update_recv_primary_order
   268 gokuapp(6454):     >>update_recv_order
   270 gokuapp(6454):     <<update_recv_order
   272 gokuapp(6454):      <<update_recv_primary_order
   275 gokuapp(6454):       <<update_read_field_flags
   277 gokuapp(6454):       >>update_read_field_flags
   279 gokuapp(6454):       <<update_read_memblt_order
   282 gokuapp(6454):        <<update_read_coord
   283 gokuapp(6454):        >>update_read_coord
   286 gokuapp(6454):        <<update_read_coord
   287 gokuapp(6454):        >>update_read_coord
   288 gokuapp(6454):       >>update_read_memblt_order
   290 gokuapp(6454):      >>update_recv_primary_order
   291 gokuapp(6454):     >>update_recv_order
   293 gokuapp(6454):     <<update_recv_order
   295 gokuapp(6454):      <<update_recv_primary_order
   298 gokuapp(6454):       <<update_read_field_flags
   300 gokuapp(6454):       >>update_read_field_flags
   302 gokuapp(6454):       <<update_read_memblt_order
   305 gokuapp(6454):        <<update_read_coord
   306 gokuapp(6454):        >>update_read_coord
   308 gokuapp(6454):       >>update_read_memblt_order
   309 gokuapp(6454):      >>update_recv_primary_order
   310 gokuapp(6454):     >>update_recv_order
   312 gokuapp(6454):     <<update_recv_order
   315 gokuapp(6454):      <<update_recv_primary_order
   317 gokuapp(6454):       <<update_read_field_flags
   319 gokuapp(6454):       >>update_read_field_flags
   321 gokuapp(6454):       <<update_read_memblt_order
   324 gokuapp(6454):        <<update_read_coord
   326 gokuapp(6454):        >>update_read_coord
   327 gokuapp(6454):       >>update_read_memblt_order
   328 gokuapp(6454):      >>update_recv_primary_order
   329 gokuapp(6454):     >>update_recv_order
   331 gokuapp(6454):     <<update_recv_order
   334 gokuapp(6454):      <<update_recv_primary_order
   337 gokuapp(6454):       <<update_read_field_flags
   338 gokuapp(6454):       >>update_read_field_flags
   340 gokuapp(6454):       <<update_read_memblt_order
   343 gokuapp(6454):        <<update_read_coord
   345 gokuapp(6454):        >>update_read_coord
   346 gokuapp(6454):       >>update_read_memblt_order
   347 gokuapp(6454):      >>update_recv_primary_order
   348 gokuapp(6454):     >>update_recv_order
   350 gokuapp(6454):     <<update_recv_order
   353 gokuapp(6454):      <<update_recv_altsec_order
   356 gokuapp(6454):       <<update_read_frame_marker_order
   358 gokuapp(6454):       >>update_read_frame_marker_order
   359 gokuapp(6454):      >>update_recv_altsec_order
   360 gokuapp(6454):     >>update_recv_order
   361 gokuapp(6454):    >>fastpath_recv_orders
   363 gokuapp(6454):   >>fastpath_recv_update
   364 gokuapp(6454):  >>fastpath_recv_update_data
   385 gokuapp(6454): >>fastpath_recv_updates

上面的内容是典型的rdp gdi协议!
下面我们直接看rdp gdi协议文档内容:

The Remote Desktop Protocol: Graphics Devices Interfaces (GDI) Acceleration Extension is an extension to the Remote Desktop Protocol: Basic Connectivity and Graphics Remoting (as specified in [MS-DPBCGR]). The aim of the Remote Desktop Protocol: GDI Acceleration Extension is to reduce the bandwidth associated with graphics remoting by encoding the drawing operations that produce an image instead of encoding the actual image.

可以看到gdi协议的目的是减少网络带宽的占用,如何减少,用传输drawing operations替代传输编码的图像。所以,gdi协议的大部分内容是传输drawing operations!

一些文档中用到的术语!列出了我认为比较重要的几个:

ARGB: A color space wherein each color is represented as a quad (A, R, G, B), where A represents the alpha (transparency) component, R represents the red component, G represents the green component, and B represents the blue component. The ARGB value is typically stored as a 32-bit integer, wherein the alpha channel is stored in the highest 8 bits and the blue value is storedin the lowest 8 bits.

brush: An 8-by-8-pixel bitmap that is repeated horizontally and vertically to fill an area.

color plane: A two-dimensional surface containing a collection of values that represent a single component of the ARGB or AYCoCg color space.

color space: Any method of representing colors for printing or electronic display.

Packed Encoding Rules (PER): A set of encoding rules for ASN.1 notation, specified in [ITUX691]. These rules enable the identification, extraction, and decoding of data structures.

protocol data unit (PDU): Information that is delivered as a unit among peer entities of a network and that may contain control information, address information, or data. For more information on remote procedure call (RPC)-specific PDUs, see [C706] section 12.

Reverse Polish Notation (RPN): A mathematical notation wherein each operator follows all of its operands. Also known as postfix notation.

screen tearing: A phenomenon in video rendering where a newly rendered frame partially overlaps with a previously rendered frame, creating a torn look as graphical objects do not line up.

具体GDI协议是如何降低带宽的使用,同时又能保证终端的体验效果呢?文档有如下解释:

For example, instead of sending the bitmap image of a filled rectangle from server to client, an orderto render a rectangle at coordinate (X, Y) with a given width, height, and fill color is sent to the client. The client then executes the drawing order to produce the intended graphics result.

In addition to defining how to encode common drawing operations, the Remote Desktop Protocol: GDI Acceleration Extension also facilitates the use of caches to store drawing primitives such as bitmaps, color tables, and characters. The effective use of caching techniques helps to reduce wire traffic by ensuring that items used in multiple drawing operations are sent only once from server to client (retransmission of these items for use in conjunction with future drawing operations is not required after the item has been cached on the client).

GDI协议是发送的编码的drawing order,同时还会发送bitmaps, color tables, characters的cache。所以GDI协议的cache机制很关键!

GDI协议的几个关键部分:

  • Caches
    The Remote Desktop Protocol: GDI Acceleration Extension defines a number of caches that may be
    leveraged by clients and servers:
     Bitmap Cache: Stores bitmap images.
     Color Table Cache: Stores color palettes.
     Glyph Cache: Stores character images.
     Fragment Cache: Stores collections of glyphs.

    Brush Cache: Stores 8-by-8-pixel bitmaps used to fill regions.
     Offscreen Bitmap Cache: Stores writable bitmaps.
     GDI+ Caches: Used to cache GDI+ 1.1 primitives:

     Graphics Cache
     Brush Cache
     Pen Cache
     Image Attributes Cache
     Image Cache
    NineGrid Bitmap Cache: Stores NineGrid-compliant bitmaps. For more information about nine-grid
    bitmaps, see [NINEGRID].

  • Drawing Orders
    Drawing orders are used to perform the following operations:
     Transport bitmap data
     Encode graphics rendering primitives
     Manipulate data caches
     Manage rendering surfaces
     Support application remoting ([MS-RDPERP] section 1.3)
     Support desktop composition ([MS-RDPEDC] section 1.3)
    There are three classes of drawing orders:
     Primary
     Secondary
     Alternate secondary

  • Bulk Data Compression

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

推荐阅读更多精彩内容

  • Alex二年级时学了一篇选自《聊斋志异》的课文,回来颇感兴趣,找出原文后却有些意兴阑珊。后来趁着新鲜有空会挑几则和...
    安言片语阅读 2,105评论 0 49
  • 第一章 死不瞑目 夜深沉,洒下点点新月的光芒,寂静得可怕,清月宫外面的风阴冷的嚎叫着,时不时可以听到风吹树叶的沙...
    向日葵丶阅读 439评论 1 2
  • 子在川上曰 逝者如斯夫,不舍昼夜 苏 子 曰 逝者如斯,而未尝往已 前者来自孔子,说时间就像流水一样,不断流...
    穹涯阅读 794评论 14 19