Include cursor image to capture
[platform/core/uifw/e-mod-tizen-rdp.git] / src / e_mod_rdp.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <errno.h>
10
11 #include <assert.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <linux/input.h>
17
18 #include <freerdp/version.h>
19 #include <freerdp/freerdp.h>
20 #include <freerdp/listener.h>
21 #include <freerdp/update.h>
22 #include <freerdp/input.h>
23 #include <freerdp/codec/color.h>
24 #include <freerdp/codec/rfx.h>
25 #include <freerdp/codec/nsc.h>
26 #include <freerdp/locale/keyboard.h>
27 #include <winpr/input.h>
28 #include <winpr/ssl.h>
29
30 #include <pixman.h>
31 #include <tbm_surface.h>
32 #include <tbm_surface_internal.h>
33
34 #include "e_mod_main.h"
35 #include "e_mod_rdp.h"
36
37 #define E_RDP_WIDTH 1280
38 #define E_RDP_HEIGHT 720
39 #define E_MOD_RDP_CONFIG_VERSION  2
40 #define E_MOD_RDP_NAME_LEN        64
41 #define MAX_FREERDP_FDS           10
42 #define DEFAULT_PIXEL_FORMAT PIXEL_FORMAT_BGRA32
43
44 enum peer_item_flags
45 {
46    RDP_PEER_ACTIVATED      = (1 << 0),
47    RDP_PEER_OUTPUT_ENABLED = (1 << 1),
48 };
49
50 typedef struct _E_Rdp_Output E_Rdp_Output;
51 typedef struct _E_Rdp_Backend E_Rdp_Backend;
52 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
53 typedef struct _E_Rdp_Peer_Item E_Rdp_Peer_Item;
54 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
55
56 static E_Rdp_Config_Data *g_rdp_config;
57 static E_Rdp_Backend *g_rdp_backend;
58 static unsigned int refresh_raw_frame_id;
59
60 struct _E_Rdp_Output
61 {
62    E_Output *primary_output;
63    Ecore_Timer *frame_timer;
64    pixman_image_t *pix_surface;
65    tbm_surface_h tbm_surface;
66
67    struct wl_list peers;
68 };
69
70 struct _E_Rdp_Backend
71 {
72    freerdp_listener *listener;
73    struct wl_event_source *listener_events[MAX_FREERDP_FDS];
74    E_Rdp_Output *output;
75
76    char *server_cert;
77    char *server_key;
78    char *rdp_key;
79    int tls_enabled;
80    int no_clients_resize;
81    int force_no_compression;
82 };
83
84 struct _E_Rdp_Peer_Item
85 {
86    int flags;
87    freerdp_peer *peer;
88
89    struct wl_list link;
90 };
91
92 struct _E_Rdp_Peer_Context
93 {
94    rdpContext _p;
95
96    E_Rdp_Backend *rdpBackend;
97    struct wl_event_source *events[MAX_FREERDP_FDS];
98    RFX_CONTEXT *rfx_context;
99    wStream *encode_stream;
100    RFX_RECT *rfx_rects;
101    NSC_CONTEXT *nsc_context;
102
103    E_Rdp_Peer_Item item;
104 };
105
106 struct rdp_to_xkb_keyboard_layout
107 {
108    UINT32 rdpLayoutCode;
109    const char *xkbLayout;
110    const char *xkbVariant;
111 };
112
113 static tbm_surface_h
114 _e_rdp_tbm_image_create(E_Rdp_Output *output, int w, int h, int color)
115 {
116    tbm_surface_h tbm_surface = NULL;
117
118    tbm_surface = tbm_surface_internal_create_with_flags(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
119    if (!tbm_surface)
120      return NULL;
121
122    return tbm_surface;
123 }
124
125 static pixman_format_code_t
126 _e_rdp_pixman_format_get(tbm_format format)
127 {
128    switch (format)
129      {
130       case TBM_FORMAT_ARGB8888:
131         return PIXMAN_a8r8g8b8;
132
133       case TBM_FORMAT_XRGB8888:
134         return PIXMAN_x8r8g8b8;
135
136       default:
137         return 0;
138      }
139
140    return 0;
141 }
142
143 static pixman_image_t *
144 _e_rdp_pixman_image_create(tbm_surface_h tbm_surface)
145 {
146    int err;
147    tbm_surface_info_s info;
148    pixman_image_t *pix_surface = NULL;
149    pixman_format_code_t pix_format = 0;
150
151    EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
152
153    err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
154    if (err)
155      return NULL;
156
157    pix_format = _e_rdp_pixman_format_get(info.format);
158    if (pix_format == 0)
159      {
160         ERR("not supported format");
161         goto out;
162      }
163
164    pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
165    if (pix_surface == NULL)
166      ERR("create pixman image failed");
167
168 out:
169    tbm_surface_unmap(tbm_surface);
170    return pix_surface;
171 }
172
173 static void
174 e_rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
175 {
176    int width, height, nrects, i;
177    pixman_box32_t *region, *rects;
178    uint32_t *ptr;
179    RFX_RECT *rfxRect;
180    rdpUpdate *update = peer->update;
181    SURFACE_BITS_COMMAND cmd = { 0 };
182    E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
183
184    Stream_Clear(context->encode_stream);
185    Stream_SetPosition(context->encode_stream, 0);
186
187    width = (damage->extents.x2 - damage->extents.x1);
188    height = (damage->extents.y2 - damage->extents.y1);
189
190    cmd.skipCompression = TRUE;
191    cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
192    cmd.destLeft = damage->extents.x1;
193    cmd.destTop = damage->extents.y1;
194    cmd.destRight = damage->extents.x2;
195    cmd.destBottom = damage->extents.y2;
196    cmd.bmp.bpp = 32;
197    cmd.bmp.codecID = peer->settings->RemoteFxCodecId;
198    cmd.bmp.width = width;
199    cmd.bmp.height = height;
200
201    ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
202
203    rects = pixman_region32_rectangles(damage, &nrects);
204    context->rfx_rects = realloc(context->rfx_rects, nrects * sizeof *rfxRect);
205    if (context->rfx_rects == NULL)
206      {
207         ERR("realloc failed");
208         return;
209      }
210
211    for (i = 0; i < nrects; i++)
212      {
213         region = &rects[i];
214         rfxRect = &context->rfx_rects[i];
215
216         rfxRect->x = (region->x1 - damage->extents.x1);
217         rfxRect->y = (region->y1 - damage->extents.y1);
218         rfxRect->width = (region->x2 - region->x1);
219         rfxRect->height = (region->y2 - region->y1);
220      }
221
222    rfx_compose_message(context->rfx_context, context->encode_stream, context->rfx_rects, nrects, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
223
224    cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
225    cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
226
227    update->SurfaceBits(update->context, &cmd);
228 }
229
230
231 static void
232 e_rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
233 {
234    int width, height;
235    uint32_t *ptr;
236    rdpUpdate *update = peer->update;
237    SURFACE_BITS_COMMAND cmd = { 0 };
238    E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
239
240    Stream_Clear(context->encode_stream);
241    Stream_SetPosition(context->encode_stream, 0);
242
243    width = (damage->extents.x2 - damage->extents.x1);
244    height = (damage->extents.y2 - damage->extents.y1);
245
246    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
247    cmd.skipCompression = TRUE;
248    cmd.destLeft = damage->extents.x1;
249    cmd.destTop = damage->extents.y1;
250    cmd.destRight = damage->extents.x2;
251    cmd.destBottom = damage->extents.y2;
252    cmd.bmp.bpp = 32;
253    cmd.bmp.codecID = peer->settings->NSCodecId;
254    cmd.bmp.width = width;
255    cmd.bmp.height = height;
256
257    ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
258
259    nsc_compose_message(context->nsc_context, context->encode_stream, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
260
261    cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
262    cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
263
264    update->SurfaceBits(update->context, &cmd);
265 }
266
267 static void
268 pixman_image_flipped_subrect(const pixman_box32_t *rect, pixman_image_t *img, BYTE *dest)
269 {
270    int stride = pixman_image_get_stride(img);
271    int h;
272    int toCopy = (rect->x2 - rect->x1) * 4;
273    int height = (rect->y2 - rect->y1);
274    const BYTE *src = (const BYTE *)pixman_image_get_data(img);
275    src += ((rect->y2-1) * stride) + (rect->x1 * 4);
276
277    for (h = 0; h < height; h++, src -= stride, dest += toCopy)
278      memcpy(dest, src, toCopy);
279 }
280
281 static void
282 e_rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_peer *peer)
283 {
284    rdpUpdate *update = peer->update;
285    SURFACE_BITS_COMMAND cmd = { 0 };
286    SURFACE_FRAME_MARKER marker;
287    pixman_box32_t *rect, subrect;
288    int nrects, i;
289    int heightIncrement, remainingHeight, top;
290
291    rect = pixman_region32_rectangles(region, &nrects);
292    if (!nrects)
293      return;
294
295    if (refresh_raw_frame_id == 1024)
296      refresh_raw_frame_id = 0;
297    refresh_raw_frame_id++;
298
299    marker.frameId = refresh_raw_frame_id;
300    marker.frameAction = SURFACECMD_FRAMEACTION_BEGIN;
301    update->SurfaceFrameMarker(peer->context, &marker);
302
303    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
304    cmd.bmp.bpp = 32;
305    cmd.bmp.codecID = 0;
306
307    for (i = 0; i < nrects; i++, rect++)
308      {
309         /*INF("rect(%d,%d, %d,%d)\n", rect->x1, rect->y1, rect->x2, rect->y2);*/
310         cmd.destLeft = rect->x1;
311         cmd.destRight = rect->x2;
312         cmd.bmp.width = (rect->x2 - rect->x1);
313
314         heightIncrement = peer->settings->MultifragMaxRequestSize / (16 + cmd.bmp.width * 4);
315         remainingHeight = rect->y2 - rect->y1;
316         top = rect->y1;
317
318         subrect.x1 = rect->x1;
319         subrect.x2 = rect->x2;
320
321         while (remainingHeight)
322           {
323              cmd.bmp.height = (remainingHeight > heightIncrement) ? heightIncrement : remainingHeight;
324              cmd.destTop = top;
325              cmd.destBottom = top + cmd.bmp.height;
326              cmd.bmp.bitmapDataLength = cmd.bmp.width * cmd.bmp.height * 4;
327              cmd.bmp.bitmapData = (BYTE *)realloc(cmd.bmp.bitmapData, cmd.bmp.bitmapDataLength);
328
329              subrect.y1 = top;
330              subrect.y2 = top + cmd.bmp.height;
331              pixman_image_flipped_subrect(&subrect, image, cmd.bmp.bitmapData);
332
333              /*INF("*  sending (%d,%d, %d,%d)\n", subrect.x1, subrect.y1, subrect.x2, subrect.y2); */
334              update->SurfaceBits(peer->context, &cmd);
335
336              remainingHeight -= cmd.bmp.height;
337              top += cmd.bmp.height;
338           }
339      }
340
341    free(cmd.bmp.bitmapData);
342
343    marker.frameAction = SURFACECMD_FRAMEACTION_END;
344    update->SurfaceFrameMarker(peer->context, &marker);
345 }
346
347 static void
348 e_rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer, tbm_surface_h tbm_surface, pixman_image_t *pix_surface)
349 {
350    E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
351    E_Rdp_Output *output = context->rdpBackend->output;
352    rdpSettings *settings = peer->settings;
353
354    if (settings->RemoteFxCodec)
355      e_rdp_peer_refresh_rfx(region, pix_surface, peer);
356    else if (settings->NSCodec)
357      e_rdp_peer_refresh_nsc(region, pix_surface, peer);
358    else
359      e_rdp_peer_refresh_raw(region, pix_surface, peer);
360
361    if (output->pix_surface)
362      pixman_image_unref(output->pix_surface);
363    output->pix_surface = pix_surface;
364
365    if (output->tbm_surface)
366      tbm_surface_destroy(output->tbm_surface);
367    output->tbm_surface = tbm_surface;
368 }
369
370 static void
371 _e_rdp_output_image_showing_rect_get(Eina_Rectangle *out_rect, Eina_Rectangle *dst_rect, Eina_Rectangle *showing_rect)
372 {
373    showing_rect->x = dst_rect->x;
374    showing_rect->y = dst_rect->y;
375
376    if (dst_rect->x >= out_rect->w)
377      showing_rect->w = 0;
378    else if (dst_rect->x + dst_rect->w > out_rect->w)
379      showing_rect->w = out_rect->w - dst_rect->x;
380    else
381      showing_rect->w = dst_rect->w;
382
383    if (dst_rect->y >= out_rect->h)
384      showing_rect->h = 0;
385    else if (dst_rect->y + dst_rect->h > out_rect->h)
386      showing_rect->h = out_rect->h - dst_rect->y;
387    else
388      showing_rect->h = dst_rect->h;
389 }
390
391 static void
392 _e_rdp_output_image_src_crop_get(E_Hwc_Window *hwc_window, Eina_Rectangle *fit, Eina_Rectangle *showing_rect, int primary_w, int primary_h)
393 {
394    float ratio_x, ratio_y;
395    Eina_Rectangle out_rect;
396    Eina_Rectangle dst_rect;
397
398    fit->x = 0;
399    fit->y = 0;
400    fit->w = 0;
401    fit->h = 0;
402
403    out_rect.x = 0;
404    out_rect.y = 0;
405    out_rect.w = primary_w;
406    out_rect.h = primary_h;
407
408    dst_rect.x = hwc_window->current.info.dst_pos.x;
409    dst_rect.y = hwc_window->current.info.dst_pos.y;
410    dst_rect.w = hwc_window->current.info.dst_pos.w;
411    dst_rect.h = hwc_window->current.info.dst_pos.h;
412
413    _e_rdp_output_image_showing_rect_get(&out_rect, &dst_rect, showing_rect);
414
415    fit->x = hwc_window->current.info.src_config.pos.x;
416    fit->y = hwc_window->current.info.src_config.pos.y;
417
418    if (hwc_window->current.info.transform % 2 == 0)
419      {
420         ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.w;
421         ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.h;
422
423         fit->w = showing_rect->w * ratio_x;
424         fit->h = showing_rect->h * ratio_y;
425      }
426    else
427      {
428         ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.h;
429         ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.w;
430
431         fit->w = showing_rect->h * ratio_x;
432         fit->h = showing_rect->w * ratio_y;
433      }
434 }
435
436 static void
437 _e_rdp_output_center_rect_get (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
438 {
439    float rw, rh;
440
441    if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
442      return;
443
444    rw = (float)src_w / dst_w;
445    rh = (float)src_h / dst_h;
446
447    if (rw > rh)
448      {
449         fit->w = dst_w;
450         fit->h = src_h / rw;
451         fit->x = 0;
452         fit->y = (dst_h - fit->h) / 2;
453      }
454    else if (rw < rh)
455      {
456         fit->w = src_w / rh;
457         fit->h = dst_h;
458         fit->x = (dst_w - fit->w) / 2;
459         fit->y = 0;
460      }
461    else
462      {
463         fit->w = dst_w;
464         fit->h = dst_h;
465         fit->x = 0;
466         fit->y = 0;
467      }
468
469    if (fit->x % 2)
470      fit->x = fit->x - 1;
471 }
472
473 static void
474 _e_rdp_output_image_dst_crop_get(E_Hwc_Window *hwc_window, int src_w, int src_h, int w, int h,
475                                  Eina_Rectangle *pos, Eina_Rectangle *showing_pos, Eina_Rectangle *dst_crop, int rotate)
476 {
477    dst_crop->x = 0;
478    dst_crop->y = 0;
479    dst_crop->w = 0;
480    dst_crop->h = 0;
481
482    if (hwc_window->current.info.src_config.pos.w == w && hwc_window->current.info.src_config.pos.h == h &&
483        pos->x == 0 && pos->y == 0 && pos->w == src_w && pos->h == src_h)
484      {
485         dst_crop->x = pos->x;
486         dst_crop->y = pos->y;
487         dst_crop->w = pos->w;
488         dst_crop->h = pos->h;
489      }
490    else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
491      {
492         dst_crop->x = hwc_window->current.info.dst_pos.x + pos->x;
493         dst_crop->y = hwc_window->current.info.dst_pos.y + pos->y;
494         dst_crop->w = hwc_window->current.info.dst_pos.w;
495         dst_crop->h = hwc_window->current.info.dst_pos.h;
496      }
497    else if (rotate == 0)
498      {
499         dst_crop->x = showing_pos->x * pos->w / w + pos->x;
500         dst_crop->y = showing_pos->y * pos->h / h + pos->y;
501         dst_crop->w = showing_pos->w * pos->w / w;
502         dst_crop->h = showing_pos->h * pos->h / h;
503      }
504    else
505      {
506         dst_crop->x = pos->x;
507         dst_crop->y = pos->y;
508         dst_crop->w = pos->w;
509         dst_crop->h = pos->h;
510      }
511 }
512
513 static void
514 _e_rdp_output_image_composite(pixman_image_t *src_img, pixman_image_t *dst_img,
515                           int sx, int sy, int sw, int sh,
516                           int dx, int dy, int dw, int dh,
517                           Eina_Bool over, int rotate, int hflip, int vflip)
518 {
519    double scale_x, scale_y;
520    int rotate_step;
521    pixman_transform_t t;
522    struct pixman_f_transform ft;
523    pixman_op_t op;
524
525    pixman_f_transform_init_identity(&ft);
526
527    if (hflip)
528      {
529         pixman_f_transform_scale(&ft, NULL, -1, 1);
530         pixman_f_transform_translate(&ft, NULL, dw, 0);
531      }
532
533    if (vflip)
534      {
535         pixman_f_transform_scale(&ft, NULL, 1, -1);
536         pixman_f_transform_translate(&ft, NULL, 0, dh);
537      }
538
539    rotate_step = (rotate + 360) / 90 % 4;
540    if (rotate_step > 0)
541      {
542         int c, s, tx = 0, ty = 0;
543         switch (rotate_step)
544           {
545            case 1:
546               c = 0, s = -1, tx = -dw;
547               break;
548            case 2:
549               c = -1, s = 0, tx = -dw, ty = -dh;
550               break;
551            case 3:
552               c = 0, s = 1, ty = -dh;
553               break;
554           }
555         pixman_f_transform_translate(&ft, NULL, tx, ty);
556         pixman_f_transform_rotate(&ft, NULL, c, s);
557      }
558
559    if (rotate_step % 2 == 0)
560      {
561         scale_x = (double)sw / dw;
562         scale_y = (double)sh / dh;
563      }
564    else
565      {
566         scale_x = (double)sw / dh;
567         scale_y = (double)sh / dw;
568      }
569
570    pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
571    pixman_f_transform_translate(&ft, NULL, sx, sy);
572    pixman_transform_from_pixman_f_transform(&t, &ft);
573    pixman_image_set_transform(src_img, &t);
574
575    if (!over) op = PIXMAN_OP_SRC;
576    else op = PIXMAN_OP_OVER;
577
578    pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
579                           dx, dy, dw, dh);
580 }
581
582 static Eina_Bool
583 _e_rdp_pixman_output_image_composite_cursor(E_Rdp_Output *output, E_Hwc_Window *hwc_window, pixman_image_t *pix_surface, int pix_w, int pix_h, int primary_w, int primary_h)
584 {
585    Eina_Rectangle showing_pos = {0, };
586    Eina_Rectangle dst_pos = {0, };
587    Eina_Rectangle src_crop = {0, };
588    Eina_Rectangle dst_crop = {0, };
589    void *src_ptr = NULL;
590    int src_stride, img_w, img_h;
591    pixman_image_t *pix_shm_src = NULL;
592
593    if (!hwc_window->cursor.buffer)
594      return EINA_FALSE;
595
596    src_ptr = hwc_window->cursor.img_ptr;
597    src_stride = hwc_window->cursor.img_stride;
598    img_w = hwc_window->cursor.img_w;
599    img_h = hwc_window->cursor.img_h;
600
601    pix_shm_src = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride);
602    if (!pix_shm_src)
603      {
604         ERR("create pixman image failed");
605         return EINA_FALSE;
606      }
607
608    _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
609    _e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos);
610    _e_rdp_output_image_dst_crop_get(hwc_window, img_w, img_h, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
611
612    _e_rdp_output_image_composite(pix_shm_src, pix_surface,
613                                  src_crop.x, src_crop.y, src_crop.w, src_crop.h,
614                                  dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
615                                  EINA_TRUE, 0, 0, 0);
616
617    pixman_image_unref(pix_shm_src);
618
619    return EINA_TRUE;
620 }
621
622 static Eina_Bool
623 _e_rdp_pixman_output_image_composite(E_Rdp_Output *output, E_Hwc_Window *hwc_window, pixman_image_t *pix_surface, int pix_w, int pix_h, int primary_w, int primary_h)
624 {
625    Eina_Rectangle showing_pos = {0, };
626    Eina_Rectangle dst_pos = {0, };
627    Eina_Rectangle src_crop = {0, };
628    Eina_Rectangle dst_crop = {0, };
629    tbm_surface_h tbm_surface = NULL;
630    tbm_surface_info_s info;
631    pixman_image_t *pix_surface_src = NULL;
632    pixman_format_code_t pix_format = 0;
633    int err = 0;
634
635    tbm_surface = hwc_window->display.buffer.tsurface;
636    if (!tbm_surface)
637      return EINA_FALSE;
638
639    tbm_surface_internal_ref(tbm_surface);
640
641    err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
642    if (err)
643      return EINA_FALSE;
644
645    pix_format = _e_rdp_pixman_format_get(info.format);
646    if (pix_format == 0)
647      {
648         ERR("not supported format");
649         tbm_surface_unmap(tbm_surface);
650         return EINA_FALSE;
651      }
652
653    pix_surface_src = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
654    if (pix_surface_src == NULL)
655      {
656         ERR("create pixman image failed");
657         tbm_surface_unmap(tbm_surface);
658         return EINA_FALSE;
659      }
660
661    _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
662    _e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos);
663    _e_rdp_output_image_dst_crop_get(hwc_window, info.width, info.height, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
664
665    _e_rdp_output_image_composite(pix_surface_src, pix_surface,
666                                  src_crop.x, src_crop.y, src_crop.w, src_crop.h,
667                                  dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
668                                  EINA_TRUE, 0, 0, 0);
669
670    pixman_image_unref(pix_surface_src);
671    tbm_surface_unmap(tbm_surface);
672    tbm_surface_internal_unref(tbm_surface);
673
674    return EINA_TRUE;
675 }
676
677 static int
678 _e_rdp_cb_hwc_window_sort(const void *d1, const void *d2)
679 {
680    E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
681    E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
682    int zpos1 = 0, zpos2 = 0;
683
684    if (!hwc_window1) return(1);
685    if (!hwc_window2) return(-1);
686
687    if (hwc_window1->state == E_HWC_WINDOW_STATE_NONE)
688      zpos1 = -999;
689    else
690      zpos1 = hwc_window1->zpos;
691
692    if (hwc_window2->state == E_HWC_WINDOW_STATE_NONE)
693      zpos2 = -999;
694    else
695      zpos2 = hwc_window2->zpos;
696
697    return (zpos1 - zpos2);
698 }
699
700 static pixman_image_t *
701 _e_rdp_pixman_output_image_get(E_Rdp_Output *output, tbm_surface_h tbm_surface)
702 {
703    E_Output *e_output = NULL;
704    E_Hwc *hwc = NULL;
705    E_Hwc_Window *hwc_window = NULL;
706    Eina_List *l;
707    Eina_List *visible_list = NULL;
708    Eina_Bool target_window = EINA_FALSE;
709    int err;
710    tbm_surface_info_s info;
711    pixman_image_t *pix_surface = NULL;
712    pixman_format_code_t pix_format = 0;
713    int e_output_w, e_output_h;
714
715    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
716    EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
717
718    e_output = output->primary_output;
719    EINA_SAFETY_ON_NULL_RETURN_VAL(e_output, NULL);
720
721    hwc = e_output->hwc;
722    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
723
724    e_output_w = e_output->config.mode.w;
725    e_output_h = e_output->config.mode.h;
726
727    err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
728    if (err)
729      return NULL;
730
731    pix_format = _e_rdp_pixman_format_get(info.format);
732    if (pix_format == 0)
733      {
734         ERR("not supported format");
735         goto out;
736      }
737
738    pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
739    if (pix_surface == NULL)
740      {
741         ERR("create pixman image failed");
742         goto out;
743      }
744
745    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
746      {
747         if (!hwc_window) continue;
748         if (hwc_window->is_target) continue;
749         if (hwc_window->is_video) continue;
750         if (hwc_window->state == E_HWC_WINDOW_STATE_NONE || hwc_window->zpos == -999) continue;
751
752         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
753           {
754              target_window = EINA_TRUE;
755              visible_list = eina_list_append(visible_list, hwc_window);
756              continue;
757           }
758
759         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE)
760           visible_list = eina_list_append(visible_list, hwc_window);
761
762         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR)
763           {
764              if (hwc_window->cursor.buffer)
765                visible_list = eina_list_append(visible_list, hwc_window);
766           }
767      }
768
769    if (eina_list_count(visible_list) == 0)
770      {
771         ERR("no visible hwc_window for capture");
772         _e_rdp_pixman_output_image_composite(output, (E_Hwc_Window *)hwc->target_hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
773         goto out;
774      }
775
776    visible_list = eina_list_sort(visible_list, eina_list_count(visible_list), _e_rdp_cb_hwc_window_sort);
777
778    EINA_LIST_FOREACH(visible_list, l, hwc_window)
779      {
780         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
781           {
782              if (target_window)
783                {
784                   target_window = EINA_FALSE;
785                   _e_rdp_pixman_output_image_composite(output, (E_Hwc_Window *)hwc->target_hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
786                }
787              continue;
788           }
789
790         if (hwc_window->is_cursor)
791           _e_rdp_pixman_output_image_composite_cursor(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
792         else
793           _e_rdp_pixman_output_image_composite(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
794      }
795
796 out:
797    tbm_surface_unmap(tbm_surface);
798
799    return pix_surface;
800 }
801
802 static Eina_Bool
803 _e_rdp_frame_timer(void *data)
804 {
805    E_Rdp_Output *output;
806    tbm_surface_h tbm_surface = NULL;
807    pixman_image_t *pix_surface = NULL;
808    pixman_box32_t box;
809    pixman_region32_t damage;
810    E_Rdp_Peer_Item *rdp_peer, *tmp;
811    freerdp_peer *client = NULL;
812
813    EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
814
815    output = (E_Rdp_Output *)data;
816
817    tbm_surface = _e_rdp_tbm_image_create(output, E_RDP_WIDTH, E_RDP_HEIGHT, 0x00000000);
818    if (tbm_surface == NULL)
819      {
820         ERR("create tbm surface failed");
821         return ECORE_CALLBACK_RENEW;
822      }
823
824    pix_surface = _e_rdp_pixman_output_image_get(output, tbm_surface);
825    if (pix_surface == NULL)
826      {
827         ERR("create output pixman surface failed");
828         tbm_surface_destroy(tbm_surface);
829         return ECORE_CALLBACK_RENEW;
830      }
831
832    /* sends a full refresh */
833    box.x1 = 0;
834    box.y1 = 0;
835    box.x2 = E_RDP_WIDTH;
836    box.y2 = E_RDP_HEIGHT;
837    pixman_region32_init_with_extents(&damage, &box);
838
839    wl_list_for_each_safe(rdp_peer, tmp, &output->peers, link)
840      {
841         client = rdp_peer->peer;
842         if (!client)
843           continue;
844
845         e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
846      }
847    pixman_region32_fini(&damage);
848
849    return ECORE_CALLBACK_RENEW;
850 }
851
852
853 static BOOL
854 e_rdp_peer_capabilities(freerdp_peer *client)
855 {
856    return TRUE;
857 }
858
859 static BOOL
860 e_rdp_peer_post_connect(freerdp_peer *client)
861 {
862    return TRUE;
863 }
864
865 static BOOL
866 e_rdp_peer_activate(freerdp_peer *client)
867 {
868    E_Rdp_Peer_Context *peerCtx;
869    E_Rdp_Backend *b;
870    E_Rdp_Output *output;
871    rdpSettings *settings;
872    rdpPointerUpdate *pointer;
873    E_Rdp_Peer_Item *peersItem;
874    pixman_box32_t box;
875    pixman_region32_t damage;
876    POINTER_SYSTEM_UPDATE pointer_system;
877    tbm_surface_h tbm_surface = NULL;
878    pixman_image_t *pix_surface = NULL;
879
880    EINA_SAFETY_ON_NULL_RETURN_VAL(client, FALSE);
881    EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, FALSE);
882    EINA_SAFETY_ON_NULL_RETURN_VAL(client->settings, FALSE);
883
884    peerCtx = (E_Rdp_Peer_Context *)client->context;
885    EINA_SAFETY_ON_NULL_RETURN_VAL(peerCtx, FALSE);
886
887    b = peerCtx->rdpBackend;
888    EINA_SAFETY_ON_NULL_RETURN_VAL(b, FALSE);
889
890    peersItem = &peerCtx->item;
891    EINA_SAFETY_ON_NULL_RETURN_VAL(peersItem, FALSE);
892
893    output = b->output;
894    settings = client->settings;
895
896    if (!settings->SurfaceCommandsEnabled)
897      {
898         ERR("client doesn't support required SurfaceCommands\n");
899         return FALSE;
900      }
901
902    if (b->force_no_compression && settings->CompressionEnabled)
903      {
904         ERR("Forcing compression off\n");
905         settings->CompressionEnabled = FALSE;
906      }
907
908    if (E_RDP_WIDTH != (int)settings->DesktopWidth || E_RDP_HEIGHT != (int)settings->DesktopHeight)
909      {
910         if (b->no_clients_resize)
911           {
912              /* RDP peers don't dictate their resolution to e */
913              if (!settings->DesktopResize)
914                {
915                   /* peer does not support desktop resize */
916                   ERR("%s: client doesn't support resizing, closing connection\n", __FUNCTION__);
917                   return FALSE;
918                }
919              else
920                {
921                   settings->DesktopWidth = E_RDP_WIDTH;
922                   settings->DesktopHeight = E_RDP_HEIGHT;
923                   client->update->DesktopResize(client->context);
924                }
925           }
926         else
927           {
928              ;
929              /* not supported */
930           }
931      }
932
933    rfx_context_reset(peerCtx->rfx_context, E_RDP_WIDTH, E_RDP_HEIGHT);
934    nsc_context_reset(peerCtx->nsc_context, E_RDP_WIDTH, E_RDP_HEIGHT);
935    if (peersItem->flags & RDP_PEER_ACTIVATED)
936      return TRUE;
937
938    /* when here it's the first reactivation, we need to setup a little more */
939    DBG("kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x kbd_functionKeys:0x%x\n",
940        settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType, settings->KeyboardFunctionKey);
941
942    peersItem->flags |= RDP_PEER_ACTIVATED;
943
944    /* disable pointer on the client side */
945    pointer = client->update->pointer;
946    pointer_system.type = SYSPTR_NULL;
947    pointer->PointerSystem(client->context, &pointer_system);
948
949    tbm_surface = _e_rdp_tbm_image_create(output, E_RDP_WIDTH, E_RDP_HEIGHT, 0xFFFFCCFF);
950    if (tbm_surface == NULL)
951      {
952         ERR("create sample tbm surface failed");
953         return TRUE;
954      }
955    pix_surface = _e_rdp_pixman_image_create(tbm_surface);
956    if (pix_surface == NULL)
957      {
958         ERR("create sample pixman failed");
959         tbm_surface_destroy(tbm_surface);
960         return TRUE;
961      }
962
963    /* sends a full refresh */
964    box.x1 = 0;
965    box.y1 = 0;
966    box.x2 = E_RDP_WIDTH;
967    box.y2 = E_RDP_HEIGHT;
968    pixman_region32_init_with_extents(&damage, &box);
969
970    e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
971
972    pixman_region32_fini(&damage);
973
974    if (output->frame_timer != NULL)
975      ecore_timer_del(output->frame_timer);
976    output->frame_timer = ecore_timer_add(0.2, _e_rdp_frame_timer, output);
977
978    return TRUE;
979 }
980
981 static BOOL
982 e_rdp_suppress_output(rdpContext *context, BYTE allow, const RECTANGLE_16 *area)
983 {
984    E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)context;
985
986    if (allow)
987      peerContext->item.flags |= RDP_PEER_OUTPUT_ENABLED;
988    else
989      peerContext->item.flags &= (~RDP_PEER_OUTPUT_ENABLED);
990
991    return TRUE;
992 }
993
994 static BOOL
995 e_rdp_input_synchronize_event(rdpInput *input, UINT32 flags)
996 {
997    //To do
998    return TRUE;
999 }
1000
1001 static BOOL
1002 e_rdp_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1003 {
1004    //To do
1005    return TRUE;
1006 }
1007
1008 static BOOL
1009 e_rdp_extended_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1010 {
1011    //To do
1012    return TRUE;
1013 }
1014
1015 static BOOL
1016 e_rdp_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1017 {
1018    //To do
1019    return TRUE;
1020 }
1021
1022 static BOOL
1023 e_rdp_input_unicode_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1024 {
1025    DBG("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
1026    return TRUE;
1027 }
1028
1029 static int
1030 e_rdp_client_activity(int fd, uint32_t mask, void *data)
1031 {
1032    freerdp_peer *client = (freerdp_peer *)data;
1033    E_Rdp_Peer_Context *peerCtx;
1034    E_Rdp_Backend *b;
1035    E_Rdp_Output *output;
1036
1037    EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1038    EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, 0);
1039
1040    if (client->CheckFileDescriptor(client))
1041      {
1042 //        DBG("enable client activity %p", client);
1043         return 0;
1044      }
1045
1046    INF("unable to checkDescriptor for %p\n", client);
1047    peerCtx = (E_Rdp_Peer_Context *)client->context;
1048    EINA_SAFETY_ON_NULL_GOTO(peerCtx, out_clean);
1049
1050    b = peerCtx->rdpBackend;
1051    EINA_SAFETY_ON_NULL_GOTO(b, out_clean);
1052
1053    output = b->output;
1054    if (output->frame_timer)
1055      {
1056         ecore_timer_del(output->frame_timer);
1057         output->frame_timer = NULL;
1058      }
1059 out_clean:
1060    freerdp_peer_context_free(client);
1061    freerdp_peer_free(client);
1062    return 0;
1063 }
1064
1065 static BOOL
1066 e_rdp_peer_context_new(freerdp_peer *client, E_Rdp_Peer_Context *context)
1067 {
1068    context->item.peer = client;
1069    context->item.flags = RDP_PEER_OUTPUT_ENABLED;
1070
1071    context->rfx_context = rfx_context_new(TRUE);
1072    if (!context->rfx_context)
1073      return FALSE;
1074
1075    context->rfx_context->mode = RLGR3;
1076    context->rfx_context->width = client->settings->DesktopWidth;
1077    context->rfx_context->height = client->settings->DesktopHeight;
1078    rfx_context_set_pixel_format(context->rfx_context, DEFAULT_PIXEL_FORMAT);
1079
1080    context->nsc_context = nsc_context_new();
1081    if (!context->nsc_context)
1082      goto out_error_nsc;
1083
1084    nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, DEFAULT_PIXEL_FORMAT);
1085    context->encode_stream = Stream_New(NULL, 65536);
1086    if (!context->encode_stream)
1087      goto out_error_stream;
1088
1089    return TRUE;
1090
1091 out_error_nsc:
1092    rfx_context_free(context->rfx_context);
1093 out_error_stream:
1094    nsc_context_free(context->nsc_context);
1095    return FALSE;
1096 }
1097
1098 static void
1099 e_rdp_peer_context_free(freerdp_peer *client, E_Rdp_Peer_Context *context)
1100 {
1101    int i;
1102    if (!context)
1103      return;
1104
1105    wl_list_remove(&context->item.link);
1106    for (i = 0; i < MAX_FREERDP_FDS; i++)
1107      {
1108         if (context->events[i])
1109           wl_event_source_remove(context->events[i]);
1110      }
1111
1112    Stream_Free(context->encode_stream, TRUE);
1113    nsc_context_free(context->nsc_context);
1114    rfx_context_free(context->rfx_context);
1115    free(context->rfx_rects);
1116 }
1117
1118
1119 static int
1120 e_rdp_peer_init(freerdp_peer *client, E_Rdp_Backend *b)
1121 {
1122    int rcount = 0;
1123    void *rfds[MAX_FREERDP_FDS];
1124    int i, fd;
1125    struct wl_event_loop *loop;
1126    rdpSettings *settings;
1127    rdpInput *input;
1128    E_Rdp_Peer_Context *peerCtx;
1129
1130    client->ContextSize = sizeof(E_Rdp_Peer_Context);
1131    client->ContextNew = (psPeerContextNew)e_rdp_peer_context_new;
1132    client->ContextFree = (psPeerContextFree)e_rdp_peer_context_free;
1133    freerdp_peer_context_new(client);
1134
1135    peerCtx = (E_Rdp_Peer_Context *)client->context;
1136    peerCtx->rdpBackend = b;
1137
1138    settings = client->settings;
1139
1140    if (b->tls_enabled)
1141      {
1142         settings->CertificateFile = strdup(b->server_cert);
1143         settings->PrivateKeyFile = strdup(b->server_key);
1144      }
1145    else
1146      {
1147         settings->TlsSecurity = FALSE;
1148      }
1149    settings->NlaSecurity = FALSE;
1150
1151    if (!client->Initialize(client))
1152      {
1153         ERR("peer initialization failed\n");
1154         return -1;
1155      }
1156
1157    settings->OsMajorType = OSMAJORTYPE_UNIX;
1158    settings->OsMinorType = OSMINORTYPE_PSEUDO_XSERVER;
1159    settings->ColorDepth = 32;
1160    settings->RefreshRect = TRUE;
1161    settings->RemoteFxCodec = TRUE;
1162    settings->NSCodec = TRUE;
1163    settings->FrameMarkerCommandEnabled = TRUE;
1164    settings->SurfaceFrameMarkerEnabled = TRUE;
1165
1166    client->Capabilities = e_rdp_peer_capabilities;
1167    client->PostConnect = e_rdp_peer_post_connect;
1168    client->Activate = e_rdp_peer_activate;
1169
1170    client->update->SuppressOutput = (pSuppressOutput)e_rdp_suppress_output;
1171
1172    input = client->input;
1173    input->SynchronizeEvent = e_rdp_input_synchronize_event;
1174    input->MouseEvent = e_rdp_mouse_event;
1175    input->ExtendedMouseEvent = e_rdp_extended_mouse_event;
1176    input->KeyboardEvent = e_rdp_input_keyboard_event;
1177    input->UnicodeKeyboardEvent = e_rdp_input_unicode_keyboard_event;
1178
1179    if (!client->GetFileDescriptor(client, rfds, &rcount))
1180      {
1181         ERR("unable to retrieve client fds");
1182         goto error_initialize;
1183      }
1184
1185    if (rcount > MAX_FREERDP_FDS)
1186      {
1187         ERR("check fds max count. count:%d, max:%d", rcount, MAX_FREERDP_FDS);
1188         goto error_initialize;
1189      }
1190
1191    loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
1192    for (i = 0; i < rcount; i++)
1193      {
1194         fd = (int)(long)(rfds[i]);
1195
1196         peerCtx->events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_client_activity, client);
1197      }
1198    for ( ; i < MAX_FREERDP_FDS; i++)
1199      peerCtx->events[i] = 0;
1200
1201    wl_list_insert(&b->output->peers, &peerCtx->item.link);
1202    return 0;
1203
1204 error_initialize:
1205    client->Close(client);
1206    return -1;
1207 }
1208
1209 static BOOL
1210 e_rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
1211 {
1212    E_Rdp_Backend *b = (E_Rdp_Backend *)instance->param4;
1213
1214    if (e_rdp_peer_init(client, b) < 0)
1215      {
1216         ERR("error when treating incoming peer\n");
1217         return FALSE;
1218      }
1219
1220    return TRUE;
1221 }
1222
1223 static int
1224 e_rdp_listener_activity(int fd, uint32_t mask, void *data)
1225 {
1226    freerdp_listener* instance = (freerdp_listener *)data;
1227
1228    if (!(mask & WL_EVENT_READABLE))
1229      return 0;
1230
1231    if (!instance->CheckFileDescriptor(instance))
1232      {
1233         ERR("failed to check FreeRDP file descriptor\n");
1234         return -1;
1235      }
1236
1237    return 0;
1238 }
1239
1240 static Eina_Bool
1241 e_rdp_implant_listener(E_Rdp_Backend *b, freerdp_listener *instance)
1242 {
1243    int i, fd;
1244    int rcount = 0;
1245    void* rfds[MAX_FREERDP_FDS];
1246    struct wl_event_loop *loop;
1247
1248    if (!instance->GetFileDescriptor(instance, rfds, &rcount))
1249      {
1250         ERR("Failed to get FreeRDP file descriptor\n");
1251         return EINA_FALSE;
1252      }
1253
1254    loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
1255    for (i = 0; i < rcount; i++)
1256      {
1257         fd = (int)(long)(rfds[i]);
1258         b->listener_events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_listener_activity, instance);
1259      }
1260
1261    for ( ; i < MAX_FREERDP_FDS; i++)
1262      b->listener_events[i] = 0;
1263
1264    return EINA_TRUE;
1265 }
1266
1267 static void
1268 e_rdp_output_destroy(E_Rdp_Output *output)
1269 {
1270    EINA_SAFETY_ON_NULL_RETURN(output);
1271
1272    if (output->pix_surface)
1273      pixman_image_unref(output->pix_surface);
1274    if (output->tbm_surface)
1275      tbm_surface_destroy(output->tbm_surface);
1276
1277    free(output);
1278 }
1279
1280 E_Rdp_Output *
1281 e_rdp_output_create(void)
1282 {
1283    E_Rdp_Output *output = NULL;
1284
1285    output = E_NEW(E_Rdp_Output, 1);
1286    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1287
1288    output->primary_output = e_output_find_by_index(0);
1289
1290    wl_list_init(&output->peers);
1291
1292    return output;
1293 }
1294
1295 static void
1296 e_rdp_backend_destroy(void)
1297 {
1298    E_Rdp_Backend *b = NULL;
1299    E_Rdp_Peer_Item *rdp_peer, *tmp;
1300    int i;
1301
1302    b = g_rdp_backend;
1303    EINA_SAFETY_ON_NULL_RETURN(b);
1304
1305    if (b->output->frame_timer)
1306      {
1307         ecore_timer_del(b->output->frame_timer);
1308         b->output->frame_timer = NULL;
1309      }
1310
1311    wl_list_for_each_safe(rdp_peer, tmp, &b->output->peers, link)
1312      {
1313         freerdp_peer* client = rdp_peer->peer;
1314
1315         client->Disconnect(client);
1316         freerdp_peer_context_free(client);
1317         freerdp_peer_free(client);
1318      }
1319
1320    for (i = 0; i < MAX_FREERDP_FDS; i++)
1321      if (b->listener_events[i])
1322        wl_event_source_remove(b->listener_events[i]);
1323
1324    freerdp_listener_free(b->listener);
1325
1326    e_rdp_output_destroy(b->output);
1327
1328    free(b->server_cert);
1329    free(b->server_key);
1330    free(b);
1331 }
1332
1333
1334 Eina_Bool
1335 e_rdp_backend_create(E_Rdp_Conf_Edd *config)
1336 {
1337    E_Rdp_Backend *b;
1338
1339    b = E_NEW(E_Rdp_Backend, 1);
1340    EINA_SAFETY_ON_NULL_RETURN_VAL(b, EINA_FALSE);
1341
1342    b->rdp_key = NULL;
1343    b->no_clients_resize = config->no_clients_resize;
1344    b->force_no_compression = config->force_no_compression;
1345
1346    /* activate TLS only if certificate/key are available */
1347    if (config->server_cert && config->server_key)
1348      {
1349         DBG("TLS support activated\n");
1350         b->server_cert = strdup(config->server_cert);
1351         b->server_key = strdup(config->server_key);
1352         if (!b->server_cert || !b->server_key)
1353           goto err_free_strings;
1354         b->tls_enabled = 1;
1355      }
1356
1357    b->output = e_rdp_output_create();
1358    if (!b->output)
1359      {
1360         ERR("output create failed");
1361         goto err_free_strings;
1362      }
1363
1364    b->listener = freerdp_listener_new();
1365    b->listener->PeerAccepted = e_rdp_incoming_peer;
1366    b->listener->param4 = b;
1367    if (!b->listener->Open(b->listener, NULL, config->port))
1368      {
1369         ERR("unable to bind rdp socket\n");
1370         goto err_listener;
1371      }
1372
1373    if (e_rdp_implant_listener(b, b->listener) == EINA_FALSE)
1374      goto err_listener;
1375
1376    g_rdp_backend = b;
1377
1378    return EINA_TRUE;
1379
1380    err_listener:
1381    freerdp_listener_free(b->listener);
1382
1383    e_rdp_output_destroy(b->output);
1384    b->output = NULL;
1385
1386    err_free_strings:
1387    free(b->server_cert);
1388    free(b->server_key);
1389    free(b);
1390
1391    return EINA_FALSE;
1392 }
1393
1394 Eina_Bool
1395 e_mod_rdp_init(void)
1396 {
1397    int major, minor, revision;
1398    Eina_Bool ret = EINA_FALSE;
1399
1400    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
1401    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
1402
1403 #if FREERDP_VERSION_MAJOR >= 2
1404    winpr_InitializeSSL(0);
1405 #endif
1406
1407    freerdp_get_version(&major, &minor, &revision);
1408    if (major < E_MOD_RDP_CONFIG_VERSION)
1409      {
1410         ERR("Not supported version");
1411         return EINA_FALSE;
1412      }
1413    INF("freerdp version : %d.%d.%d", major, minor, revision);
1414
1415
1416    /* Init config */
1417    g_rdp_config = E_NEW(E_Rdp_Config_Data, 1);
1418    EINA_SAFETY_ON_NULL_RETURN_VAL(g_rdp_config, EINA_FALSE);
1419
1420    ret = e_rdp_conf_init(g_rdp_config);
1421    EINA_SAFETY_ON_FALSE_GOTO(ret, conf_err);
1422
1423    ret = e_rdp_backend_create(g_rdp_config->conf);
1424    EINA_SAFETY_ON_FALSE_GOTO(ret, create_err);
1425
1426    return ret;
1427
1428 create_err:
1429    e_rdp_conf_deinit(g_rdp_config);
1430 conf_err:
1431    E_FREE(g_rdp_config);
1432
1433    return ret;
1434 }
1435
1436 void
1437 e_mod_rdp_deinit(void)
1438 {
1439    e_rdp_backend_destroy();
1440    if (g_rdp_config)
1441      {
1442         e_rdp_conf_deinit(g_rdp_config);
1443         E_FREE(g_rdp_config);
1444      }
1445 }