Split up vnc.c into modules and re-implement clipboard functions

This commit is contained in:
matt335672 2021-05-27 15:35:52 +01:00
parent 3ea19ef0cd
commit fe28af93e8
7 changed files with 1309 additions and 336 deletions

View File

@ -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
View 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
View 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
View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

70
vnc/vnc_clip.h Normal file
View 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 */