2012-09-20 07:51:34 +04:00
|
|
|
/**
|
|
|
|
* xrdp: A Remote Desktop Protocol server.
|
|
|
|
*
|
2015-07-12 11:06:04 +03:00
|
|
|
* Copyright (C) Jay Sorg 2004-2015
|
2012-09-20 07:51:34 +04:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* libxup main file
|
|
|
|
*/
|
2006-02-04 22:00:34 +03:00
|
|
|
|
2017-03-03 07:33:23 +03:00
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
|
|
#include <config_ac.h>
|
|
|
|
#endif
|
|
|
|
|
2006-02-04 22:00:34 +03:00
|
|
|
#include "xup.h"
|
2013-10-02 22:56:09 +04:00
|
|
|
#include "log.h"
|
2015-07-11 06:38:27 +03:00
|
|
|
#include "trans.h"
|
2020-12-21 15:36:00 +03:00
|
|
|
#include "string_calls.h"
|
2006-02-04 22:00:34 +03:00
|
|
|
|
2018-10-16 07:42:13 +03:00
|
|
|
static int
|
2022-03-15 07:45:26 +03:00
|
|
|
send_server_monitor_resize(
|
|
|
|
struct mod *mod, struct stream *s, int width, int height, int bpp);
|
2018-10-16 07:42:13 +03:00
|
|
|
|
|
|
|
static int
|
2022-03-15 07:45:26 +03:00
|
|
|
send_server_monitor_full_invalidate(
|
|
|
|
struct mod *mod, struct stream *s, int width, int height);
|
2018-10-16 07:42:13 +03:00
|
|
|
|
|
|
|
static int
|
|
|
|
send_server_version_message(struct mod *v, struct stream *s);
|
|
|
|
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_mod_process_message(struct mod *mod, struct stream *s);
|
2006-02-04 22:00:34 +03:00
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
/******************************************************************************/
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_send_copy(struct mod *mod, struct stream *s)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
return trans_write_copy_s(mod->trans, s);
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_start(struct mod *mod, int w, int h, int bpp)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_start");
|
2012-09-20 07:51:34 +04:00
|
|
|
mod->width = w;
|
|
|
|
mod->height = h;
|
|
|
|
mod->bpp = bpp;
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_start");
|
2012-09-20 07:51:34 +04:00
|
|
|
return 0;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
2013-10-02 09:42:12 +04:00
|
|
|
/******************************************************************************/
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2013-10-02 09:42:12 +04:00
|
|
|
lib_mod_log_peer(struct mod *mod)
|
|
|
|
{
|
|
|
|
int my_pid;
|
|
|
|
int pid;
|
|
|
|
int uid;
|
|
|
|
int gid;
|
|
|
|
|
2013-10-02 22:56:09 +04:00
|
|
|
my_pid = g_getpid();
|
2015-07-11 06:38:27 +03:00
|
|
|
if (g_sck_get_peer_cred(mod->trans->sck, &pid, &uid, &gid) == 0)
|
2013-10-02 09:42:12 +04:00
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_INFO, "lib_mod_log_peer: xrdp_pid=%d connected "
|
2023-01-05 14:17:35 +03:00
|
|
|
"to Xorg_pid=%d Xorg_uid=%d Xorg_gid=%d "
|
2022-04-22 13:56:23 +03:00
|
|
|
"client=%s",
|
2021-02-09 05:43:44 +03:00
|
|
|
my_pid, pid, uid, gid,
|
2022-04-22 13:56:23 +03:00
|
|
|
mod->client_info.client_description);
|
2013-10-02 09:42:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_ERROR, "lib_mod_log_peer: g_sck_get_peer_cred "
|
|
|
|
"failed");
|
2013-10-02 09:42:12 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
/******************************************************************************/
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_data_in(struct trans *trans)
|
|
|
|
{
|
|
|
|
struct mod *self;
|
|
|
|
struct stream *s;
|
|
|
|
int len;
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_data_in:");
|
2015-07-11 06:38:27 +03:00
|
|
|
if (trans == 0)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
self = (struct mod *)(trans->callback_data);
|
|
|
|
s = trans_get_in_s(trans);
|
|
|
|
|
|
|
|
if (s == 0)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (trans->extra_flags)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
s->p = s->data;
|
|
|
|
in_uint8s(s, 4); /* processed later in lib_mod_process_message */
|
|
|
|
in_uint32_le(s, len);
|
|
|
|
if (len < 0 || len > 128 * 1024)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_ERROR, "lib_data_in: bad size");
|
2015-07-11 06:38:27 +03:00
|
|
|
return 1;
|
|
|
|
}
|
2015-07-19 08:48:07 +03:00
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
trans->header_size = len + 8;
|
|
|
|
trans->extra_flags = 2;
|
|
|
|
break;
|
|
|
|
}
|
2021-02-09 05:43:44 +03:00
|
|
|
/* fall through */
|
2015-07-11 06:38:27 +03:00
|
|
|
case 2:
|
|
|
|
s->p = s->data;
|
|
|
|
if (lib_mod_process_message(self, s) != 0)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_ERROR, "lib_data_in: lib_mod_process_message failed");
|
2015-07-11 06:38:27 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
init_stream(s, 0);
|
|
|
|
trans->header_size = 8;
|
|
|
|
trans->extra_flags = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-04 22:00:34 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_connect(struct mod *mod)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int error;
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
int socket_mode;
|
2012-09-20 07:51:34 +04:00
|
|
|
struct stream *s;
|
|
|
|
char con_port[256];
|
|
|
|
|
|
|
|
mod->server_msg(mod, "started connecting", 0);
|
|
|
|
|
2014-06-11 04:49:15 +04:00
|
|
|
/* only support 8, 15, 16, 24, and 32 bpp connections from rdp client */
|
2022-03-15 07:45:26 +03:00
|
|
|
if (mod->bpp != 8
|
|
|
|
&& mod->bpp != 15
|
|
|
|
&& mod->bpp != 16
|
|
|
|
&& mod->bpp != 24
|
|
|
|
&& mod->bpp != 32)
|
2012-03-16 08:42:39 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
mod->server_msg(mod,
|
2022-03-15 07:45:26 +03:00
|
|
|
"error - only supporting 8, 15, 16, 24, and 32"
|
|
|
|
" bpp rdp connections", 0);
|
2012-09-20 07:51:34 +04:00
|
|
|
return 1;
|
2012-03-16 08:42:39 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
make_stream(s);
|
|
|
|
g_sprintf(con_port, "%s", mod->port);
|
|
|
|
|
2014-03-23 03:51:30 +04:00
|
|
|
error = 0;
|
2012-09-20 07:51:34 +04:00
|
|
|
mod->sck_closed = 0;
|
|
|
|
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
if (con_port[0] == '/')
|
2009-08-17 23:36:08 +04:00
|
|
|
{
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
socket_mode = TRANS_MODE_UNIX;
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_INFO, "lib_mod_connect: connecting via UNIX socket");
|
2015-07-11 06:38:27 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
socket_mode = TRANS_MODE_TCP;
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG(LOG_LEVEL_INFO, "lib_mod_connect: connecting via TCP socket");
|
2022-04-20 11:40:36 +03:00
|
|
|
if (g_strcmp(mod->ip, "") == 0)
|
|
|
|
{
|
|
|
|
mod->server_msg(mod, "error - no ip set", 0);
|
|
|
|
free_stream(s);
|
|
|
|
return 1;
|
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
mod->trans = trans_create(socket_mode, 8 * 8192, 8192);
|
|
|
|
if (mod->trans == 0)
|
|
|
|
{
|
|
|
|
free_stream(s);
|
|
|
|
return 1;
|
|
|
|
}
|
2020-08-07 13:48:22 +03:00
|
|
|
mod->trans->si = mod->si;
|
2015-07-11 11:18:02 +03:00
|
|
|
mod->trans->my_source = XRDP_SOURCE_MOD;
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
mod->trans->is_term = mod->server_is_term;
|
2015-07-11 11:18:02 +03:00
|
|
|
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
/* Give the X server a bit of time to start */
|
|
|
|
if (trans_connect(mod->trans, mod->ip, con_port, 30 * 1000) == 0)
|
2015-07-11 06:38:27 +03:00
|
|
|
{
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_INFO, "lib_mod_connect: connected to Xserver "
|
2023-01-05 14:17:35 +03:00
|
|
|
"(Xorg) sck %lld",
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
(long long) (mod->trans->sck));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mod->server_msg(mod, "connection problem, giving up", 0);
|
|
|
|
error = 1;
|
2009-08-17 23:36:08 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
if (error == 0 && socket_mode == TRANS_MODE_UNIX)
|
2013-10-02 09:42:12 +04:00
|
|
|
{
|
Rework transport connect logic
There are a number of ways the existing transport connect logic in
trans_connect could be improved for POSIX compatibility, and also
slightly tidied up:-
1) The same socket is re-used for multiple connect attempts following
failure which isn't behaviour defined by POSIX.1-2017 (although it
works on Linux).
2) An asynchronous connect is started, and then after a short
delay connect() is called again on the same socket. POSIX.1-2017
is clear that in this situation EALREADY is returned before the
connection is established, but is silent on the behaviour expected
when the connection is established. Returning success is an option,
but so is returning EISCONN. The current code assumes the connect()
call will succeed.
3) The code contains two virtually identical, quite complex loops for
TCP and UNIX sockets, differing only in the calls to create a socket
and connect it.
4) trans_connect() contains looping and retry logic, but this isn't
seen as sufficient by the chansrv connect code in xrdp/xrdp_mm.c and
the Xorg connect code in xup/xup.c. Both of these implement their own
looping and retry logic on top of the logic in trans_connect(),
resulting in slightly unpredictable behaviour with regard to
timeouts.
5) A socket number can technically be zero, but in a couple of places
this isn't allowed for.
This PR attempts to correct the implementation of trans_connect(),
and also to simplify the areas it is called from.
As part of the PR, the signature of the server_is_term member of the
xrdp module interface is changed to match the signature expected by the
is_term member of a struct trans. This allows for trans_connect()
in xrdp modules to directly access g_is_term() within the main xrdp
executable. At the moment this functionality is only used by the xup
module.
2022-03-31 16:33:06 +03:00
|
|
|
lib_mod_log_peer(mod);
|
2013-10-02 09:42:12 +04:00
|
|
|
}
|
|
|
|
|
2009-08-17 23:36:08 +04:00
|
|
|
if (error == 0)
|
|
|
|
{
|
2018-10-16 07:42:13 +03:00
|
|
|
error = send_server_version_message(mod, s);
|
2009-08-17 23:36:08 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
if (error == 0)
|
2009-08-17 23:36:08 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
/* send screen size message */
|
2022-03-15 07:45:26 +03:00
|
|
|
error = send_server_monitor_resize(
|
|
|
|
mod, s, mod->width, mod->height, mod->bpp);
|
2009-08-17 23:36:08 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
if (error == 0)
|
|
|
|
{
|
2022-03-15 07:45:26 +03:00
|
|
|
error = send_server_monitor_full_invalidate(
|
|
|
|
mod, s, mod->width, mod->height);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
free_stream(s);
|
|
|
|
|
|
|
|
if (error != 0)
|
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
trans_delete(mod->trans);
|
|
|
|
mod->trans = 0;
|
2012-09-20 07:51:34 +04:00
|
|
|
mod->server_msg(mod, "some problem", 0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mod->server_msg(mod, "connected ok", 0);
|
2015-07-11 06:38:27 +03:00
|
|
|
mod->trans->trans_data_in = lib_data_in;
|
|
|
|
mod->trans->header_size = 8;
|
|
|
|
mod->trans->callback_data = mod;
|
|
|
|
mod->trans->no_stream_init_on_data_in = 1;
|
|
|
|
mod->trans->extra_flags = 1;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_connect");
|
2012-09-20 07:51:34 +04:00
|
|
|
return 0;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2,
|
2008-06-30 09:02:47 +04:00
|
|
|
tbus param3, tbus param4)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
struct stream *s;
|
|
|
|
int len;
|
|
|
|
int key;
|
|
|
|
int rv;
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_event");
|
2012-09-20 07:51:34 +04:00
|
|
|
make_stream(s);
|
|
|
|
|
|
|
|
if ((msg >= 15) && (msg <= 16)) /* key events */
|
2011-11-13 04:40:08 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
key = param2;
|
|
|
|
|
|
|
|
if (key > 0)
|
2011-11-13 04:40:08 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
if (key == 65027) /* altgr */
|
|
|
|
{
|
|
|
|
if (mod->shift_state)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "special");
|
2012-09-20 07:51:34 +04:00
|
|
|
/* fix for mstsc sending left control down with altgr */
|
|
|
|
/* control down / up
|
|
|
|
msg param1 param2 param3 param4
|
|
|
|
15 0 65507 29 0
|
|
|
|
16 0 65507 29 49152 */
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 103);
|
|
|
|
out_uint32_le(s, 16); /* key up */
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
out_uint32_le(s, 65507); /* left control */
|
|
|
|
out_uint32_le(s, 29); /* RDP scan code */
|
|
|
|
out_uint32_le(s, 0xc000); /* flags */
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_send_copy(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key == 65507) /* left control */
|
|
|
|
{
|
|
|
|
mod->shift_state = msg == 15;
|
|
|
|
}
|
2011-11-13 04:40:08 +04:00
|
|
|
}
|
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 103);
|
|
|
|
out_uint32_le(s, msg);
|
|
|
|
out_uint32_le(s, param1);
|
|
|
|
out_uint32_le(s, param2);
|
|
|
|
out_uint32_le(s, param3);
|
|
|
|
out_uint32_le(s, param4);
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
2015-07-11 06:38:27 +03:00
|
|
|
rv = lib_send_copy(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
free_stream(s);
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_event");
|
2012-09-20 07:51:34 +04:00
|
|
|
return rv;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_fill_rect(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
rv = mod->server_fill_rect(mod, x, y, cx, cy);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_screen_blt(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
|
|
|
rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_paint_rect(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int len_bmpdata;
|
|
|
|
char *bmpdata;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint32_le(s, len_bmpdata);
|
|
|
|
in_uint8p(s, bmpdata, len_bmpdata);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
|
|
|
rv = mod->server_paint_rect(mod, x, y, cx, cy,
|
|
|
|
bmpdata, width, height,
|
|
|
|
srcx, srcy);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_clip(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
rv = mod->server_set_clip(mod, x, y, cx, cy);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_reset_clip(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = mod->server_reset_clip(mod);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_fgcolor(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int fgcolor;
|
|
|
|
|
|
|
|
in_uint32_le(s, fgcolor);
|
|
|
|
rv = mod->server_set_fgcolor(mod, fgcolor);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_bgcolor(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int bgcolor;
|
|
|
|
|
|
|
|
in_uint32_le(s, bgcolor);
|
|
|
|
rv = mod->server_set_bgcolor(mod, bgcolor);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_opcode(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int opcode;
|
|
|
|
|
|
|
|
in_uint16_le(s, opcode);
|
|
|
|
rv = mod->server_set_opcode(mod, opcode);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_pen(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int style;
|
|
|
|
int width;
|
|
|
|
|
|
|
|
in_uint16_le(s, style);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
rv = mod->server_set_pen(mod, style, width);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_draw_line(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x1;
|
|
|
|
int y1;
|
|
|
|
int x2;
|
|
|
|
int y2;
|
|
|
|
|
|
|
|
in_sint16_le(s, x1);
|
|
|
|
in_sint16_le(s, y1);
|
|
|
|
in_sint16_le(s, x2);
|
|
|
|
in_sint16_le(s, y2);
|
|
|
|
rv = mod->server_draw_line(mod, x1, y1, x2, y2);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_cursor(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
char cur_data[32 * (32 * 3)];
|
|
|
|
char cur_mask[32 * (32 / 8)];
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint8a(s, cur_data, 32 * (32 * 3));
|
|
|
|
in_uint8a(s, cur_mask, 32 * (32 / 8));
|
|
|
|
rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_create_os_surface(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int rdpid;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
in_uint32_le(s, rdpid);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
rv = mod->server_create_os_surface(mod, rdpid, width, height);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_switch_os_surface(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int rdpid;
|
|
|
|
|
|
|
|
in_uint32_le(s, rdpid);
|
|
|
|
rv = mod->server_switch_os_surface(mod, rdpid);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_delete_os_surface(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int rdpid;
|
|
|
|
|
|
|
|
in_uint32_le(s, rdpid);
|
|
|
|
rv = mod->server_delete_os_surface(mod, rdpid);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_paint_rect_os(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int rdpid;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint32_le(s, rdpid);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
|
|
|
rv = mod->server_paint_rect_os(mod, x, y, cx, cy,
|
|
|
|
rdpid, srcx, srcy);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_set_hints(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int hints;
|
|
|
|
int mask;
|
|
|
|
|
|
|
|
in_uint32_le(s, hints);
|
|
|
|
in_uint32_le(s, mask);
|
|
|
|
rv = mod->server_set_hints(mod, hints, mask);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-07-31 22:12:00 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2012-09-20 07:51:34 +04:00
|
|
|
process_server_window_new_update(struct mod *mod, struct stream *s)
|
2012-07-31 22:12:00 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int flags;
|
|
|
|
int window_id;
|
|
|
|
int title_bytes;
|
|
|
|
int index;
|
|
|
|
int bytes;
|
|
|
|
int rv;
|
|
|
|
struct rail_window_state_order rwso;
|
|
|
|
|
|
|
|
g_memset(&rwso, 0, sizeof(rwso));
|
|
|
|
in_uint32_le(s, window_id);
|
|
|
|
in_uint32_le(s, rwso.owner_window_id);
|
|
|
|
in_uint32_le(s, rwso.style);
|
|
|
|
in_uint32_le(s, rwso.extended_style);
|
|
|
|
in_uint32_le(s, rwso.show_state);
|
|
|
|
in_uint16_le(s, title_bytes);
|
|
|
|
|
|
|
|
if (title_bytes > 0)
|
2012-07-31 22:12:00 +04:00
|
|
|
{
|
2016-06-22 02:30:18 +03:00
|
|
|
rwso.title_info = g_new(char, title_bytes + 1);
|
2012-09-20 07:51:34 +04:00
|
|
|
in_uint8a(s, rwso.title_info, title_bytes);
|
|
|
|
rwso.title_info[title_bytes] = 0;
|
2012-07-31 22:12:00 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
in_uint32_le(s, rwso.client_offset_x);
|
|
|
|
in_uint32_le(s, rwso.client_offset_y);
|
|
|
|
in_uint32_le(s, rwso.client_area_width);
|
|
|
|
in_uint32_le(s, rwso.client_area_height);
|
|
|
|
in_uint32_le(s, rwso.rp_content);
|
|
|
|
in_uint32_le(s, rwso.root_parent_handle);
|
|
|
|
in_uint32_le(s, rwso.window_offset_x);
|
|
|
|
in_uint32_le(s, rwso.window_offset_y);
|
|
|
|
in_uint32_le(s, rwso.window_client_delta_x);
|
|
|
|
in_uint32_le(s, rwso.window_client_delta_y);
|
|
|
|
in_uint32_le(s, rwso.window_width);
|
|
|
|
in_uint32_le(s, rwso.window_height);
|
|
|
|
in_uint16_le(s, rwso.num_window_rects);
|
|
|
|
|
|
|
|
if (rwso.num_window_rects > 0)
|
|
|
|
{
|
|
|
|
bytes = sizeof(struct rail_window_rect) * rwso.num_window_rects;
|
|
|
|
rwso.window_rects = (struct rail_window_rect *)g_malloc(bytes, 0);
|
|
|
|
|
|
|
|
for (index = 0; index < rwso.num_window_rects; index++)
|
|
|
|
{
|
|
|
|
in_uint16_le(s, rwso.window_rects[index].left);
|
|
|
|
in_uint16_le(s, rwso.window_rects[index].top);
|
|
|
|
in_uint16_le(s, rwso.window_rects[index].right);
|
|
|
|
in_uint16_le(s, rwso.window_rects[index].bottom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
in_uint32_le(s, rwso.visible_offset_x);
|
|
|
|
in_uint32_le(s, rwso.visible_offset_y);
|
|
|
|
in_uint16_le(s, rwso.num_visibility_rects);
|
|
|
|
|
|
|
|
if (rwso.num_visibility_rects > 0)
|
2012-07-31 22:12:00 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
bytes = sizeof(struct rail_window_rect) * rwso.num_visibility_rects;
|
|
|
|
rwso.visibility_rects = (struct rail_window_rect *)g_malloc(bytes, 0);
|
|
|
|
|
|
|
|
for (index = 0; index < rwso.num_visibility_rects; index++)
|
|
|
|
{
|
|
|
|
in_uint16_le(s, rwso.visibility_rects[index].left);
|
|
|
|
in_uint16_le(s, rwso.visibility_rects[index].top);
|
|
|
|
in_uint16_le(s, rwso.visibility_rects[index].right);
|
|
|
|
in_uint16_le(s, rwso.visibility_rects[index].bottom);
|
|
|
|
}
|
2012-07-31 22:12:00 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
in_uint32_le(s, flags);
|
|
|
|
mod->server_window_new_update(mod, window_id, &rwso, flags);
|
|
|
|
rv = 0;
|
|
|
|
g_free(rwso.title_info);
|
|
|
|
g_free(rwso.window_rects);
|
|
|
|
g_free(rwso.visibility_rects);
|
|
|
|
return rv;
|
2012-07-31 22:12:00 +04:00
|
|
|
}
|
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_window_delete(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int window_id;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
in_uint32_le(s, window_id);
|
|
|
|
mod->server_window_delete(mod, window_id);
|
|
|
|
rv = 0;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-06-30 23:36:01 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2021-02-09 05:43:44 +03:00
|
|
|
process_server_window_show(struct mod *mod, struct stream *s)
|
2013-06-30 23:36:01 +04:00
|
|
|
{
|
|
|
|
int window_id;
|
|
|
|
int rv;
|
|
|
|
int flags;
|
|
|
|
struct rail_window_state_order rwso;
|
2014-01-28 22:40:19 +04:00
|
|
|
|
2013-06-30 23:36:01 +04:00
|
|
|
g_memset(&rwso, 0, sizeof(rwso));
|
|
|
|
in_uint32_le(s, window_id);
|
|
|
|
in_uint32_le(s, flags);
|
|
|
|
in_uint32_le(s, rwso.show_state);
|
|
|
|
mod->server_window_new_update(mod, window_id, &rwso, flags);
|
|
|
|
rv = 0;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-07-31 22:12:00 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_add_char(struct mod *mod, struct stream *s)
|
2012-07-31 22:12:00 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int rv;
|
2014-02-04 07:48:57 +04:00
|
|
|
int font;
|
2016-01-31 04:33:04 +03:00
|
|
|
int character;
|
2014-02-04 07:48:57 +04:00
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int len_bmpdata;
|
|
|
|
char *bmpdata;
|
2012-07-31 22:12:00 +04:00
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
in_uint16_le(s, font);
|
2016-01-31 04:33:04 +03:00
|
|
|
in_uint16_le(s, character);
|
2014-02-04 07:48:57 +04:00
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint16_le(s, len_bmpdata);
|
|
|
|
in_uint8p(s, bmpdata, len_bmpdata);
|
2016-01-31 04:33:04 +03:00
|
|
|
rv = mod->server_add_char(mod, font, character, x, y, cx, cy, bmpdata);
|
2014-02-04 07:48:57 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_add_char_alpha(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int font;
|
2016-01-31 04:33:04 +03:00
|
|
|
int character;
|
2014-02-04 07:48:57 +04:00
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int len_bmpdata;
|
|
|
|
char *bmpdata;
|
|
|
|
|
|
|
|
in_uint16_le(s, font);
|
2016-01-31 04:33:04 +03:00
|
|
|
in_uint16_le(s, character);
|
2014-02-04 07:48:57 +04:00
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint16_le(s, len_bmpdata);
|
|
|
|
in_uint8p(s, bmpdata, len_bmpdata);
|
2016-01-31 04:33:04 +03:00
|
|
|
rv = mod->server_add_char_alpha(mod, font, character, x, y, cx, cy,
|
2014-02-04 07:48:57 +04:00
|
|
|
bmpdata);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_draw_text(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int font;
|
|
|
|
int flags;
|
|
|
|
int mixmode;
|
|
|
|
int clip_left;
|
|
|
|
int clip_top;
|
|
|
|
int clip_right;
|
|
|
|
int clip_bottom;
|
|
|
|
int box_left;
|
|
|
|
int box_top;
|
|
|
|
int box_right;
|
|
|
|
int box_bottom;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int len_bmpdata;
|
|
|
|
char *bmpdata;
|
|
|
|
|
|
|
|
in_uint16_le(s, font);
|
|
|
|
in_uint16_le(s, flags);
|
|
|
|
in_uint16_le(s, mixmode);
|
|
|
|
in_sint16_le(s, clip_left);
|
|
|
|
in_sint16_le(s, clip_top);
|
|
|
|
in_sint16_le(s, clip_right);
|
|
|
|
in_sint16_le(s, clip_bottom);
|
|
|
|
in_sint16_le(s, box_left);
|
|
|
|
in_sint16_le(s, box_top);
|
|
|
|
in_sint16_le(s, box_right);
|
|
|
|
in_sint16_le(s, box_bottom);
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, len_bmpdata);
|
|
|
|
in_uint8p(s, bmpdata, len_bmpdata);
|
|
|
|
rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top,
|
|
|
|
clip_right, clip_bottom, box_left, box_top,
|
|
|
|
box_right, box_bottom, x, y, bmpdata, len_bmpdata);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_create_os_surface_bpp(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int rdpid;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int bpp;
|
|
|
|
|
|
|
|
in_uint32_le(s, rdpid);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
in_uint8(s, bpp);
|
|
|
|
rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_paint_rect_bpp(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int len_bmpdata;
|
|
|
|
char *bmpdata;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
|
|
|
int bpp;
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint32_le(s, len_bmpdata);
|
|
|
|
in_uint8p(s, bmpdata, len_bmpdata);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
|
|
|
in_uint8(s, bpp);
|
|
|
|
rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy,
|
|
|
|
bmpdata, width, height,
|
|
|
|
srcx, srcy, bpp);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
process_server_composite(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int srcidx;
|
|
|
|
int srcformat;
|
|
|
|
int srcwidth;
|
|
|
|
int srcrepeat;
|
|
|
|
int transform[10];
|
|
|
|
int mskflags;
|
|
|
|
int mskidx;
|
|
|
|
int mskformat;
|
|
|
|
int mskwidth;
|
|
|
|
int mskrepeat;
|
|
|
|
int op;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
|
|
|
int mskx;
|
|
|
|
int msky;
|
|
|
|
int dstx;
|
|
|
|
int dsty;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int dstformat;
|
|
|
|
|
|
|
|
in_uint16_le(s, srcidx);
|
|
|
|
in_uint32_le(s, srcformat);
|
|
|
|
in_uint16_le(s, srcwidth);
|
|
|
|
in_uint8(s, srcrepeat);
|
|
|
|
g_memcpy(transform, s->p, 40);
|
|
|
|
in_uint8s(s, 40);
|
|
|
|
in_uint8(s, mskflags);
|
|
|
|
in_uint16_le(s, mskidx);
|
|
|
|
in_uint32_le(s, mskformat);
|
|
|
|
in_uint16_le(s, mskwidth);
|
|
|
|
in_uint8(s, mskrepeat);
|
|
|
|
in_uint8(s, op);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
|
|
|
in_sint16_le(s, mskx);
|
|
|
|
in_sint16_le(s, msky);
|
|
|
|
in_sint16_le(s, dstx);
|
|
|
|
in_sint16_le(s, dsty);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
in_uint32_le(s, dstformat);
|
|
|
|
rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat,
|
|
|
|
transform, mskflags, mskidx, mskformat,
|
|
|
|
mskwidth, mskrepeat, op, srcx, srcy, mskx, msky,
|
|
|
|
dstx, dsty, width, height, dstformat);
|
2012-09-20 07:51:34 +04:00
|
|
|
return rv;
|
2012-07-31 22:12:00 +04:00
|
|
|
}
|
|
|
|
|
2013-03-19 10:43:17 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2013-03-19 10:43:17 +04:00
|
|
|
process_server_set_pointer_ex(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int bpp;
|
|
|
|
int Bpp;
|
|
|
|
char cur_data[32 * (32 * 4)];
|
|
|
|
char cur_mask[32 * (32 / 8)];
|
|
|
|
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, bpp);
|
|
|
|
Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8;
|
|
|
|
in_uint8a(s, cur_data, 32 * (32 * Bpp));
|
|
|
|
in_uint8a(s, cur_mask, 32 * (32 / 8));
|
|
|
|
rv = mod->server_set_cursor_ex(mod, x, y, cur_data, cur_mask, bpp);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2006-02-04 22:00:34 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2013-09-10 02:43:58 +04:00
|
|
|
send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy,
|
|
|
|
int frame_id)
|
2013-08-19 09:36:18 +04:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
make_stream(s);
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 105);
|
|
|
|
out_uint32_le(s, flags);
|
2013-09-10 02:43:58 +04:00
|
|
|
out_uint32_le(s, frame_id);
|
2013-08-19 09:36:18 +04:00
|
|
|
out_uint32_le(s, x);
|
|
|
|
out_uint32_le(s, y);
|
|
|
|
out_uint32_le(s, cx);
|
|
|
|
out_uint32_le(s, cy);
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_send_copy(mod, s);
|
2013-08-19 09:36:18 +04:00
|
|
|
free_stream(s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2015-07-11 06:38:27 +03:00
|
|
|
process_server_paint_rect_shmem(struct mod *amod, struct stream *s)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
2013-08-19 09:36:18 +04:00
|
|
|
int flags;
|
2014-02-04 07:48:57 +04:00
|
|
|
int frame_id;
|
2013-08-19 09:36:18 +04:00
|
|
|
int shmem_id;
|
|
|
|
int shmem_offset;
|
2014-02-04 07:48:57 +04:00
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int srcx;
|
|
|
|
int srcy;
|
2012-09-20 07:51:34 +04:00
|
|
|
char *bmpdata;
|
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, cx);
|
|
|
|
in_uint16_le(s, cy);
|
|
|
|
in_uint32_le(s, flags);
|
|
|
|
in_uint32_le(s, frame_id);
|
|
|
|
in_uint32_le(s, shmem_id);
|
|
|
|
in_uint32_le(s, shmem_offset);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
in_sint16_le(s, srcx);
|
|
|
|
in_sint16_le(s, srcy);
|
2014-07-29 05:13:07 +04:00
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
bmpdata = 0;
|
2014-07-29 05:13:07 +04:00
|
|
|
rv = 0;
|
2015-07-11 06:38:27 +03:00
|
|
|
if (amod->screen_shmem_id_mapped == 0)
|
2014-02-04 07:48:57 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
amod->screen_shmem_id = shmem_id;
|
2016-07-08 03:58:48 +03:00
|
|
|
amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
|
2021-02-09 05:43:44 +03:00
|
|
|
if (amod->screen_shmem_pixels == (void *) -1)
|
2014-02-04 07:48:57 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
/* failed */
|
|
|
|
amod->screen_shmem_id = 0;
|
|
|
|
amod->screen_shmem_pixels = 0;
|
|
|
|
amod->screen_shmem_id_mapped = 0;
|
2014-02-04 07:48:57 +04:00
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
else
|
2014-02-04 07:48:57 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
amod->screen_shmem_id_mapped = 1;
|
2014-02-04 07:48:57 +04:00
|
|
|
}
|
|
|
|
}
|
2019-11-08 10:28:07 +03:00
|
|
|
else if (amod->screen_shmem_id != shmem_id)
|
|
|
|
{
|
|
|
|
amod->screen_shmem_id = shmem_id;
|
|
|
|
g_shmdt(amod->screen_shmem_pixels);
|
|
|
|
amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
|
2021-02-09 05:43:44 +03:00
|
|
|
if (amod->screen_shmem_pixels == (void *) -1)
|
2019-11-08 10:28:07 +03:00
|
|
|
{
|
|
|
|
/* failed */
|
|
|
|
amod->screen_shmem_id = 0;
|
|
|
|
amod->screen_shmem_pixels = 0;
|
|
|
|
amod->screen_shmem_id_mapped = 0;
|
|
|
|
}
|
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
if (amod->screen_shmem_pixels != 0)
|
|
|
|
{
|
|
|
|
bmpdata = amod->screen_shmem_pixels + shmem_offset;
|
|
|
|
}
|
2014-02-04 07:48:57 +04:00
|
|
|
if (bmpdata != 0)
|
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
rv = amod->server_paint_rect(amod, x, y, cx, cy,
|
|
|
|
bmpdata, width, height,
|
|
|
|
srcx, srcy);
|
2014-02-04 07:48:57 +04:00
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
send_paint_rect_ack(amod, flags, x, y, cx, cy, frame_id);
|
2014-02-04 07:48:57 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-02-10 06:05:47 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-10 06:05:47 +04:00
|
|
|
send_paint_rect_ex_ack(struct mod *mod, int flags, int frame_id)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
make_stream(s);
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 106);
|
|
|
|
out_uint32_le(s, flags);
|
|
|
|
out_uint32_le(s, frame_id);
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_send_copy(mod, s);
|
2014-02-10 06:05:47 +04:00
|
|
|
free_stream(s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-08 03:56:05 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
send_suppress_output(struct mod *mod, int suppress,
|
|
|
|
int left, int top, int right, int bottom)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
make_stream(s);
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 108);
|
|
|
|
out_uint32_le(s, suppress);
|
|
|
|
out_uint32_le(s, left);
|
|
|
|
out_uint32_le(s, top);
|
|
|
|
out_uint32_le(s, right);
|
|
|
|
out_uint32_le(s, bottom);
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
|
|
|
lib_send_copy(mod, s);
|
|
|
|
free_stream(s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-10 06:05:47 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-19 00:10:05 +04:00
|
|
|
process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
|
2014-02-10 06:05:47 +04:00
|
|
|
{
|
2023-03-14 08:53:22 +03:00
|
|
|
LOG(LOG_LEVEL_TRACE, "process_server_paint_rect_shmem_ex:");
|
|
|
|
|
2014-02-19 00:10:05 +04:00
|
|
|
int num_drects;
|
|
|
|
int num_crects;
|
2014-02-10 06:05:47 +04:00
|
|
|
int flags;
|
|
|
|
int frame_id;
|
|
|
|
int shmem_id;
|
|
|
|
int shmem_offset;
|
|
|
|
int width;
|
|
|
|
int height;
|
2014-02-19 00:10:05 +04:00
|
|
|
int index;
|
|
|
|
int rv;
|
|
|
|
tsi16 *ldrects;
|
|
|
|
tsi16 *ldrects1;
|
|
|
|
tsi16 *lcrects;
|
|
|
|
tsi16 *lcrects1;
|
|
|
|
char *bmpdata;
|
2014-02-10 06:05:47 +04:00
|
|
|
|
2014-02-19 00:10:05 +04:00
|
|
|
/* dirty pixels */
|
|
|
|
in_uint16_le(s, num_drects);
|
|
|
|
ldrects = (tsi16 *) g_malloc(2 * 4 * num_drects, 0);
|
|
|
|
ldrects1 = ldrects;
|
|
|
|
for (index = 0; index < num_drects; index++)
|
|
|
|
{
|
|
|
|
in_sint16_le(s, ldrects1[0]);
|
|
|
|
in_sint16_le(s, ldrects1[1]);
|
|
|
|
in_sint16_le(s, ldrects1[2]);
|
|
|
|
in_sint16_le(s, ldrects1[3]);
|
|
|
|
ldrects1 += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copied pixels */
|
|
|
|
in_uint16_le(s, num_crects);
|
|
|
|
lcrects = (tsi16 *) g_malloc(2 * 4 * num_crects, 0);
|
|
|
|
lcrects1 = lcrects;
|
|
|
|
for (index = 0; index < num_crects; index++)
|
|
|
|
{
|
|
|
|
in_sint16_le(s, lcrects1[0]);
|
|
|
|
in_sint16_le(s, lcrects1[1]);
|
|
|
|
in_sint16_le(s, lcrects1[2]);
|
|
|
|
in_sint16_le(s, lcrects1[3]);
|
|
|
|
lcrects1 += 4;
|
|
|
|
}
|
2014-02-10 06:05:47 +04:00
|
|
|
|
|
|
|
in_uint32_le(s, flags);
|
|
|
|
in_uint32_le(s, frame_id);
|
|
|
|
in_uint32_le(s, shmem_id);
|
|
|
|
in_uint32_le(s, shmem_offset);
|
|
|
|
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
2014-03-01 07:28:31 +04:00
|
|
|
|
2014-02-19 00:10:05 +04:00
|
|
|
bmpdata = 0;
|
|
|
|
if (flags == 0) /* screen */
|
|
|
|
{
|
2021-11-30 13:55:03 +03:00
|
|
|
/* Do we need to map (or remap) the memory
|
|
|
|
* area shared with the X server ? */
|
|
|
|
if (amod->screen_shmem_id_mapped == 0 ||
|
|
|
|
amod->screen_shmem_id != shmem_id)
|
2014-02-19 00:10:05 +04:00
|
|
|
{
|
2021-11-30 13:55:03 +03:00
|
|
|
if (amod->screen_shmem_id_mapped != 0)
|
|
|
|
{
|
|
|
|
g_shmdt(amod->screen_shmem_pixels);
|
|
|
|
}
|
|
|
|
amod->screen_shmem_pixels = (char *) g_shmat(shmem_id);
|
2021-02-09 05:43:44 +03:00
|
|
|
if (amod->screen_shmem_pixels == (void *) -1)
|
2015-02-10 06:26:04 +03:00
|
|
|
{
|
|
|
|
/* failed */
|
2021-11-30 13:55:03 +03:00
|
|
|
if (amod->screen_shmem_id_mapped == 0)
|
|
|
|
{
|
|
|
|
LOG(LOG_LEVEL_ERROR,
|
|
|
|
"Can't attach to shared memory id %d [%s]",
|
|
|
|
shmem_id, g_get_strerror());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG(LOG_LEVEL_ERROR,
|
|
|
|
"Can't attach to shared memory id %d from id %d [%s]",
|
|
|
|
shmem_id, amod->screen_shmem_id, g_get_strerror());
|
|
|
|
}
|
2015-02-10 06:26:04 +03:00
|
|
|
amod->screen_shmem_id = 0;
|
|
|
|
amod->screen_shmem_pixels = 0;
|
|
|
|
amod->screen_shmem_id_mapped = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-30 13:55:03 +03:00
|
|
|
amod->screen_shmem_id = shmem_id;
|
2015-02-10 06:26:04 +03:00
|
|
|
amod->screen_shmem_id_mapped = 1;
|
|
|
|
}
|
2014-02-19 00:10:05 +04:00
|
|
|
}
|
2021-11-30 13:55:03 +03:00
|
|
|
|
2014-02-19 00:10:05 +04:00
|
|
|
if (amod->screen_shmem_pixels != 0)
|
|
|
|
{
|
|
|
|
bmpdata = amod->screen_shmem_pixels + shmem_offset;
|
|
|
|
}
|
|
|
|
}
|
2021-11-30 13:55:03 +03:00
|
|
|
else
|
2014-02-19 00:10:05 +04:00
|
|
|
{
|
2021-11-30 13:55:03 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_ERROR, "process_server_paint_rect_shmem_ex:"
|
|
|
|
" flags=%d frame_id=%d, shmem_id=%d, shmem_offset=%d,"
|
|
|
|
" width=%d, height=%d",
|
|
|
|
flags, frame_id, shmem_id, shmem_offset,
|
|
|
|
width, height);
|
|
|
|
}
|
2014-03-01 07:28:31 +04:00
|
|
|
|
2021-11-30 13:55:03 +03:00
|
|
|
if (bmpdata != 0)
|
|
|
|
{
|
2014-02-19 00:10:05 +04:00
|
|
|
rv = amod->server_paint_rects(amod, num_drects, ldrects,
|
|
|
|
num_crects, lcrects,
|
2014-03-23 03:51:30 +04:00
|
|
|
bmpdata, width, height,
|
|
|
|
flags, frame_id);
|
2014-02-19 00:10:05 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rv = 1;
|
|
|
|
}
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
//LOG_DEVEL(LOG_LEVEL_TRACE, "frame_id %d", frame_id);
|
2014-03-23 03:51:30 +04:00
|
|
|
//send_paint_rect_ex_ack(amod, flags, frame_id);
|
2014-02-10 06:05:47 +04:00
|
|
|
|
2014-02-19 00:10:05 +04:00
|
|
|
g_free(lcrects);
|
|
|
|
g_free(ldrects);
|
2014-02-10 06:05:47 +04:00
|
|
|
|
2016-05-07 04:17:56 +03:00
|
|
|
return rv;
|
2014-02-10 06:05:47 +04:00
|
|
|
}
|
|
|
|
|
2022-07-14 11:46:38 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
process_server_set_pointer_shmfd(struct mod *amod, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int bpp;
|
|
|
|
int Bpp;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int fd;
|
|
|
|
int recv_bytes;
|
|
|
|
int shmembytes;
|
|
|
|
unsigned int num_fds;
|
|
|
|
void *shmemptr;
|
|
|
|
char *cur_data;
|
|
|
|
char *cur_mask;
|
|
|
|
char msg[4];
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
in_sint16_le(s, x);
|
|
|
|
in_sint16_le(s, y);
|
|
|
|
in_uint16_le(s, bpp);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
fd = -1;
|
|
|
|
num_fds = -1;
|
|
|
|
if (g_tcp_can_recv(amod->trans->sck, 5000) == 0)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
recv_bytes = g_sck_recv_fd_set(amod->trans->sck, msg, 4, &fd, 1, &num_fds);
|
|
|
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_server_set_pointer_shmfd: "
|
|
|
|
"g_sck_recv_fd_set rv %d fd %d", recv_bytes, fd);
|
|
|
|
if (recv_bytes == 4)
|
|
|
|
{
|
|
|
|
if (num_fds == 1)
|
|
|
|
{
|
|
|
|
Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8;
|
|
|
|
shmembytes = width * height * Bpp + width * height / 8;
|
|
|
|
if (g_file_map(fd, 1, 1, shmembytes, &shmemptr) == 0)
|
|
|
|
{
|
|
|
|
cur_data = (char *)shmemptr;
|
|
|
|
cur_mask = cur_data + width * height * Bpp;
|
|
|
|
rv = amod->server_set_pointer_large(amod, x, y,
|
|
|
|
cur_data, cur_mask,
|
|
|
|
bpp, width, height);
|
|
|
|
g_munmap(shmemptr, shmembytes);
|
|
|
|
}
|
|
|
|
g_file_close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2023-05-28 10:52:26 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
process_server_paint_rect_shmfd(struct mod *amod, struct stream *s)
|
|
|
|
{
|
|
|
|
int num_drects;
|
|
|
|
int num_crects;
|
|
|
|
int flags;
|
|
|
|
int frame_id;
|
|
|
|
int shmem_bytes;
|
|
|
|
int shmem_offset;
|
|
|
|
int left;
|
|
|
|
int top;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int index;
|
|
|
|
int rv;
|
|
|
|
int16_t *ldrects;
|
|
|
|
int16_t *ldrects1;
|
|
|
|
int16_t *lcrects;
|
|
|
|
int16_t *lcrects1;
|
|
|
|
char *bmpdata;
|
|
|
|
int fd;
|
|
|
|
int recv_bytes;
|
|
|
|
unsigned int num_fds;
|
|
|
|
void *shmem_ptr;
|
|
|
|
char msg[4];
|
|
|
|
|
|
|
|
/* dirty pixels */
|
|
|
|
in_uint16_le(s, num_drects);
|
|
|
|
ldrects = g_new(int16_t, 2 * 4 * num_drects);
|
|
|
|
ldrects1 = ldrects;
|
|
|
|
for (index = 0; index < num_drects; index++)
|
|
|
|
{
|
|
|
|
in_sint16_le(s, ldrects1[0]);
|
|
|
|
in_sint16_le(s, ldrects1[1]);
|
|
|
|
in_sint16_le(s, ldrects1[2]);
|
|
|
|
in_sint16_le(s, ldrects1[3]);
|
|
|
|
ldrects1 += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copied pixels */
|
|
|
|
in_uint16_le(s, num_crects);
|
|
|
|
lcrects = g_new(int16_t, 2 * 4 * num_crects);
|
|
|
|
lcrects1 = lcrects;
|
|
|
|
for (index = 0; index < num_crects; index++)
|
|
|
|
{
|
|
|
|
in_sint16_le(s, lcrects1[0]);
|
|
|
|
in_sint16_le(s, lcrects1[1]);
|
|
|
|
in_sint16_le(s, lcrects1[2]);
|
|
|
|
in_sint16_le(s, lcrects1[3]);
|
|
|
|
lcrects1 += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
in_uint32_le(s, flags);
|
|
|
|
in_uint32_le(s, frame_id);
|
|
|
|
in_uint32_le(s, shmem_bytes);
|
|
|
|
in_uint32_le(s, shmem_offset);
|
|
|
|
|
|
|
|
in_uint16_le(s, left);
|
|
|
|
in_uint16_le(s, top);
|
|
|
|
in_uint16_le(s, width);
|
|
|
|
in_uint16_le(s, height);
|
|
|
|
|
|
|
|
if (g_tcp_can_recv(amod->trans->sck, 5000) == 0)
|
|
|
|
{
|
|
|
|
g_free(ldrects);
|
|
|
|
g_free(lcrects);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
rv = 1;
|
|
|
|
recv_bytes = g_sck_recv_fd_set(amod->trans->sck, msg, 4, &fd, 1, &num_fds);
|
|
|
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_server_paint_rect_shmfd: "
|
|
|
|
"g_sck_recv_fd_set rv %d fd %d", recv_bytes, fd);
|
|
|
|
if (recv_bytes == 4)
|
|
|
|
{
|
|
|
|
if (num_fds == 1)
|
|
|
|
{
|
|
|
|
if (g_file_map(fd, 1, 1, shmem_bytes, &shmem_ptr) == 0)
|
|
|
|
{
|
|
|
|
bmpdata = (char *)shmem_ptr;
|
|
|
|
bmpdata += shmem_offset;
|
|
|
|
rv = amod->server_paint_rects_ex(amod, num_drects, ldrects,
|
|
|
|
num_crects, lcrects, bmpdata,
|
|
|
|
left, top, width, height,
|
|
|
|
flags, frame_id);
|
|
|
|
g_munmap(shmem_ptr, shmem_bytes);
|
|
|
|
}
|
|
|
|
g_file_close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_free(ldrects);
|
|
|
|
g_free(lcrects);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2018-10-16 07:42:13 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
send_server_version_message(struct mod *mod, struct stream *s)
|
|
|
|
{
|
|
|
|
/* send version message */
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 103);
|
|
|
|
out_uint32_le(s, 301);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
out_uint32_le(s, 1);
|
|
|
|
s_mark_end(s);
|
|
|
|
int len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
|
|
|
int rv = lib_send_copy(mod, s);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
2022-03-15 07:45:26 +03:00
|
|
|
send_server_monitor_resize(
|
|
|
|
struct mod *mod, struct stream *s, int width, int height, int bpp)
|
2018-10-16 07:42:13 +03:00
|
|
|
{
|
|
|
|
/* send screen size message */
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 103);
|
|
|
|
out_uint32_le(s, 300);
|
|
|
|
out_uint32_le(s, width);
|
|
|
|
out_uint32_le(s, height);
|
|
|
|
/*
|
2022-03-15 07:45:26 +03:00
|
|
|
TODO: The bpp here is only necessary for initial creation. We should
|
|
|
|
modify XUP to require this only on server initialization, but not on
|
|
|
|
resize. Microsoft's RDP protocol does not support changing
|
2018-10-16 07:42:13 +03:00
|
|
|
the bpp on resize.
|
|
|
|
*/
|
|
|
|
out_uint32_le(s, bpp);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
s_mark_end(s);
|
|
|
|
int len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
|
|
|
int rv = lib_send_copy(mod, s);
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_resize:"
|
|
|
|
" sent resize message with following properties to"
|
|
|
|
" xorgxrdp backend width=%d, height=%d, bpp=%d, return value=%d",
|
2021-05-08 19:58:11 +03:00
|
|
|
width, height, bpp, rv);
|
2018-10-16 07:42:13 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-03-15 07:45:26 +03:00
|
|
|
send_server_monitor_full_invalidate(
|
|
|
|
struct mod *mod, struct stream *s, int width, int height)
|
2018-10-16 07:42:13 +03:00
|
|
|
{
|
|
|
|
/* send invalidate message */
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 103);
|
|
|
|
out_uint32_le(s, 200);
|
|
|
|
/* x and y */
|
|
|
|
int i = 0;
|
|
|
|
out_uint32_le(s, i);
|
|
|
|
/* width and height */
|
|
|
|
i = ((width & 0xffff) << 16) | height;
|
|
|
|
out_uint32_le(s, i);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
out_uint32_le(s, 0);
|
|
|
|
s_mark_end(s);
|
|
|
|
int len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
|
|
|
int rv = lib_send_copy(mod, s);
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_full_invalidate:"
|
|
|
|
" sent invalidate message with following"
|
|
|
|
" properties to xorgxrdp backend"
|
|
|
|
" width=%d, height=%d, return value=%d",
|
2021-05-08 19:58:11 +03:00
|
|
|
width, height, rv);
|
2018-10-16 07:42:13 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
lib_send_server_version_message(struct mod *mod)
|
|
|
|
{
|
|
|
|
/* send server version message */
|
|
|
|
struct stream *s;
|
|
|
|
make_stream(s);
|
|
|
|
int rv = send_server_version_message(mod, s);
|
|
|
|
free_stream(s);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
lib_send_server_monitor_resize(struct mod *mod, int width, int height)
|
|
|
|
{
|
|
|
|
/* send screen size message */
|
|
|
|
struct stream *s;
|
|
|
|
make_stream(s);
|
|
|
|
int rv = send_server_monitor_resize(mod, s, width, height, mod->bpp);
|
|
|
|
free_stream(s);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
static int
|
|
|
|
lib_send_server_monitor_full_invalidate(struct mod *mod, int width, int height)
|
|
|
|
{
|
|
|
|
/* send invalidate message */
|
|
|
|
struct stream *s;
|
|
|
|
make_stream(s);
|
|
|
|
int rv = send_server_monitor_full_invalidate(mod, s, width, height);
|
|
|
|
free_stream(s);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-02-04 07:48:57 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2014-02-04 07:48:57 +04:00
|
|
|
lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
|
|
|
{
|
|
|
|
int rv;
|
2012-09-20 07:51:34 +04:00
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "lib_mod_process_orders: type %d", type);
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = 0;
|
2012-09-20 07:51:34 +04:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 1: /* server_begin_update */
|
|
|
|
rv = mod->server_begin_update(mod);
|
|
|
|
break;
|
|
|
|
case 2: /* server_end_update */
|
|
|
|
rv = mod->server_end_update(mod);
|
|
|
|
break;
|
|
|
|
case 3: /* server_fill_rect */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_fill_rect(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 4: /* server_screen_blt */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_screen_blt(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 5: /* server_paint_rect */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_paint_rect(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 10: /* server_set_clip */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_set_clip(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 11: /* server_reset_clip */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_reset_clip(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 12: /* server_set_fgcolor */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_set_fgcolor(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
2013-06-28 03:23:12 +04:00
|
|
|
case 13: /* server_set_bgcolor */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_set_bgcolor(mod, s);
|
|
|
|
break;
|
|
|
|
case 14: /* server_set_opcode */
|
|
|
|
rv = process_server_set_opcode(mod, s);
|
|
|
|
break;
|
|
|
|
case 17: /* server_set_pen */
|
|
|
|
rv = process_server_set_pen(mod, s);
|
|
|
|
break;
|
|
|
|
case 18: /* server_draw_line */
|
|
|
|
rv = process_server_draw_line(mod, s);
|
|
|
|
break;
|
|
|
|
case 19: /* server_set_cursor */
|
|
|
|
rv = process_server_set_cursor(mod, s);
|
|
|
|
break;
|
|
|
|
case 20: /* server_create_os_surface */
|
|
|
|
rv = process_server_create_os_surface(mod, s);
|
|
|
|
break;
|
|
|
|
case 21: /* server_switch_os_surface */
|
|
|
|
rv = process_server_switch_os_surface(mod, s);
|
|
|
|
break;
|
|
|
|
case 22: /* server_delete_os_surface */
|
|
|
|
rv = process_server_delete_os_surface(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 23: /* server_paint_rect_os */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_paint_rect_os(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 24: /* server_set_hints */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_set_hints(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
break;
|
|
|
|
case 25: /* server_window_new_update */
|
|
|
|
rv = process_server_window_new_update(mod, s);
|
|
|
|
break;
|
|
|
|
case 26: /* server_window_delete */
|
|
|
|
rv = process_server_window_delete(mod, s);
|
|
|
|
break;
|
2013-06-30 23:36:01 +04:00
|
|
|
case 27: /* server_window_new_update - show */
|
|
|
|
rv = process_server_window_show(mod, s);
|
|
|
|
break;
|
2013-07-04 02:57:00 +04:00
|
|
|
case 28: /* server_add_char */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_add_char(mod, s);
|
2013-07-04 02:57:00 +04:00
|
|
|
break;
|
|
|
|
case 29: /* server_add_char_alpha */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_add_char_alpha(mod, s);
|
2013-07-04 02:57:00 +04:00
|
|
|
break;
|
|
|
|
case 30: /* server_draw_text */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_draw_text(mod, s);
|
2013-07-04 02:57:00 +04:00
|
|
|
break;
|
2013-07-07 08:03:58 +04:00
|
|
|
case 31: /* server_create_os_surface_bpp */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_create_os_surface_bpp(mod, s);
|
2013-07-07 08:03:58 +04:00
|
|
|
break;
|
|
|
|
case 32: /* server_paint_rect_bpp */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_paint_rect_bpp(mod, s);
|
|
|
|
break;
|
|
|
|
case 33: /* server_composite */
|
|
|
|
rv = process_server_composite(mod, s);
|
2013-07-07 08:03:58 +04:00
|
|
|
break;
|
2013-03-19 10:43:17 +04:00
|
|
|
case 51: /* server_set_pointer_ex */
|
|
|
|
rv = process_server_set_pointer_ex(mod, s);
|
|
|
|
break;
|
2013-08-19 09:36:18 +04:00
|
|
|
case 60: /* server_paint_rect_shmem */
|
2014-02-04 07:48:57 +04:00
|
|
|
rv = process_server_paint_rect_shmem(mod, s);
|
2013-08-19 09:36:18 +04:00
|
|
|
break;
|
2014-02-10 06:05:47 +04:00
|
|
|
case 61: /* server_paint_rect_shmem_ex */
|
|
|
|
rv = process_server_paint_rect_shmem_ex(mod, s);
|
|
|
|
break;
|
2022-07-14 11:46:38 +03:00
|
|
|
case 63: /* server_set_pointer_shmfd */
|
|
|
|
rv = process_server_set_pointer_shmfd(mod, s);
|
|
|
|
break;
|
2023-05-28 10:52:26 +03:00
|
|
|
case 64: /* server_paint_rect_shmfd */
|
|
|
|
rv = process_server_paint_rect_shmfd(mod, s);
|
|
|
|
break;
|
2012-09-20 07:51:34 +04:00
|
|
|
default:
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_WARNING,
|
|
|
|
"lib_mod_process_orders: unknown order type %d", type);
|
2012-09-20 07:51:34 +04:00
|
|
|
rv = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rv;
|
2012-05-13 07:52:43 +04:00
|
|
|
}
|
|
|
|
|
2012-05-14 00:56:15 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_send_client_info(struct mod *mod)
|
2012-05-14 00:56:15 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
struct stream *s;
|
|
|
|
int len;
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_send_client_info:");
|
2012-09-20 07:51:34 +04:00
|
|
|
make_stream(s);
|
|
|
|
init_stream(s, 8192);
|
|
|
|
s_push_layer(s, iso_hdr, 4);
|
|
|
|
out_uint16_le(s, 104);
|
|
|
|
g_memcpy(s->p, &(mod->client_info), sizeof(mod->client_info));
|
|
|
|
s->p += sizeof(mod->client_info);
|
|
|
|
s_mark_end(s);
|
|
|
|
len = (int)(s->end - s->data);
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint32_le(s, len);
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_send_copy(mod, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
free_stream(s);
|
|
|
|
return 0;
|
2012-05-14 00:56:15 +04:00
|
|
|
}
|
|
|
|
|
2012-05-13 07:52:43 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
static int
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_mod_process_message(struct mod *mod, struct stream *s)
|
2012-05-13 07:52:43 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int num_orders;
|
|
|
|
int index;
|
|
|
|
int rv;
|
|
|
|
int len;
|
|
|
|
int type;
|
|
|
|
char *phold;
|
|
|
|
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message:");
|
2015-07-11 06:38:27 +03:00
|
|
|
rv = 0;
|
2012-09-20 07:51:34 +04:00
|
|
|
if (rv == 0)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
in_uint16_le(s, type);
|
|
|
|
in_uint16_le(s, num_orders);
|
|
|
|
in_uint32_le(s, len);
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: type %d", type);
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
if (type == 1) /* original order list */
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
for (index = 0; index < num_orders; index++)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
in_uint16_le(s, type);
|
|
|
|
rv = lib_mod_process_orders(mod, type, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
if (rv != 0)
|
|
|
|
{
|
|
|
|
break;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
}
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
else if (type == 2) /* caps */
|
2012-04-15 05:19:43 +04:00
|
|
|
{
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
|
|
|
"lib_mod_process_message: type 2 len %d", len);
|
2015-07-11 06:38:27 +03:00
|
|
|
for (index = 0; index < num_orders; index++)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
phold = s->p;
|
|
|
|
in_uint16_le(s, type);
|
|
|
|
in_uint16_le(s, len);
|
|
|
|
|
|
|
|
switch (type)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
default:
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
|
|
|
"lib_mod_process_message: unknown"
|
|
|
|
" cap type %d len %d",
|
2015-07-11 06:38:27 +03:00
|
|
|
type, len);
|
|
|
|
break;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
s->p = phold + len;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
|
|
|
|
lib_send_client_info(mod);
|
2012-04-15 05:19:43 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
else if (type == 3) /* order list with len after type */
|
2012-05-13 07:52:43 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
for (index = 0; index < num_orders; index++)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
phold = s->p;
|
|
|
|
in_uint16_le(s, type);
|
|
|
|
in_uint16_le(s, len);
|
|
|
|
rv = lib_mod_process_orders(mod, type, s);
|
2012-09-20 07:51:34 +04:00
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
if (rv != 0)
|
|
|
|
{
|
|
|
|
break;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
|
|
|
|
s->p = phold + len;
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type);
|
2012-05-13 07:52:43 +04:00
|
|
|
}
|
2012-04-15 05:19:43 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
return rv;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
2015-07-11 06:38:27 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2015-07-11 06:38:27 +03:00
|
|
|
lib_mod_signal(struct mod *mod)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
// no-op
|
2015-07-11 06:38:27 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-04 22:00:34 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_end(struct mod *mod)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2014-01-28 22:40:19 +04:00
|
|
|
if (mod->screen_shmem_pixels != 0)
|
|
|
|
{
|
|
|
|
g_shmdt(mod->screen_shmem_pixels);
|
|
|
|
mod->screen_shmem_pixels = 0;
|
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
return 0;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2016-11-20 20:55:32 +03:00
|
|
|
lib_mod_set_param(struct mod *mod, const char *name, const char *value)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
if (g_strcasecmp(name, "username") == 0)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
g_strncpy(mod->username, value, INFO_CLIENT_MAX_CB_LEN - 1);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
else if (g_strcasecmp(name, "password") == 0)
|
|
|
|
{
|
2021-02-09 05:43:44 +03:00
|
|
|
g_strncpy(mod->password, value, INFO_CLIENT_MAX_CB_LEN - 1);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
|
|
|
else if (g_strcasecmp(name, "ip") == 0)
|
|
|
|
{
|
|
|
|
g_strncpy(mod->ip, value, 255);
|
|
|
|
}
|
|
|
|
else if (g_strcasecmp(name, "port") == 0)
|
|
|
|
{
|
|
|
|
g_strncpy(mod->port, value, 255);
|
|
|
|
}
|
|
|
|
else if (g_strcasecmp(name, "client_info") == 0)
|
|
|
|
{
|
|
|
|
g_memcpy(&(mod->client_info), value, sizeof(mod->client_info));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
2008-04-03 10:37:51 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_get_wait_objs(struct mod *mod, tbus *read_objs, int *rcount,
|
|
|
|
tbus *write_objs, int *wcount, int *timeout)
|
2008-04-03 10:37:51 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
if (mod != 0)
|
2008-04-03 10:37:51 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
if (mod->trans != 0)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
trans_get_wait_objs_rw(mod->trans, read_objs, rcount,
|
2015-07-13 11:10:48 +03:00
|
|
|
write_objs, wcount, timeout);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
2008-04-03 10:37:51 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
return 0;
|
2008-04-03 10:37:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2012-09-20 07:51:34 +04:00
|
|
|
lib_mod_check_wait_objs(struct mod *mod)
|
2008-04-03 10:37:51 +04:00
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
if (mod != 0)
|
2008-04-03 10:37:51 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
if (mod->trans != 0)
|
2012-09-20 07:51:34 +04:00
|
|
|
{
|
2015-07-11 06:38:27 +03:00
|
|
|
rv = trans_check_wait_objs(mod->trans);
|
2012-09-20 07:51:34 +04:00
|
|
|
}
|
2008-04-03 10:37:51 +04:00
|
|
|
}
|
2012-09-20 07:51:34 +04:00
|
|
|
|
|
|
|
return rv;
|
2008-04-03 10:37:51 +04:00
|
|
|
}
|
|
|
|
|
2014-03-23 03:51:30 +04:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
2017-03-12 19:35:00 +03:00
|
|
|
int
|
2014-03-23 03:51:30 +04:00
|
|
|
lib_mod_frame_ack(struct mod *amod, int flags, int frame_id)
|
|
|
|
{
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
|
|
|
"lib_mod_frame_ack: flags 0x%8.8x frame_id %d", flags, frame_id);
|
2014-03-23 03:51:30 +04:00
|
|
|
send_paint_rect_ex_ack(amod, flags, frame_id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-08 03:56:05 +03:00
|
|
|
/******************************************************************************/
|
|
|
|
/* return error */
|
|
|
|
int
|
|
|
|
lib_mod_suppress_output(struct mod *amod, int suppress,
|
|
|
|
int left, int top, int right, int bottom)
|
|
|
|
{
|
2022-03-15 07:45:26 +03:00
|
|
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
|
|
|
"lib_mod_suppress_output: suppress 0x%8.8x left %d top %d "
|
2021-02-09 05:43:44 +03:00
|
|
|
"right %d bottom %d", suppress, left, top, right, bottom);
|
2019-04-08 03:56:05 +03:00
|
|
|
send_suppress_output(amod, suppress, left, top, right, bottom);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-04 22:00:34 +03:00
|
|
|
/******************************************************************************/
|
2016-07-08 08:09:09 +03:00
|
|
|
tintptr EXPORT_CC
|
2006-02-04 22:00:34 +03:00
|
|
|
mod_init(void)
|
|
|
|
{
|
2012-09-20 07:51:34 +04:00
|
|
|
struct mod *mod;
|
|
|
|
|
|
|
|
mod = (struct mod *)g_malloc(sizeof(struct mod), 1);
|
|
|
|
mod->size = sizeof(struct mod);
|
|
|
|
mod->version = CURRENT_MOD_VER;
|
2016-07-08 08:09:09 +03:00
|
|
|
mod->handle = (tintptr) mod;
|
2012-09-20 07:51:34 +04:00
|
|
|
mod->mod_connect = lib_mod_connect;
|
|
|
|
mod->mod_start = lib_mod_start;
|
|
|
|
mod->mod_event = lib_mod_event;
|
|
|
|
mod->mod_signal = lib_mod_signal;
|
|
|
|
mod->mod_end = lib_mod_end;
|
|
|
|
mod->mod_set_param = lib_mod_set_param;
|
|
|
|
mod->mod_get_wait_objs = lib_mod_get_wait_objs;
|
|
|
|
mod->mod_check_wait_objs = lib_mod_check_wait_objs;
|
2014-03-23 03:51:30 +04:00
|
|
|
mod->mod_frame_ack = lib_mod_frame_ack;
|
2019-04-08 03:56:05 +03:00
|
|
|
mod->mod_suppress_output = lib_mod_suppress_output;
|
2018-10-16 07:42:13 +03:00
|
|
|
mod->mod_server_monitor_resize = lib_send_server_monitor_resize;
|
2022-03-15 07:45:26 +03:00
|
|
|
mod->mod_server_monitor_full_invalidate
|
|
|
|
= lib_send_server_monitor_full_invalidate;
|
2018-10-16 07:42:13 +03:00
|
|
|
mod->mod_server_version_message = lib_send_server_version_message;
|
2016-07-08 08:09:09 +03:00
|
|
|
return (tintptr) mod;
|
2006-02-04 22:00:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int EXPORT_CC
|
2016-07-08 08:09:09 +03:00
|
|
|
mod_exit(tintptr handle)
|
2006-02-04 22:00:34 +03:00
|
|
|
{
|
2016-07-08 08:09:09 +03:00
|
|
|
struct mod *mod = (struct mod *) handle;
|
|
|
|
|
2012-09-20 07:51:34 +04:00
|
|
|
if (mod == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2015-07-11 06:38:27 +03:00
|
|
|
trans_delete(mod->trans);
|
2012-09-20 07:51:34 +04:00
|
|
|
g_free(mod);
|
2006-02-04 22:00:34 +03:00
|
|
|
return 0;
|
|
|
|
}
|