Split up vnc.c into modules and re-implement clipboard functions
This commit is contained in:
parent
3ea19ef0cd
commit
fe28af93e8
@ -10,7 +10,10 @@ module_LTLIBRARIES = \
|
||||
|
||||
libvnc_la_SOURCES = \
|
||||
vnc.c \
|
||||
vnc.h
|
||||
vnc_clip.c \
|
||||
rfb.h \
|
||||
vnc.h \
|
||||
vnc_clip.h
|
||||
|
||||
libvnc_la_LIBADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
||||
|
53
vnc/rfb.c
Normal file
53
vnc/rfb.c
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2015
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* libvnc - RFB specific functions
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "rfb.h"
|
||||
|
||||
/* Messages for ExtendedDesktopSize status code */
|
||||
static const char *eds_status_msg[] =
|
||||
{
|
||||
/* 0 */ "No error",
|
||||
/* 1 */ "Resize is administratively prohibited",
|
||||
/* 2 */ "Out of resources",
|
||||
/* 3 */ "Invalid screen layout",
|
||||
/* others */ "Unknown code"
|
||||
};
|
||||
|
||||
/* elements in above list */
|
||||
#define EDS_STATUS_MSG_COUNT \
|
||||
(sizeof(eds_status_msg) / sizeof(eds_status_msg[0]))
|
||||
|
||||
/**************************************************************************//**
|
||||
* Returns an error string for an ExtendedDesktopSize status code
|
||||
*/
|
||||
const char *
|
||||
get_eds_status_msg(unsigned int response_code)
|
||||
{
|
||||
if (response_code >= EDS_STATUS_MSG_COUNT)
|
||||
{
|
||||
response_code = EDS_STATUS_MSG_COUNT - 1;
|
||||
}
|
||||
|
||||
return eds_status_msg[response_code];
|
||||
}
|
67
vnc/rfb.h
Normal file
67
vnc/rfb.h
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2015
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* libvnc - defines related to the RFB protocol
|
||||
*/
|
||||
|
||||
#ifndef RFB_H
|
||||
#define RFB_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
/* Client-to-server messages */
|
||||
enum c2s
|
||||
{
|
||||
RFB_C2S_SET_PIXEL_FORMAT = 0,
|
||||
RFB_C2S_SET_ENCODINGS = 2,
|
||||
RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST = 3,
|
||||
RFB_C2S_KEY_EVENT = 4,
|
||||
RFB_C2S_POINTER_EVENT = 5,
|
||||
RFB_C2S_CLIENT_CUT_TEXT = 6,
|
||||
};
|
||||
|
||||
/* Server to client messages */
|
||||
enum s2c
|
||||
{
|
||||
RFB_S2C_FRAMEBUFFER_UPDATE = 0,
|
||||
RFB_S2C_SET_COLOUR_MAP_ENTRIES = 1,
|
||||
RFB_S2C_BELL = 2,
|
||||
RFB_S2C_SERVER_CUT_TEXT = 3
|
||||
};
|
||||
|
||||
/* Encodings and pseudo-encodings
|
||||
*
|
||||
* The RFC uses a signed type for these. We use an unsigned type as the
|
||||
* binary representation for the negative values is standardised in C
|
||||
* (which it wouldn't be for an enum value)
|
||||
*/
|
||||
|
||||
typedef uint32_t encoding_type;
|
||||
|
||||
#define RFB_ENC_RAW (encoding_type)0
|
||||
#define RFB_ENC_COPY_RECT (encoding_type)1
|
||||
#define RFB_ENC_CURSOR (encoding_type)-239
|
||||
#define RFB_ENC_DESKTOP_SIZE (encoding_type)-223
|
||||
#define RFB_ENC_EXTENDED_DESKTOP_SIZE (encoding_type)-308
|
||||
|
||||
/**
|
||||
* Returns an error string for an ExtendedDesktopSize status code
|
||||
*/
|
||||
const char *
|
||||
rfb_get_eds_status_msg(unsigned int response_code);
|
||||
|
||||
#endif /* RFB_H */
|
401
vnc/vnc.c
401
vnc/vnc.c
@ -31,57 +31,14 @@
|
||||
#endif
|
||||
|
||||
#include "vnc.h"
|
||||
#include "vnc_clip.h"
|
||||
#include "rfb.h"
|
||||
#include "log.h"
|
||||
#include "trans.h"
|
||||
#include "ssl_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "xrdp_client_info.h"
|
||||
|
||||
/* Client-to-server messages */
|
||||
enum c2s
|
||||
{
|
||||
C2S_SET_PIXEL_FORMAT = 0,
|
||||
C2S_SET_ENCODINGS = 2,
|
||||
C2S_FRAMEBUFFER_UPDATE_REQUEST = 3,
|
||||
C2S_KEY_EVENT = 4,
|
||||
C2S_POINTER_EVENT = 5,
|
||||
C2S_CLIENT_CUT_TEXT = 6,
|
||||
};
|
||||
|
||||
/* Server to client messages */
|
||||
enum s2c
|
||||
{
|
||||
S2C_FRAMEBUFFER_UPDATE = 0,
|
||||
S2C_SET_COLOUR_MAP_ENTRIES = 1,
|
||||
S2C_BELL = 2,
|
||||
S2C_SERVER_CUT_TEXT = 3
|
||||
};
|
||||
|
||||
/* Encodings and pseudo-encodings
|
||||
*
|
||||
* The RFC uses a signed type for these. We use an unsigned type as the
|
||||
* binary representation for the negative values is standardised in C
|
||||
* (which it wouldn't be for an enum value)
|
||||
*/
|
||||
|
||||
typedef uint32_t encoding_type;
|
||||
|
||||
#define ENC_RAW (encoding_type)0
|
||||
#define ENC_COPY_RECT (encoding_type)1
|
||||
#define ENC_CURSOR (encoding_type)-239
|
||||
#define ENC_DESKTOP_SIZE (encoding_type)-223
|
||||
#define ENC_EXTENDED_DESKTOP_SIZE (encoding_type)-308
|
||||
|
||||
/* Messages for ExtendedDesktopSize status code */
|
||||
static const char *eds_status_msg[] =
|
||||
{
|
||||
/* 0 */ "No error",
|
||||
/* 1 */ "Resize is administratively prohibited",
|
||||
/* 2 */ "Out of resources",
|
||||
/* 3 */ "Invalid screen layout",
|
||||
/* others */ "Unknown code"
|
||||
};
|
||||
|
||||
/* elements in above list */
|
||||
#define EDS_STATUS_MSG_COUNT \
|
||||
(sizeof(eds_status_msg) / sizeof(eds_status_msg[0]))
|
||||
@ -92,11 +49,8 @@ enum
|
||||
MSK_EXTENDED_DESKTOP_SIZE = (1 << 0)
|
||||
};
|
||||
|
||||
static int
|
||||
lib_mod_process_message(struct vnc *v, struct stream *s);
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
int
|
||||
lib_send_copy(struct vnc *v, struct stream *s)
|
||||
{
|
||||
return trans_write_copy_s(v->trans, s);
|
||||
@ -152,160 +106,6 @@ rfbHashEncryptBytes(char *bytes, const char *passwd)
|
||||
rfbEncryptBytes(bytes, passwd_hash_text);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lib_process_channel_data(struct vnc *v, int chanid, int flags, int size,
|
||||
struct stream *s, int total_size)
|
||||
{
|
||||
int type;
|
||||
int status;
|
||||
int length;
|
||||
int clip_bytes;
|
||||
int index;
|
||||
int format;
|
||||
struct stream *out_s;
|
||||
|
||||
if (chanid == v->clip_chanid)
|
||||
{
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, status);
|
||||
in_uint32_le(s, length);
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "clip data type %d status %d length %d", type, status, length);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "clipboard data", s->p, s->end - s->p);
|
||||
switch (type)
|
||||
{
|
||||
case 2: /* CLIPRDR_FORMAT_ANNOUNCE */
|
||||
LOG(LOG_LEVEL_DEBUG, "CLIPRDR_FORMAT_ANNOUNCE - "
|
||||
"status %d length %d", status, length);
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
out_uint16_le(out_s, 3); // msg-type: CLIPRDR_FORMAT_ACK
|
||||
out_uint16_le(out_s, 1); // msg-status-code: CLIPRDR_RESPONSE
|
||||
out_uint32_le(out_s, 0); // null (?)
|
||||
out_uint8s(out_s, 4); // pad
|
||||
s_mark_end(out_s);
|
||||
length = (int)(out_s->end - out_s->data);
|
||||
v->server_send_to_channel(v, v->clip_chanid, out_s->data,
|
||||
length, length, 3);
|
||||
free_stream(out_s);
|
||||
#if 0
|
||||
// Send the CLIPRDR_DATA_REQUEST message to the cliprdr channel.
|
||||
//
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
out_uint16_le(out_s, 4); // msg-type: CLIPRDR_DATA_REQUEST
|
||||
out_uint16_le(out_s, 0); // msg-status-code: CLIPRDR_REQUEST
|
||||
out_uint32_le(out_s, 4); // sizeof supported-format-list.
|
||||
out_uint32_le(out_s, 1); // supported-format-list: CF_TEXT
|
||||
out_uint8s(out_s, 0); // pad (garbage pad?)
|
||||
s_mark_end(out_s);
|
||||
length = (int)(out_s->end - out_s->data);
|
||||
v->server_send_to_channel(v, v->clip_chanid, out_s->data,
|
||||
length, length, 3);
|
||||
free_stream(out_s);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 3: /* CLIPRDR_FORMAT_ACK */
|
||||
LOG(LOG_LEVEL_DEBUG, "CLIPRDR_FORMAT_ACK - "
|
||||
"status %d length %d", status, length);
|
||||
break;
|
||||
case 4: /* CLIPRDR_DATA_REQUEST */
|
||||
LOG(LOG_LEVEL_DEBUG, "CLIPRDR_DATA_REQUEST - "
|
||||
"status %d length %d", status, length);
|
||||
format = 0;
|
||||
|
||||
if (length >= 4)
|
||||
{
|
||||
in_uint32_le(s, format);
|
||||
}
|
||||
|
||||
/* only support CF_TEXT and CF_UNICODETEXT */
|
||||
if ((format != 1) && (format != 13))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
out_uint16_le(out_s, 5);
|
||||
out_uint16_le(out_s, 1);
|
||||
|
||||
if (format == 13) /* CF_UNICODETEXT */
|
||||
{
|
||||
out_uint32_le(out_s, v->clip_data_s->size * 2 + 2);
|
||||
|
||||
for (index = 0; index < v->clip_data_s->size; index++)
|
||||
{
|
||||
out_uint8(out_s, v->clip_data_s->data[index]);
|
||||
out_uint8(out_s, 0);
|
||||
}
|
||||
|
||||
out_uint8s(out_s, 2);
|
||||
}
|
||||
else if (format == 1) /* CF_TEXT */
|
||||
{
|
||||
out_uint32_le(out_s, v->clip_data_s->size + 1);
|
||||
|
||||
for (index = 0; index < v->clip_data_s->size; index++)
|
||||
{
|
||||
out_uint8(out_s, v->clip_data_s->data[index]);
|
||||
}
|
||||
|
||||
out_uint8s(out_s, 1);
|
||||
}
|
||||
|
||||
out_uint8s(out_s, 4); /* pad */
|
||||
s_mark_end(out_s);
|
||||
length = (int)(out_s->end - out_s->data);
|
||||
v->server_send_to_channel(v, v->clip_chanid, out_s->data, length,
|
||||
length, 3);
|
||||
free_stream(out_s);
|
||||
break;
|
||||
|
||||
case 5: /* CLIPRDR_DATA_RESPONSE */
|
||||
LOG(LOG_LEVEL_DEBUG, "CLIPRDR_DATA_RESPONSE - "
|
||||
"status %d length %d", status, length);
|
||||
clip_bytes = MIN(length, 256);
|
||||
// - Read the response data from the cliprdr channel, stream 's'.
|
||||
// - Send the response data to the vnc server, stream 'out_s'.
|
||||
//
|
||||
make_stream(out_s);
|
||||
// Send the RFB message type (CLIENT_CUT_TEXT) to the vnc server.
|
||||
init_stream(out_s, clip_bytes + 1 + 3 + 4 + 16);
|
||||
out_uint8(out_s, C2S_CLIENT_CUT_TEXT);
|
||||
out_uint8s(out_s, 3); // padding
|
||||
// Send the length of the cut-text to the vnc server.
|
||||
out_uint32_be(out_s, clip_bytes);
|
||||
// Send the cut-text (as read from 's') to the vnc server.
|
||||
for (index = 0; index < clip_bytes; index++)
|
||||
{
|
||||
char cur_char = '\0';
|
||||
in_uint8(s, cur_char); // text in from 's'
|
||||
out_uint8(out_s, cur_char); // text out to 'out_s'
|
||||
}
|
||||
s_mark_end(out_s);
|
||||
lib_send_copy(v, out_s);
|
||||
free_stream(out_s);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC clip information unhandled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "lib_process_channel_data: unknown chanid: "
|
||||
"%d :(v->clip_chanid) %d", chanid, v->clip_chanid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Logs a debug message containing a screen layout
|
||||
*
|
||||
@ -695,11 +495,16 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
|
||||
|
||||
if ((size >= 0) && (size <= (32 * 1024)) && (data != 0))
|
||||
{
|
||||
init_stream(s, size);
|
||||
out_uint8a(s, data, size);
|
||||
s_mark_end(s);
|
||||
s->p = s->data;
|
||||
error = lib_process_channel_data(v, chanid, flags, size, s, total_size);
|
||||
if (chanid == v->clip_chanid)
|
||||
{
|
||||
error = vnc_clip_process_channel_data(v, data, size,
|
||||
total_size, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "lib_process_channel_data: unknown chanid: "
|
||||
"%d :(v->clip_chanid) %d", chanid, v->clip_chanid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -718,7 +523,7 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
|
||||
{
|
||||
/* fix for mstsc sending left control down with altgr */
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_KEY_EVENT);
|
||||
out_uint8(s, RFB_C2S_KEY_EVENT);
|
||||
out_uint8(s, 0); /* down flag */
|
||||
out_uint8s(s, 2);
|
||||
out_uint32_be(s, 65507); /* left control */
|
||||
@ -728,7 +533,7 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
|
||||
}
|
||||
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_KEY_EVENT);
|
||||
out_uint8(s, RFB_C2S_KEY_EVENT);
|
||||
out_uint8(s, msg == 15); /* down flag */
|
||||
out_uint8s(s, 2);
|
||||
out_uint32_be(s, key);
|
||||
@ -780,7 +585,7 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
|
||||
}
|
||||
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_POINTER_EVENT);
|
||||
out_uint8(s, RFB_C2S_POINTER_EVENT);
|
||||
out_uint8(s, v->mod_mouse_state);
|
||||
out_uint16_be(s, param1);
|
||||
out_uint16_be(s, param2);
|
||||
@ -792,7 +597,7 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
|
||||
if (v->suppress_output == 0)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 0); /* incremental == 0 : Full contents */
|
||||
x = (param1 >> 16) & 0xffff;
|
||||
out_uint16_be(s, x);
|
||||
@ -1018,15 +823,22 @@ get_bytes_per_pixel(int bpp)
|
||||
* @param bytes Bytes to skip
|
||||
* @return != 0 for error
|
||||
*/
|
||||
static int
|
||||
skip_trans_bytes(struct trans *trans, int bytes)
|
||||
int
|
||||
skip_trans_bytes(struct trans *trans, unsigned int bytes)
|
||||
{
|
||||
struct stream *s;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, bytes);
|
||||
error = trans_force_read_s(trans, s, bytes);
|
||||
|
||||
while (error == 0 && bytes > 0)
|
||||
{
|
||||
int chunk_size = MIN(32768, bytes);
|
||||
init_stream(s, chunk_size);
|
||||
error = trans_force_read_s(trans, s, chunk_size);
|
||||
bytes -= chunk_size;
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
|
||||
return error;
|
||||
@ -1054,40 +866,40 @@ skip_encoding(struct vnc *v, int x, int y, int cx, int cy,
|
||||
|
||||
switch (encoding)
|
||||
{
|
||||
case ENC_RAW:
|
||||
case RFB_ENC_RAW:
|
||||
{
|
||||
int need_size = cx * cy * get_bytes_per_pixel(v->server_bpp);
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping ENC_RAW encoding");
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping RFB_ENC_RAW encoding");
|
||||
error = skip_trans_bytes(v->trans, need_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENC_COPY_RECT:
|
||||
case RFB_ENC_COPY_RECT:
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping ENC_COPY_RECT encoding");
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping RFB_ENC_COPY_RECT encoding");
|
||||
error = skip_trans_bytes(v->trans, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENC_CURSOR:
|
||||
case RFB_ENC_CURSOR:
|
||||
{
|
||||
int j = cx * cy * get_bytes_per_pixel(v->server_bpp);
|
||||
int k = ((cx + 7) / 8) * cy;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping ENC_CURSOR encoding");
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping RFB_ENC_CURSOR encoding");
|
||||
error = skip_trans_bytes(v->trans, j + k);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENC_DESKTOP_SIZE:
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping ENC_DESKTOP_SIZE encoding");
|
||||
case RFB_ENC_DESKTOP_SIZE:
|
||||
LOG(LOG_LEVEL_DEBUG, "Skipping RFB_ENC_DESKTOP_SIZE encoding");
|
||||
break;
|
||||
|
||||
case ENC_EXTENDED_DESKTOP_SIZE:
|
||||
case RFB_ENC_EXTENDED_DESKTOP_SIZE:
|
||||
{
|
||||
struct vnc_screen_layout layout = {0};
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"Skipping ENC_EXTENDED_DESKTOP_SIZE encoding "
|
||||
"Skipping RFB_ENC_EXTENDED_DESKTOP_SIZE encoding "
|
||||
"x=%d, y=%d geom=%dx%d",
|
||||
x, y, cx, cy);
|
||||
error = read_extended_desktop_size_rect(v, &layout);
|
||||
@ -1165,7 +977,7 @@ find_matching_extended_rect(struct vnc *v,
|
||||
in_uint16_be(s, cy);
|
||||
in_uint32_be(s, encoding);
|
||||
|
||||
if (encoding == ENC_EXTENDED_DESKTOP_SIZE &&
|
||||
if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE &&
|
||||
match_layout->s == NULL &&
|
||||
match(x, y, cx, cy))
|
||||
{
|
||||
@ -1230,7 +1042,7 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
/*
|
||||
* Ask for an immediate, minimal update.
|
||||
*/
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 0); /* incremental == 0 : Full update */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
@ -1244,7 +1056,7 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
/*
|
||||
* Ask for a deferred minimal update.
|
||||
*/
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 1); /* incremental == 1 : Changes only */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
@ -1260,7 +1072,7 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
*/
|
||||
if (v->suppress_output == 0)
|
||||
{
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 0); /* incremental == 0 : Full update */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
@ -1297,20 +1109,6 @@ rect_is_reply_to_us(int x, int y, int cx, int cy)
|
||||
return (x == 1);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Returns an error string for an ExtendedDesktopSize status code
|
||||
*/
|
||||
static const char *
|
||||
get_eds_status_msg(unsigned int response_code)
|
||||
{
|
||||
if (response_code >= EDS_STATUS_MSG_COUNT)
|
||||
{
|
||||
response_code = EDS_STATUS_MSG_COUNT - 1;
|
||||
}
|
||||
|
||||
return eds_status_msg[response_code];
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Handles the first framebuffer update from the server
|
||||
*
|
||||
@ -1431,7 +1229,7 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"VNC server resize failed - error code %d [%s]",
|
||||
response_code,
|
||||
get_eds_status_msg(response_code));
|
||||
rfb_get_eds_status_msg(response_code));
|
||||
/* Force client to same size as server */
|
||||
LOG(LOG_LEVEL_WARNING, "Resizing client to server %dx%d",
|
||||
v->server_width, v->server_height);
|
||||
@ -1514,7 +1312,7 @@ lib_framebuffer_update(struct vnc *v)
|
||||
in_uint16_be(s, cy);
|
||||
in_uint32_be(s, encoding);
|
||||
|
||||
if (encoding == ENC_RAW)
|
||||
if (encoding == RFB_ENC_RAW)
|
||||
{
|
||||
need_size = cx * cy * get_bytes_per_pixel(v->server_bpp);
|
||||
init_stream(pixel_s, need_size);
|
||||
@ -1525,7 +1323,7 @@ lib_framebuffer_update(struct vnc *v)
|
||||
error = v->server_paint_rect(v, x, y, cx, cy, pixel_s->data, cx, cy, 0, 0);
|
||||
}
|
||||
}
|
||||
else if (encoding == ENC_COPY_RECT)
|
||||
else if (encoding == RFB_ENC_COPY_RECT)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
error = trans_force_read_s(v->trans, s, 4);
|
||||
@ -1537,7 +1335,7 @@ lib_framebuffer_update(struct vnc *v)
|
||||
error = v->server_screen_blt(v, x, y, cx, cy, srcx, srcy);
|
||||
}
|
||||
}
|
||||
else if (encoding == ENC_CURSOR)
|
||||
else if (encoding == RFB_ENC_CURSOR)
|
||||
{
|
||||
g_memset(cursor_data, 0, 32 * (32 * 3));
|
||||
g_memset(cursor_mask, 0, 32 * (32 / 8));
|
||||
@ -1582,14 +1380,14 @@ lib_framebuffer_update(struct vnc *v)
|
||||
error = v->server_set_cursor(v, x, y, cursor_data, cursor_mask);
|
||||
}
|
||||
}
|
||||
else if (encoding == ENC_DESKTOP_SIZE)
|
||||
else if (encoding == RFB_ENC_DESKTOP_SIZE)
|
||||
{
|
||||
/* Server end has resized */
|
||||
v->server_width = cx;
|
||||
v->server_height = cy;
|
||||
error = resize_client(v, 1, cx, cy);
|
||||
}
|
||||
else if (encoding == ENC_EXTENDED_DESKTOP_SIZE)
|
||||
else if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE)
|
||||
{
|
||||
layout.total_width = cx;
|
||||
layout.total_height = cy;
|
||||
@ -1622,7 +1420,7 @@ lib_framebuffer_update(struct vnc *v)
|
||||
if (v->suppress_output == 0)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 1); /* incremental == 1 : Changes only */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
@ -1638,57 +1436,6 @@ lib_framebuffer_update(struct vnc *v)
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* clip data from the vnc server */
|
||||
int
|
||||
lib_clip_data(struct vnc *v)
|
||||
{
|
||||
struct stream *s;
|
||||
struct stream *out_s;
|
||||
int size;
|
||||
int error;
|
||||
|
||||
free_stream(v->clip_data_s);
|
||||
v->clip_data_s = 0;
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
error = trans_force_read_s(v->trans, s, 7);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
in_uint8s(s, 3);
|
||||
in_uint32_be(s, size);
|
||||
make_stream(v->clip_data_s);
|
||||
init_stream(v->clip_data_s, size);
|
||||
error = trans_force_read_s(v->trans, v->clip_data_s, size);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
out_uint16_le(out_s, 2);
|
||||
out_uint16_le(out_s, 0);
|
||||
out_uint32_le(out_s, 0x90);
|
||||
out_uint8(out_s, 0x0d);
|
||||
out_uint8s(out_s, 35);
|
||||
out_uint8(out_s, 0x10);
|
||||
out_uint8s(out_s, 35);
|
||||
out_uint8(out_s, 0x01);
|
||||
out_uint8s(out_s, 35);
|
||||
out_uint8(out_s, 0x07);
|
||||
out_uint8s(out_s, 35);
|
||||
out_uint8s(out_s, 4);
|
||||
s_mark_end(out_s);
|
||||
size = (int)(out_s->end - out_s->data);
|
||||
error = v->server_send_to_channel(v, v->clip_chanid, out_s->data, size, size, 3);
|
||||
free_stream(out_s);
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
lib_palette_update(struct vnc *v)
|
||||
@ -1775,7 +1522,7 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
|
||||
error = 0;
|
||||
if (error == 0)
|
||||
{
|
||||
if (type == S2C_FRAMEBUFFER_UPDATE)
|
||||
if (type == RFB_S2C_FRAMEBUFFER_UPDATE)
|
||||
{
|
||||
switch (v->resize_status)
|
||||
{
|
||||
@ -1791,18 +1538,18 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
|
||||
error = lib_framebuffer_update(v);
|
||||
}
|
||||
}
|
||||
else if (type == S2C_SET_COLOUR_MAP_ENTRIES)
|
||||
else if (type == RFB_S2C_SET_COLOUR_MAP_ENTRIES)
|
||||
{
|
||||
error = lib_palette_update(v);
|
||||
}
|
||||
else if (type == S2C_BELL)
|
||||
else if (type == RFB_S2C_BELL)
|
||||
{
|
||||
error = lib_bell_trigger(v);
|
||||
}
|
||||
else if (type == S2C_SERVER_CUT_TEXT) /* clipboard */
|
||||
else if (type == RFB_S2C_SERVER_CUT_TEXT) /* clipboard */
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC got clip data");
|
||||
error = lib_clip_data(v);
|
||||
error = vnc_clip_process_rfb_data(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1826,22 +1573,6 @@ lib_mod_start(struct vnc *v, int w, int h, int bpp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lib_open_clip_channel(struct vnc *v)
|
||||
{
|
||||
char init_data[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
v->clip_chanid = v->server_get_channel_id(v, "cliprdr");
|
||||
|
||||
if (v->clip_chanid >= 0)
|
||||
{
|
||||
v->server_send_to_channel(v, v->clip_chanid, init_data, 12, 12, 3);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lib_data_in(struct trans *trans)
|
||||
@ -2117,7 +1848,7 @@ lib_mod_connect(struct vnc *v)
|
||||
if (error == 0)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_SET_PIXEL_FORMAT);
|
||||
out_uint8(s, RFB_C2S_SET_PIXEL_FORMAT);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
@ -2209,13 +1940,13 @@ lib_mod_connect(struct vnc *v)
|
||||
unsigned int i;
|
||||
|
||||
/* These encodings are always supported */
|
||||
e[n++] = ENC_RAW;
|
||||
e[n++] = ENC_COPY_RECT;
|
||||
e[n++] = ENC_CURSOR;
|
||||
e[n++] = ENC_DESKTOP_SIZE;
|
||||
e[n++] = RFB_ENC_RAW;
|
||||
e[n++] = RFB_ENC_COPY_RECT;
|
||||
e[n++] = RFB_ENC_CURSOR;
|
||||
e[n++] = RFB_ENC_DESKTOP_SIZE;
|
||||
if (v->enabled_encodings_mask & MSK_EXTENDED_DESKTOP_SIZE)
|
||||
{
|
||||
e[n++] = ENC_EXTENDED_DESKTOP_SIZE;
|
||||
e[n++] = RFB_ENC_EXTENDED_DESKTOP_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2224,7 +1955,7 @@ lib_mod_connect(struct vnc *v)
|
||||
}
|
||||
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_SET_ENCODINGS);
|
||||
out_uint8(s, RFB_C2S_SET_ENCODINGS);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, n); /* Number of encodings following */
|
||||
for (i = 0 ; i < n; ++i)
|
||||
@ -2259,7 +1990,7 @@ lib_mod_connect(struct vnc *v)
|
||||
if (error == 0)
|
||||
{
|
||||
v->server_msg(v, "VNC connection complete, connected ok", 0);
|
||||
lib_open_clip_channel(v);
|
||||
vnc_clip_open_clip_channel(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2292,7 +2023,6 @@ lib_mod_end(struct vnc *v)
|
||||
{
|
||||
}
|
||||
|
||||
free_stream(v->clip_data_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2452,7 +2182,7 @@ lib_mod_suppress_output(struct vnc *v, int suppress,
|
||||
{
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
out_uint8(s, C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 0); /* incremental == 0 : Full contents */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
@ -2520,6 +2250,8 @@ mod_init(void)
|
||||
|
||||
/* Member variables */
|
||||
v->enabled_encodings_mask = -1;
|
||||
vnc_clip_init(v);
|
||||
|
||||
return (tintptr) v;
|
||||
}
|
||||
|
||||
@ -2536,6 +2268,7 @@ mod_exit(tintptr handle)
|
||||
}
|
||||
trans_delete(v->trans);
|
||||
g_free(v->client_layout.s);
|
||||
vnc_clip_exit(v);
|
||||
g_free(v);
|
||||
return 0;
|
||||
}
|
||||
|
18
vnc/vnc.h
18
vnc/vnc.h
@ -18,6 +18,9 @@
|
||||
* libvnc
|
||||
*/
|
||||
|
||||
#ifndef VNC_H
|
||||
#define VNC_H
|
||||
|
||||
/* include other h files */
|
||||
#include "arch.h"
|
||||
#include "parse.h"
|
||||
@ -58,6 +61,9 @@ enum vnc_resize_status
|
||||
|
||||
struct source_info;
|
||||
|
||||
/* Defined in vnc_clip.c */
|
||||
struct vnc_clipboard_data;
|
||||
|
||||
struct vnc
|
||||
{
|
||||
int size; /* size of this struct */
|
||||
@ -149,7 +155,7 @@ struct vnc
|
||||
int shift_state; /* 0 up, 1 down */
|
||||
int keylayout;
|
||||
int clip_chanid;
|
||||
struct stream *clip_data_s;
|
||||
struct vnc_clipboard_data *vc;
|
||||
int delay_ms;
|
||||
struct trans *trans;
|
||||
int got_guid;
|
||||
@ -160,3 +166,13 @@ struct vnc
|
||||
struct vnc_screen_layout client_layout;
|
||||
enum vnc_resize_status resize_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
int
|
||||
lib_send_copy(struct vnc *v, struct stream *s);
|
||||
int
|
||||
skip_trans_bytes(struct trans *trans, unsigned int bytes);
|
||||
|
||||
#endif /* VNC_H */
|
||||
|
1031
vnc/vnc_clip.c
Normal file
1031
vnc/vnc_clip.c
Normal file
File diff suppressed because it is too large
Load Diff
70
vnc/vnc_clip.h
Normal file
70
vnc/vnc_clip.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2015
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* libvnc - functions used by the VNC clipboard feature
|
||||
*/
|
||||
|
||||
#ifndef VNC_CLIP_H
|
||||
#define VNC_CLIP_H
|
||||
|
||||
struct vnc;
|
||||
struct stream;
|
||||
|
||||
/**
|
||||
* Init the clip module private data structures
|
||||
*/
|
||||
void
|
||||
vnc_clip_init(struct vnc *v);
|
||||
|
||||
/**
|
||||
* Deallocate the clip module private data structures
|
||||
*/
|
||||
void
|
||||
vnc_clip_exit(struct vnc *v);
|
||||
|
||||
/**
|
||||
* Process incoming data from the RDP clip channel
|
||||
* @param v VNC Object
|
||||
* @param s Stream object containing data
|
||||
*
|
||||
* @return Non-zero if error occurs
|
||||
*/
|
||||
int
|
||||
vnc_clip_process_channel_data(struct vnc *v, char *data, int size,
|
||||
int total_size, int flags);
|
||||
|
||||
/**
|
||||
* Process incoming RFB protocol clipboard data
|
||||
* @param v VNC Object
|
||||
*
|
||||
* @return Non-zero if error occurs
|
||||
*/
|
||||
int
|
||||
vnc_clip_process_rfb_data(struct vnc *v);
|
||||
|
||||
/**
|
||||
* Open the RDP clipboard channel
|
||||
*
|
||||
* The clip channel ID is written to the VNC object
|
||||
* *
|
||||
* @param v VNC Object
|
||||
* @return Non-zero if error occurs
|
||||
*/
|
||||
int
|
||||
vnc_clip_open_clip_channel(struct vnc *v);
|
||||
|
||||
#endif /* VNC_CLIP_H */
|
Loading…
Reference in New Issue
Block a user