"Fossies" - the Fresh Open Source Software Archive

Member "rdesktop-1.9.0/seamless.c" (13 Jun 2019, 10446 Bytes) of package /linux/privat/rdesktop-1.9.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "seamless.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.3_vs_1.8.5.

    1 /* -*- c-basic-offset: 8 -*-
    2    rdesktop: A Remote Desktop Protocol client.
    3    Seamless Windows support
    4    Copyright 2005-2008 Peter Astrand <astrand@cendio.se> for Cendio AB
    5    Copyright 2007-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
    6    Copyright 2013-2017 Henrik Andersson  <hean01@cendio.se> for Cendio AB
    7 
    8    This program is free software: you can redistribute it and/or modify
    9    it under the terms of the GNU General Public License as published by
   10    the Free Software Foundation, either version 3 of the License, or
   11    (at your option) any later version.
   12 
   13    This program is distributed in the hope that it will be useful,
   14    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16    GNU General Public License for more details.
   17 
   18    You should have received a copy of the GNU General Public License
   19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   20 */
   21 
   22 #include "rdesktop.h"
   23 #include <stdarg.h>
   24 #include <assert.h>
   25 
   26 extern RD_BOOL g_seamless_rdp;
   27 static VCHANNEL *seamless_channel;
   28 static unsigned int seamless_serial;
   29 static char *seamless_rest = NULL;
   30 static char icon_buf[1024];
   31 
   32 static char *
   33 seamless_get_token(char **s)
   34 {
   35     char *comma, *head;
   36     head = *s;
   37 
   38     if (!head)
   39         return NULL;
   40 
   41     comma = strchr(head, ',');
   42     if (comma)
   43     {
   44         *comma = '\0';
   45         *s = comma + 1;
   46     }
   47     else
   48     {
   49         *s = NULL;
   50     }
   51 
   52     return head;
   53 }
   54 
   55 
   56 static RD_BOOL
   57 seamless_process_line(const char *line, void *data)
   58 {
   59     UNUSED(data);
   60     char *p, *l;
   61     char *tok1, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
   62     unsigned long id, flags;
   63     char *endptr;
   64 
   65     l = xstrdup(line);
   66     p = l;
   67 
   68     logger(Core, Debug, "seamless_process_line(), got '%s'", p);
   69 
   70     tok1 = seamless_get_token(&p);
   71     (void) seamless_get_token(&p);
   72     tok3 = seamless_get_token(&p);
   73     tok4 = seamless_get_token(&p);
   74     tok5 = seamless_get_token(&p);
   75     tok6 = seamless_get_token(&p);
   76     tok7 = seamless_get_token(&p);
   77     tok8 = seamless_get_token(&p);
   78 
   79     if (!strcmp("CREATE", tok1))
   80     {
   81         unsigned long group, parent;
   82         if (!tok6)
   83             return False;
   84 
   85         id = strtoul(tok3, &endptr, 0);
   86         if (*endptr)
   87             return False;
   88 
   89         group = strtoul(tok4, &endptr, 0);
   90         if (*endptr)
   91             return False;
   92 
   93         parent = strtoul(tok5, &endptr, 0);
   94         if (*endptr)
   95             return False;
   96 
   97         flags = strtoul(tok6, &endptr, 0);
   98         if (*endptr)
   99             return False;
  100 
  101         ui_seamless_create_window(id, group, parent, flags);
  102     }
  103     else if (!strcmp("DESTROY", tok1))
  104     {
  105         if (!tok4)
  106             return False;
  107 
  108         id = strtoul(tok3, &endptr, 0);
  109         if (*endptr)
  110             return False;
  111 
  112         flags = strtoul(tok4, &endptr, 0);
  113         if (*endptr)
  114             return False;
  115 
  116         ui_seamless_destroy_window(id, flags);
  117 
  118     }
  119     else if (!strcmp("DESTROYGRP", tok1))
  120     {
  121         if (!tok4)
  122             return False;
  123 
  124         id = strtoul(tok3, &endptr, 0);
  125         if (*endptr)
  126             return False;
  127 
  128         flags = strtoul(tok4, &endptr, 0);
  129         if (*endptr)
  130             return False;
  131 
  132         ui_seamless_destroy_group(id, flags);
  133     }
  134     else if (!strcmp("SETICON", tok1))
  135     {
  136         int chunk, width, height, len;
  137         char byte[3];
  138 
  139         if (!tok8)
  140             return False;
  141 
  142         id = strtoul(tok3, &endptr, 0);
  143         if (*endptr)
  144             return False;
  145 
  146         chunk = strtoul(tok4, &endptr, 0);
  147         if (*endptr)
  148             return False;
  149 
  150         width = strtoul(tok6, &endptr, 0);
  151         if (*endptr)
  152             return False;
  153 
  154         height = strtoul(tok7, &endptr, 0);
  155         if (*endptr)
  156             return False;
  157 
  158         byte[2] = '\0';
  159         len = 0;
  160         while (*tok8 != '\0')
  161         {
  162             byte[0] = *tok8;
  163             tok8++;
  164             if (*tok8 == '\0')
  165                 return False;
  166             byte[1] = *tok8;
  167             tok8++;
  168 
  169             icon_buf[len] = strtol(byte, NULL, 16);
  170             len++;
  171 
  172             if ((size_t)len >= sizeof(icon_buf))
  173             {
  174                 logger(Protocol, Warning, "seamless_process_line(), icon data would overrun icon_buf");
  175                 break;
  176             }
  177         }
  178 
  179         ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
  180     }
  181     else if (!strcmp("DELICON", tok1))
  182     {
  183         int width, height;
  184 
  185         if (!tok6)
  186             return False;
  187 
  188         id = strtoul(tok3, &endptr, 0);
  189         if (*endptr)
  190             return False;
  191 
  192         width = strtoul(tok5, &endptr, 0);
  193         if (*endptr)
  194             return False;
  195 
  196         height = strtoul(tok6, &endptr, 0);
  197         if (*endptr)
  198             return False;
  199 
  200         ui_seamless_delicon(id, tok4, width, height);
  201     }
  202     else if (!strcmp("POSITION", tok1))
  203     {
  204         int x, y, width, height;
  205 
  206         if (!tok8)
  207             return False;
  208 
  209         id = strtoul(tok3, &endptr, 0);
  210         if (*endptr)
  211             return False;
  212 
  213         x = strtol(tok4, &endptr, 0);
  214         if (*endptr)
  215             return False;
  216         y = strtol(tok5, &endptr, 0);
  217         if (*endptr)
  218             return False;
  219 
  220         width = strtol(tok6, &endptr, 0);
  221         if (*endptr)
  222             return False;
  223         height = strtol(tok7, &endptr, 0);
  224         if (*endptr)
  225             return False;
  226 
  227         flags = strtoul(tok8, &endptr, 0);
  228         if (*endptr)
  229             return False;
  230 
  231         ui_seamless_move_window(id, x, y, width, height, flags);
  232     }
  233     else if (!strcmp("ZCHANGE", tok1))
  234     {
  235         unsigned long behind;
  236 
  237         id = strtoul(tok3, &endptr, 0);
  238         if (*endptr)
  239             return False;
  240 
  241         behind = strtoul(tok4, &endptr, 0);
  242         if (*endptr)
  243             return False;
  244 
  245         flags = strtoul(tok5, &endptr, 0);
  246         if (*endptr)
  247             return False;
  248 
  249         ui_seamless_restack_window(id, behind, flags);
  250     }
  251     else if (!strcmp("TITLE", tok1))
  252     {
  253         if (!tok5)
  254             return False;
  255 
  256         id = strtoul(tok3, &endptr, 0);
  257         if (*endptr)
  258             return False;
  259 
  260         flags = strtoul(tok5, &endptr, 0);
  261         if (*endptr)
  262             return False;
  263 
  264         ui_seamless_settitle(id, tok4, flags);
  265     }
  266     else if (!strcmp("STATE", tok1))
  267     {
  268         unsigned int state;
  269 
  270         if (!tok5)
  271             return False;
  272 
  273         id = strtoul(tok3, &endptr, 0);
  274         if (*endptr)
  275             return False;
  276 
  277         state = strtoul(tok4, &endptr, 0);
  278         if (*endptr)
  279             return False;
  280 
  281         flags = strtoul(tok5, &endptr, 0);
  282         if (*endptr)
  283             return False;
  284 
  285         ui_seamless_setstate(id, state, flags);
  286     }
  287     else if (!strcmp("DEBUG", tok1))
  288     {
  289         logger(Core, Debug, "seamless_process_line(), %s", line);
  290     }
  291     else if (!strcmp("SYNCBEGIN", tok1))
  292     {
  293         if (!tok3)
  294             return False;
  295 
  296         flags = strtoul(tok3, &endptr, 0);
  297         if (*endptr)
  298             return False;
  299 
  300         ui_seamless_syncbegin(flags);
  301     }
  302     else if (!strcmp("SYNCEND", tok1))
  303     {
  304         if (!tok3)
  305             return False;
  306 
  307         flags = strtoul(tok3, &endptr, 0);
  308         if (*endptr)
  309             return False;
  310 
  311         /* do nothing, currently */
  312     }
  313     else if (!strcmp("HELLO", tok1))
  314     {
  315         if (!tok3)
  316             return False;
  317 
  318         flags = strtoul(tok3, &endptr, 0);
  319         if (*endptr)
  320             return False;
  321 
  322         ui_seamless_begin(! !(flags & SEAMLESSRDP_HELLO_HIDDEN));
  323     }
  324     else if (!strcmp("ACK", tok1))
  325     {
  326         unsigned int serial;
  327 
  328         serial = strtoul(tok3, &endptr, 0);
  329         if (*endptr)
  330             return False;
  331 
  332         ui_seamless_ack(serial);
  333     }
  334     else if (!strcmp("HIDE", tok1))
  335     {
  336         if (!tok3)
  337             return False;
  338 
  339         flags = strtoul(tok3, &endptr, 0);
  340         if (*endptr)
  341             return False;
  342 
  343         ui_seamless_hide_desktop();
  344     }
  345     else if (!strcmp("UNHIDE", tok1))
  346     {
  347         if (!tok3)
  348             return False;
  349 
  350         flags = strtoul(tok3, &endptr, 0);
  351         if (*endptr)
  352             return False;
  353 
  354         ui_seamless_unhide_desktop();
  355     }
  356 
  357 
  358     xfree(l);
  359     return True;
  360 }
  361 
  362 
  363 static RD_BOOL
  364 seamless_line_handler(const char *line, void *data)
  365 {
  366     if (!seamless_process_line(line, data))
  367     {
  368         logger(Core, Warning, "seamless_line_handler(), invalid request '%s'", line);
  369     }
  370     return True;
  371 }
  372 
  373 
  374 static void
  375 seamless_process(STREAM s)
  376 {
  377     unsigned int pkglen;
  378     char *buf;
  379 
  380     pkglen = s_remaining(s);
  381     /* str_handle_lines requires null terminated strings */
  382     buf = xmalloc(pkglen + 1);
  383     in_uint8a(s, buf, pkglen);
  384     buf[pkglen] = '\0';
  385     str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
  386 
  387     xfree(buf);
  388 }
  389 
  390 
  391 RD_BOOL
  392 seamless_init(void)
  393 {
  394     if (!g_seamless_rdp)
  395         return False;
  396 
  397     seamless_serial = 0;
  398 
  399     seamless_channel =
  400         channel_register("seamrdp", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
  401                  seamless_process);
  402     return (seamless_channel != NULL);
  403 }
  404 
  405 void
  406 seamless_reset_state(void)
  407 {
  408     if (seamless_rest != NULL)
  409     {
  410         xfree(seamless_rest);
  411         seamless_rest = NULL;
  412     }
  413 }
  414 
  415 static unsigned int
  416 seamless_send(const char *command, const char *format, ...)
  417 {
  418     STREAM s;
  419     size_t len;
  420     va_list argp;
  421     char *escaped, buf[1025];
  422 
  423     len = snprintf(buf, sizeof(buf) - 1, "%s,%u,", command, seamless_serial);
  424 
  425     assert(len < (sizeof(buf) - 1));
  426 
  427     va_start(argp, format);
  428     len += vsnprintf(buf + len, sizeof(buf) - len - 1, format, argp);
  429     va_end(argp);
  430 
  431     assert(len < (sizeof(buf) - 1));
  432 
  433     escaped = utils_string_escape(buf);
  434     len = snprintf(buf, sizeof(buf), "%s", escaped);
  435     free(escaped);
  436     assert(len < (sizeof(buf) - 1));
  437 
  438     buf[len] = '\n';
  439     buf[len + 1] = '\0';
  440 
  441     len++;
  442 
  443     s = channel_init(seamless_channel, len);
  444     out_uint8a(s, buf, len) s_mark_end(s);
  445 
  446     logger(Core, Debug, "seamless_send(), sending '%s'", buf);
  447 
  448     channel_send(s, seamless_channel);
  449     s_free(s);
  450 
  451     return seamless_serial++;
  452 }
  453 
  454 
  455 unsigned int
  456 seamless_send_sync()
  457 {
  458     if (!g_seamless_rdp)
  459         return (unsigned int) -1;
  460 
  461     return seamless_send("SYNC", "");
  462 }
  463 
  464 
  465 unsigned int
  466 seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
  467 {
  468     if (!g_seamless_rdp)
  469         return (unsigned int) -1;
  470 
  471     return seamless_send("STATE", "0x%08lx,0x%x,0x%lx", id, state, flags);
  472 }
  473 
  474 
  475 unsigned int
  476 seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
  477 {
  478     return seamless_send("POSITION", "0x%08lx,%d,%d,%d,%d,0x%lx", id, x, y, width, height,
  479                  flags);
  480 }
  481 
  482 
  483 /* Update select timeout */
  484 void
  485 seamless_select_timeout(struct timeval *tv)
  486 {
  487     struct timeval ourtimeout = { 0, SEAMLESSRDP_POSITION_TIMER };
  488 
  489     if (g_seamless_rdp)
  490     {
  491         if (timercmp(&ourtimeout, tv, <))
  492         {
  493             tv->tv_sec = ourtimeout.tv_sec;
  494             tv->tv_usec = ourtimeout.tv_usec;
  495         }
  496     }
  497 }
  498 
  499 
  500 unsigned int
  501 seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
  502 {
  503     if (!g_seamless_rdp)
  504         return (unsigned int) -1;
  505 
  506     return seamless_send("ZCHANGE", "0x%08lx,0x%08lx,0x%lx", id, below, flags);
  507 }
  508 
  509 
  510 
  511 unsigned int
  512 seamless_send_focus(unsigned long id, unsigned long flags)
  513 {
  514     if (!g_seamless_rdp)
  515         return (unsigned int) -1;
  516 
  517     return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
  518 }
  519 
  520 /* Send client-to-server message to destroy process on the server. */
  521 unsigned int
  522 seamless_send_destroy(unsigned long id)
  523 {
  524     return seamless_send("DESTROY", "0x%08lx", id);
  525 }
  526 
  527 unsigned int
  528 seamless_send_spawn(char *cmdline)
  529 {
  530     unsigned int res;
  531     if (!g_seamless_rdp)
  532         return (unsigned int) -1;
  533 
  534     res = seamless_send("SPAWN", cmdline);
  535 
  536     return res;
  537 }
  538 
  539 unsigned int
  540 seamless_send_persistent(RD_BOOL enable)
  541 {
  542     unsigned int res;
  543     if (!g_seamless_rdp)
  544         return (unsigned int) -1;
  545 
  546     logger(Core, Debug, "seamless_send_persistent(), %s persistent seamless mode",
  547            enable ? "enable" : "disable");
  548     res = seamless_send("PERSISTENT", "%d", enable);
  549 
  550     return res;
  551 }