mirror of
https://invent.kde.org/network/krfb
synced 2024-07-01 07:24:29 +00:00
CVE-2014-4607: Unbundle libvncserver
http://seclists.org/oss-sec/2014/q2/676 REVIEW: 119548
This commit is contained in:
parent
83767fea93
commit
1c85dc7d85
|
@ -32,6 +32,8 @@ set(CMAKE_MODULE_PATH
|
|||
${CMAKE_MODULE_PATH}
|
||||
)
|
||||
|
||||
find_package(LibVNCServer REQUIRED)
|
||||
|
||||
macro_optional_find_package(TelepathyQt4)
|
||||
macro_log_feature(TelepathyQt4_FOUND "telepathy-qt" "Telepathy Qt Bindings" "http://telepathy.freedesktop.org" FALSE "0.9" "Needed to build Telepathy Tubes support.")
|
||||
|
||||
|
@ -44,8 +46,6 @@ macro_bool_to_01(X11_XShm_FOUND HAVE_XSHM)
|
|||
include_directories ("${CMAKE_CURRENT_BINARY_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb/ui"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/libvncserver/"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libvncserver/"
|
||||
)
|
||||
|
||||
if(Q_WS_X11)
|
||||
|
@ -54,9 +54,8 @@ if(Q_WS_X11)
|
|||
endif(NOT X11_XTest_FOUND)
|
||||
endif(Q_WS_X11)
|
||||
|
||||
add_subdirectory(libvncserver)
|
||||
add_subdirectory(krfb)
|
||||
add_subdirectory (framebuffers)
|
||||
add_subdirectory(framebuffers)
|
||||
add_subdirectory(doc)
|
||||
|
||||
if (NOT INSIDE_KDENETWORK)
|
||||
|
|
41
cmake/modules/FindLibVNCServer.cmake
Normal file
41
cmake/modules/FindLibVNCServer.cmake
Normal file
|
@ -0,0 +1,41 @@
|
|||
# cmake macro to test LIBVNCSERVER LIB
|
||||
|
||||
# Copyright (c) 2006, Alessandro Praduroux <pradu@pradu.it>
|
||||
# Copyright (c) 2007, Urs Wolfer <uwolfer @ kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
INCLUDE(CheckPointerMember)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(LIBVNCSERVER_FIND_QUIETLY TRUE)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
FIND_PATH(LIBVNCSERVER_INCLUDE_DIR rfb/rfb.h)
|
||||
|
||||
FIND_LIBRARY(LIBVNCSERVER_LIBRARIES NAMES vncserver libvncserver)
|
||||
|
||||
# libvncserver and libvncclient are in the same package, so it does
|
||||
# not make sense to add a new cmake script for finding libvncclient.
|
||||
# instead just find the libvncclient also in this file.
|
||||
FIND_PATH(LIBVNCCLIENT_INCLUDE_DIR rfb/rfbclient.h)
|
||||
FIND_LIBRARY(LIBVNCCLIENT_LIBRARIES NAMES vncclient libvncclient)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
SET(CMAKE_REQUIRED_INCLUDES "${LIBVNCSERVER_INCLUDE_DIR}" "${CMAKE_REQUIRED_INCLUDES}")
|
||||
CHECK_POINTER_MEMBER(rfbClient* GotXCutText rfb/rfbclient.h LIBVNCSERVER_FOUND)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
IF (LIBVNCSERVER_FOUND)
|
||||
IF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found LibVNCServer: ${LIBVNCSERVER_LIBRARIES}")
|
||||
ENDIF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
ELSE (LIBVNCSERVER_FOUND)
|
||||
IF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could NOT find acceptable version of LibVNCServer (version 0.9 or later required).")
|
||||
ENDIF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
ENDIF (LIBVNCSERVER_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(LIBVNCSERVER_INCLUDE_DIR LIBVNCSERVER_LIBRARIES)
|
|
@ -20,6 +20,7 @@ target_link_libraries (krfbprivate
|
|||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${X11_X11_LIB}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties (krfbprivate PROPERTIES
|
||||
|
@ -103,6 +104,7 @@ target_link_libraries (krfb
|
|||
${QT_QTNETWORK_LIBRARY}
|
||||
${KDE4_KDNSSD_LIBS}
|
||||
${KDE4_KDEUI_LIBS}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
)
|
||||
|
||||
if(TelepathyQt4_FOUND)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef KRFB_RFB_H
|
||||
#define KRFB_RFB_H
|
||||
|
||||
#include "../libvncserver/rfb/rfb.h"
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
# Striped down version of libvncserver's original CMakeLists.txt
|
||||
|
||||
project(LibVNCServer)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckTypeSize)
|
||||
include(TestBigEndian)
|
||||
include(MacroBoolTo01)
|
||||
|
||||
set(FULL_PACKAGE_NAME "Krfb LibVNCServer")
|
||||
set(PACKAGE_VERSION "0.9.8-10-g17ce0c5")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
macro_optional_find_package(ZLIB)
|
||||
macro_log_feature(ZLIB_FOUND "ZLib" "The Zlib compression library" "http://www.zlib.net" FALSE "" "Used by the vncserver library.")
|
||||
|
||||
macro_optional_find_package(JPEG)
|
||||
macro_log_feature(JPEG_FOUND "LibJPEG" "The JPEG library" "" FALSE "" "Used by the vncserver library")
|
||||
|
||||
macro_bool_to_01(ZLIB_FOUND LIBVNCSERVER_HAVE_LIBZ)
|
||||
macro_bool_to_01(JPEG_FOUND LIBVNCSERVER_HAVE_LIBJPEG)
|
||||
option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON)
|
||||
# if(GNUTLS_FOUND)
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_TLS 1)
|
||||
# endif(GNUTLS_FOUND)
|
||||
# if(LIBGCRYPT_LIBRARIES)
|
||||
# message(STATUS "Found libgcrypt: ${LIBGCRYPT_LIBRARIES}")
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_GCRYPT 1)
|
||||
# endif(LIBGCRYPT_LIBRARIES)
|
||||
|
||||
|
||||
check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H)
|
||||
check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H)
|
||||
check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H)
|
||||
check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H)
|
||||
check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H)
|
||||
check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H)
|
||||
check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H)
|
||||
|
||||
# headers needed for check_type_size()
|
||||
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
|
||||
check_include_file("stdint.h" HAVE_STDINT_H)
|
||||
check_include_file("stddef.h" HAVE_STDDEF_H)
|
||||
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
|
||||
|
||||
check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY)
|
||||
|
||||
macro_bool_to_01(CMAKE_USE_PTHREADS_INIT LIBVNCSERVER_HAVE_LIBPTHREAD)
|
||||
if(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
# socklen_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
endif(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
if(HAVE_ARPA_INET_H)
|
||||
# in_addr_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h")
|
||||
endif(HAVE_ARPA_INET_H)
|
||||
|
||||
check_type_size(pid_t LIBVNCSERVER_PID_T)
|
||||
check_type_size(size_t LIBVNCSERVER_SIZE_T)
|
||||
check_type_size(socklen_t LIBVNCSERVER_SOCKLEN_T)
|
||||
check_type_size(in_addr_t LIBVNCSERVER_IN_ADDR_T)
|
||||
if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
set(LIBVNCSERVER_NEED_INADDR_T 1)
|
||||
endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
|
||||
test_big_endian(LIBVNCSERVER_WORDS_BIGENDIAN)
|
||||
|
||||
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libvncserver-config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libvncserver-config.h
|
||||
)
|
||||
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
main.c
|
||||
rfbserver.c
|
||||
rfbregion.c
|
||||
auth.c
|
||||
sockets.c
|
||||
stats.c
|
||||
corre.c
|
||||
hextile.c
|
||||
rre.c
|
||||
translate.c
|
||||
cutpaste.c
|
||||
httpd.c
|
||||
cursor.c
|
||||
font.c
|
||||
draw.c
|
||||
selbox.c
|
||||
d3des.c
|
||||
vncauth.c
|
||||
cargs.c
|
||||
minilzo.c
|
||||
ultra.c
|
||||
scale.c
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBZ)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
zlib.c
|
||||
zrle.c
|
||||
zrleoutstream.c
|
||||
zrlepalettehelper.c
|
||||
)
|
||||
endif(ZLIB_FOUND)
|
||||
|
||||
if(JPEG_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
tight.c
|
||||
)
|
||||
endif(JPEG_FOUND)
|
||||
|
||||
|
||||
add_library(vncserver STATIC ${LIBVNCSERVER_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
set(ADDITIONAL_LIBS ws2_32)
|
||||
endif(WIN32)
|
||||
|
||||
target_link_libraries(vncserver
|
||||
${ADDITIONAL_LIBS}
|
||||
${ZLIB_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
)
|
|
@ -1,375 +0,0 @@
|
|||
/*
|
||||
* auth.c - deal with authentication.
|
||||
*
|
||||
* This file implements the VNC authentication protocol when setting up an RFB
|
||||
* connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/* RFB 3.8 clients are well informed */
|
||||
void rfbClientSendString(rfbClientPtr cl, const char *reason);
|
||||
|
||||
|
||||
/*
|
||||
* Handle security types
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler* securityHandlers = NULL;
|
||||
|
||||
/*
|
||||
* This method registers a list of new security types.
|
||||
* It avoids same security type getting registered multiple times.
|
||||
* The order is not preserved if multiple security types are
|
||||
* registered at one-go.
|
||||
*/
|
||||
void
|
||||
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *head = securityHandlers, *next = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
next = handler->next;
|
||||
|
||||
while(head != NULL) {
|
||||
if(head == handler) {
|
||||
rfbRegisterSecurityHandler(next);
|
||||
return;
|
||||
}
|
||||
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
handler->next = securityHandlers;
|
||||
securityHandlers = handler;
|
||||
|
||||
rfbRegisterSecurityHandler(next);
|
||||
}
|
||||
|
||||
/*
|
||||
* This method unregisters a list of security types.
|
||||
* These security types won't be available for any new
|
||||
* client connection.
|
||||
*/
|
||||
void
|
||||
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *cur = NULL, *pre = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
if(securityHandlers == handler) {
|
||||
securityHandlers = securityHandlers->next;
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
return;
|
||||
}
|
||||
|
||||
cur = pre = securityHandlers;
|
||||
|
||||
while(cur) {
|
||||
if(cur == handler) {
|
||||
pre->next = cur->next;
|
||||
break;
|
||||
}
|
||||
pre = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the authentication challenge.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthSendChallenge(rfbClientPtr cl)
|
||||
{
|
||||
|
||||
/* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
|
||||
(same as rfbVncAuth). Just send the challenge. */
|
||||
rfbRandomBytes(cl->authChallenge);
|
||||
if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
|
||||
rfbLogPerror("rfbAuthNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbVncAuthProcessResponse. */
|
||||
cl->state = RFB_AUTHENTICATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the NO AUTHENTICATION. SCARR
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthNone(rfbClientPtr cl)
|
||||
{
|
||||
uint32_t authResult;
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) {
|
||||
rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cl->state = RFB_INITIALISATION;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Advertise the supported security types (protocol 3.7). Here before sending
|
||||
* the list of security types to the client one more security type is added
|
||||
* to the list if primaryType is not set to rfbSecTypeInvalid. This security
|
||||
* type is the standard vnc security type which does the vnc authentication
|
||||
* or it will be security type for no authentication.
|
||||
* Different security types will be added by applications using this library.
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerVncAuth = {
|
||||
rfbSecTypeVncAuth,
|
||||
rfbVncAuthSendChallenge,
|
||||
NULL
|
||||
};
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerNone = {
|
||||
rfbSecTypeNone,
|
||||
rfbVncAuthNone,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
|
||||
{
|
||||
/* The size of the message is the count of security types +1,
|
||||
* since the first byte is the number of types. */
|
||||
int size = 1;
|
||||
rfbSecurityHandler* handler;
|
||||
#define MAX_SECURITY_TYPES 255
|
||||
uint8_t buffer[MAX_SECURITY_TYPES+1];
|
||||
|
||||
|
||||
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
|
||||
switch (primaryType) {
|
||||
case rfbSecTypeNone:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
|
||||
break;
|
||||
}
|
||||
|
||||
for (handler = securityHandlers;
|
||||
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
|
||||
buffer[size] = handler->type;
|
||||
size++;
|
||||
}
|
||||
buffer[0] = (unsigned char)size-1;
|
||||
|
||||
/* Send the list. */
|
||||
if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityTypeList: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if count is 0, we need to send the reason and close the connection.
|
||||
*/
|
||||
if(size <= 1) {
|
||||
/* This means total count is Zero and so reason msg should be sent */
|
||||
/* The execution should never reach here */
|
||||
char* reason = "No authentication mode is registered!";
|
||||
|
||||
rfbClientSendString(cl, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbProcessClientSecurityType. */
|
||||
cl->state = RFB_SECURITY_TYPE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tell the client what security type will be used (protocol 3.3).
|
||||
*/
|
||||
static void
|
||||
rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
|
||||
{
|
||||
uint32_t value32;
|
||||
|
||||
/* Send the value. */
|
||||
value32 = Swap32IfLE(securityType);
|
||||
if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityType: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decide what to do next. */
|
||||
switch (securityType) {
|
||||
case rfbSecTypeNone:
|
||||
/* Dispatch client input to rfbProcessClientInitMessage. */
|
||||
cl->state = RFB_INITIALISATION;
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
/* Begin the standard VNC authentication procedure. */
|
||||
rfbVncAuthSendChallenge(cl);
|
||||
break;
|
||||
default:
|
||||
/* Impossible case (hopefully). */
|
||||
rfbLogPerror("rfbSendSecurityType: assertion failed");
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthNewClient is called right after negotiating the protocol
|
||||
* version. Depending on the protocol version, we send either a code
|
||||
* for authentication scheme to be used (protocol 3.3), or a list of
|
||||
* possible "security types" (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthNewClient(rfbClientPtr cl)
|
||||
{
|
||||
int32_t securityType = rfbSecTypeInvalid;
|
||||
|
||||
if (!cl->screen->authPasswdData || cl->reverseConnection) {
|
||||
/* chk if this condition is valid or not. */
|
||||
securityType = rfbSecTypeNone;
|
||||
} else if (cl->screen->authPasswdData) {
|
||||
securityType = rfbSecTypeVncAuth;
|
||||
}
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
|
||||
{
|
||||
/* Make sure we use only RFB 3.3 compatible security types. */
|
||||
if (securityType == rfbSecTypeInvalid) {
|
||||
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
|
||||
rfbClientConnFailed(cl, "Your viewer cannot handle required "
|
||||
"authentication methods");
|
||||
return;
|
||||
}
|
||||
rfbSendSecurityType(cl, securityType);
|
||||
} else {
|
||||
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
|
||||
rfbSendSecurityTypeList(cl, securityType);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the security type chosen by the client (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbProcessClientSecurityType(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t chosenType;
|
||||
rfbSecurityHandler* handler;
|
||||
|
||||
/* Read the security type. */
|
||||
n = rfbReadExact(cl, (char *)&chosenType, 1);
|
||||
if (n <= 0) {
|
||||
if (n == 0)
|
||||
rfbLog("rfbProcessClientSecurityType: client gone\n");
|
||||
else
|
||||
rfbLogPerror("rfbProcessClientSecurityType: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure it was present in the list sent by the server. */
|
||||
for (handler = securityHandlers; handler; handler = handler->next) {
|
||||
if (chosenType == handler->type) {
|
||||
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
|
||||
handler->handler(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthProcessClientMessage is called when the client sends its
|
||||
* authentication response.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthProcessClientMessage(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t response[CHALLENGESIZE];
|
||||
uint32_t authResult;
|
||||
|
||||
if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
|
||||
if (n != 0)
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
|
||||
rfbErr("rfbAuthProcessClientMessage: password check failed\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthFailed);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
}
|
||||
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
|
||||
if (cl->protocolMinorVersion > 7) {
|
||||
rfbClientSendString(cl, "password check failed!");
|
||||
}
|
||||
else
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
cl->state = RFB_INITIALISATION;
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
* This parses the command line arguments. It was seperated from main.c by
|
||||
* Justin Dearing <jdeari01@longisland.poly.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* see GPL (latest version) for full details
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
extern int rfbStringToAddr(char *str, in_addr_t *iface);
|
||||
|
||||
void
|
||||
rfbUsage(void)
|
||||
{
|
||||
rfbProtocolExtension* extension;
|
||||
|
||||
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
|
||||
fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
|
||||
fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
|
||||
" (use 'storepasswd' to create a password file)\n");
|
||||
fprintf(stderr, "-rfbversion 3.x Set the version of the RFB we choose to advertise\n");
|
||||
fprintf(stderr, "-permitfiletransfer permit file transfer support\n");
|
||||
fprintf(stderr, "-passwd plain-password use authentication \n"
|
||||
" (use plain-password as password, USE AT YOUR RISK)\n");
|
||||
fprintf(stderr, "-deferupdate time time in ms to defer updates "
|
||||
"(default 40)\n");
|
||||
fprintf(stderr, "-deferptrupdate time time in ms to defer pointer updates"
|
||||
" (default none)\n");
|
||||
fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n");
|
||||
fprintf(stderr, "-alwaysshared always treat new clients as shared\n");
|
||||
fprintf(stderr, "-nevershared never treat new clients as shared\n");
|
||||
fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a "
|
||||
"new non-shared\n"
|
||||
" connection comes in (refuse new connection "
|
||||
"instead)\n");
|
||||
fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n");
|
||||
fprintf(stderr, "-httpport portnum use portnum for http connection\n");
|
||||
fprintf(stderr, "-enablehttpproxy enable http proxy support\n");
|
||||
fprintf(stderr, "-progressive height enable progressive updating for slow links\n");
|
||||
fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n");
|
||||
fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n");
|
||||
|
||||
for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
|
||||
if(extension->usage)
|
||||
extension->usage();
|
||||
rfbReleaseExtensionIterator();
|
||||
}
|
||||
|
||||
/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
|
||||
POSITION points to the first non purged argument afterwards. */
|
||||
void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
|
||||
{
|
||||
int amount=(*argc)-(*position)-count;
|
||||
if(amount)
|
||||
memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
|
||||
(*argc)-=count;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
|
||||
for (i = i1 = 1; i < *argc;) {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
} else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->port = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->maxClientWait = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->authPasswdData = argv[++i];
|
||||
|
||||
} else if (strcmp(argv[i], "-permitfiletransfer") == 0) { /* -permitfiletransfer */
|
||||
rfbScreen->permitFileTransfer = TRUE;
|
||||
} else if (strcmp(argv[i], "-rfbversion") == 0) { /* -rfbversion 3.6 */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
sscanf(argv[++i],"%d.%d", &rfbScreen->protocolMajorVersion, &rfbScreen->protocolMinorVersion);
|
||||
} else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */
|
||||
char **passwds = malloc(sizeof(char**)*2);
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
passwds[0] = argv[++i];
|
||||
passwds[1] = NULL;
|
||||
rfbScreen->authPasswdData = (void*)passwds;
|
||||
rfbScreen->passwordCheck = rfbCheckPasswordByList;
|
||||
} else if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-deferptrupdate") == 0) { /* -deferptrupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferPtrUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->desktopName = argv[++i];
|
||||
} else if (strcmp(argv[i], "-alwaysshared") == 0) {
|
||||
rfbScreen->alwaysShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-nevershared") == 0) {
|
||||
rfbScreen->neverShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-dontdisconnect") == 0) {
|
||||
rfbScreen->dontDisconnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-httpdir") == 0) { /* -httpdir directory-path */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpDir = argv[++i];
|
||||
} else if (strcmp(argv[i], "-httpport") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpPort = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
|
||||
rfbScreen->httpEnableProxyConnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->progressiveSliceHeight = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-listen") == 0) { /* -listen ipaddr */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
rfbProtocolExtension* extension;
|
||||
int handled=0;
|
||||
|
||||
for(extension=rfbGetExtensionIterator();handled==0 && extension;
|
||||
extension=extension->next)
|
||||
if(extension->processArgument)
|
||||
handled = extension->processArgument(*argc - i, argv + i);
|
||||
rfbReleaseExtensionIterator();
|
||||
|
||||
if(handled==0) {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
i+=handled-1;
|
||||
}
|
||||
/* we just remove the processed arguments from the list */
|
||||
rfbPurgeArguments(argc,&i1,i-i1+1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
for (i = i1 = 1; i < *argc-1;) {
|
||||
if (strcmp(argv[i], "-bpp") == 0) {
|
||||
*bpp = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-width") == 0) {
|
||||
*width = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-height") == 0) {
|
||||
*height = atoi(argv[++i]);
|
||||
} else {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
rfbPurgeArguments(argc,&i1,i-i1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* corre.c
|
||||
*
|
||||
* Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
|
||||
* code is based on krw's original javatel rfbserver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the RRE encoded version. If the RRE encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
|
||||
static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
|
||||
static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
|
||||
static uint32_t getBgColour(char *data, int size, int bpp);
|
||||
static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
|
||||
int w, int h);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
if (h > cl->correMaxHeight) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
|
||||
h - cl->correMaxHeight));
|
||||
}
|
||||
|
||||
if (w > cl->correMaxWidth) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
|
||||
w - cl->correMaxWidth, h));
|
||||
}
|
||||
|
||||
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
|
||||
* rectangle using CoRRE encoding.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbRREHeader hdr;
|
||||
int nSubrects;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
if (cl->afterEncBufSize < maxRawSize) {
|
||||
cl->afterEncBufSize = maxRawSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
(*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat),
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 16:
|
||||
nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 32:
|
||||
nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
default:
|
||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nSubrects < 0) {
|
||||
|
||||
/* RRE encoding was too large, use raw */
|
||||
|
||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE,
|
||||
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
||||
cl->ublen += sz_rfbRREHeader;
|
||||
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
||||
* colour overwritten by single-coloured rectangles. It returns the number
|
||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
||||
* fit in the buffer. It puts the encoded rectangles in cl->afterEncBuf. The
|
||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
||||
* coordinate position.
|
||||
*
|
||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
||||
* <subrect> is [<colour><x><y><w><h>].
|
||||
*/
|
||||
|
||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
||||
static int \
|
||||
subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
|
||||
uint##bpp##_t cl; \
|
||||
rfbCoRRERectangle subrect; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
|
||||
\
|
||||
*((uint##bpp##_t*)client->afterEncBuf) = bg; \
|
||||
\
|
||||
client->afterEncBufLen = (bpp/8); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
||||
* We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
subrect.x = thex; \
|
||||
subrect.y = they; \
|
||||
subrect.w = thew; \
|
||||
subrect.h = theh; \
|
||||
\
|
||||
newLen = client->afterEncBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
|
||||
if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
|
||||
return -1; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
*((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
|
||||
client->afterEncBufLen += (bpp/8); \
|
||||
memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbCoRRERectangle); \
|
||||
client->afterEncBufLen += sz_rfbCoRRERectangle; \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return numsubs; \
|
||||
}
|
||||
|
||||
DEFINE_SUBRECT_ENCODE(8)
|
||||
DEFINE_SUBRECT_ENCODE(16)
|
||||
DEFINE_SUBRECT_ENCODE(32)
|
||||
|
||||
|
||||
/*
|
||||
* getBgColour() gets the most prevalent colour in a byte array.
|
||||
*/
|
||||
static uint32_t
|
||||
getBgColour(char *data, int size, int bpp)
|
||||
{
|
||||
|
||||
#define NUMCLRS 256
|
||||
|
||||
static int counts[NUMCLRS];
|
||||
int i,j,k;
|
||||
|
||||
int maxcount = 0;
|
||||
uint8_t maxclr = 0;
|
||||
|
||||
if (bpp != 8) {
|
||||
if (bpp == 16) {
|
||||
return ((uint16_t *)data)[0];
|
||||
} else if (bpp == 32) {
|
||||
return ((uint32_t *)data)[0];
|
||||
} else {
|
||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUMCLRS; i++) {
|
||||
counts[i] = 0;
|
||||
}
|
||||
|
||||
for (j=0; j<size; j++) {
|
||||
k = (int)(((uint8_t *)data)[j]);
|
||||
if (k >= NUMCLRS) {
|
||||
rfbLog("getBgColour: unusual colour = %d\n", k);
|
||||
return 0;
|
||||
}
|
||||
counts[k] += 1;
|
||||
if (counts[k] > maxcount) {
|
||||
maxcount = counts[k];
|
||||
maxclr = ((uint8_t *)data)[j];
|
||||
}
|
||||
}
|
||||
|
||||
return maxclr;
|
||||
}
|
|
@ -1,756 +0,0 @@
|
|||
/*
|
||||
* cursor.c - support for cursor shape updates.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
#include "private.h"
|
||||
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
|
||||
|
||||
/*
|
||||
* Send cursor shape either in X-style format or in client pixel format.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorShape(rfbClientPtr cl)
|
||||
{
|
||||
rfbCursorPtr pCursor;
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbXCursorColors colors;
|
||||
int saved_ublen;
|
||||
int bitmapRowBytes, maskBytes, dataBytes;
|
||||
int i, j;
|
||||
uint8_t *bitmapData;
|
||||
uint8_t bitmapByte;
|
||||
|
||||
/* TODO: scale the cursor data to the correct size */
|
||||
|
||||
pCursor = cl->screen->getCursorPtr(cl);
|
||||
/*if(!pCursor) return TRUE;*/
|
||||
|
||||
if (cl->useRichCursorEncoding) {
|
||||
if(pCursor && !pCursor->richSource)
|
||||
rfbMakeRichCursorFromXCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
|
||||
} else {
|
||||
if(pCursor && !pCursor->source)
|
||||
rfbMakeXCursorFromRichCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingXCursor);
|
||||
}
|
||||
|
||||
/* If there is no cursor, send update with empty cursor data. */
|
||||
|
||||
if ( pCursor && pCursor->width == 1 &&
|
||||
pCursor->height == 1 &&
|
||||
pCursor->mask[0] == 0 ) {
|
||||
pCursor = NULL;
|
||||
}
|
||||
|
||||
if (pCursor == NULL) {
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
rect.r.x = rect.r.y = 0;
|
||||
rect.r.w = rect.r.h = 0;
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Calculate data sizes. */
|
||||
|
||||
bitmapRowBytes = (pCursor->width + 7) / 8;
|
||||
maskBytes = bitmapRowBytes * pCursor->height;
|
||||
dataBytes = (cl->useRichCursorEncoding) ?
|
||||
(pCursor->width * pCursor->height *
|
||||
(cl->format.bitsPerPixel / 8)) : maskBytes;
|
||||
|
||||
/* Send buffer contents if needed. */
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
return FALSE; /* FIXME. */
|
||||
}
|
||||
|
||||
saved_ublen = cl->ublen;
|
||||
|
||||
/* Prepare rectangle header. */
|
||||
|
||||
rect.r.x = Swap16IfLE(pCursor->xhot);
|
||||
rect.r.y = Swap16IfLE(pCursor->yhot);
|
||||
rect.r.w = Swap16IfLE(pCursor->width);
|
||||
rect.r.h = Swap16IfLE(pCursor->height);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
/* Prepare actual cursor data (depends on encoding used). */
|
||||
|
||||
if (!cl->useRichCursorEncoding) {
|
||||
/* XCursor encoding. */
|
||||
colors.foreRed = (char)(pCursor->foreRed >> 8);
|
||||
colors.foreGreen = (char)(pCursor->foreGreen >> 8);
|
||||
colors.foreBlue = (char)(pCursor->foreBlue >> 8);
|
||||
colors.backRed = (char)(pCursor->backRed >> 8);
|
||||
colors.backGreen = (char)(pCursor->backGreen >> 8);
|
||||
colors.backBlue = (char)(pCursor->backBlue >> 8);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
|
||||
cl->ublen += sz_rfbXCursorColors;
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->source;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* RichCursor encoding. */
|
||||
int bpp1=cl->screen->serverFormat.bitsPerPixel/8,
|
||||
bpp2=cl->format.bitsPerPixel/8;
|
||||
(*cl->translateFn)(cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat),
|
||||
&cl->format, (char*)pCursor->richSource,
|
||||
&cl->updateBuf[cl->ublen],
|
||||
pCursor->width*bpp1, pCursor->width, pCursor->height);
|
||||
|
||||
cl->ublen += pCursor->width*bpp2*pCursor->height;
|
||||
}
|
||||
|
||||
/* Prepare transparency mask. */
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->mask;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send everything we have prepared in the cl->updateBuf[]. */
|
||||
rfbStatRecordEncodingSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor),
|
||||
sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen));
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send cursor position (PointerPos pseudo-encoding).
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorPos(rfbClientPtr cl)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
|
||||
rect.r.x = Swap16IfLE(cl->screen->cursorX);
|
||||
rect.r.y = Swap16IfLE(cl->screen->cursorY);
|
||||
rect.r.w = 0;
|
||||
rect.r.h = 0;
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* conversion routine for predefined cursors in LSB order */
|
||||
unsigned char rfbReverseByte[0x100] = {
|
||||
/* copied from Xvnc/lib/font/util/utilbitmap.c */
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||
};
|
||||
|
||||
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
|
||||
{
|
||||
int i,t=(width+7)/8*height;
|
||||
for(i=0;i<t;i++)
|
||||
bitmap[i]=rfbReverseByte[(int)bitmap[i]];
|
||||
}
|
||||
|
||||
/* Cursor creation. You "paint" a cursor and let these routines do the work */
|
||||
|
||||
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
|
||||
char* cp;
|
||||
unsigned char bit;
|
||||
|
||||
cursor->cleanup=TRUE;
|
||||
cursor->width=width;
|
||||
cursor->height=height;
|
||||
/*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
|
||||
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
|
||||
|
||||
cursor->source = (unsigned char*)calloc(w,height);
|
||||
cursor->cleanupSource = TRUE;
|
||||
for(j=0,cp=cursorString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
|
||||
|
||||
if(maskString) {
|
||||
cursor->mask = (unsigned char*)calloc(w,height);
|
||||
for(j=0,cp=maskString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
|
||||
} else
|
||||
cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
|
||||
cursor->cleanupMask = TRUE;
|
||||
|
||||
return(cursor);
|
||||
}
|
||||
|
||||
char* rfbMakeMaskForXCursor(int width,int height,char* source)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
char* mask=(char*)calloc(w,height);
|
||||
unsigned char c;
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=w-1;i>=0;i--) {
|
||||
c=source[j*w+i];
|
||||
if(j>0) c|=source[(j-1)*w+i];
|
||||
if(j<height-1) c|=source[(j+1)*w+i];
|
||||
|
||||
if(i>0 && (c&0x80))
|
||||
mask[j*w+i-1]|=0x01;
|
||||
if(i<w-1 && (c&0x01))
|
||||
mask[j*w+i+1]|=0x80;
|
||||
|
||||
mask[j*w+i]|=(c<<1)|c|(c>>1);
|
||||
}
|
||||
|
||||
return(mask);
|
||||
}
|
||||
|
||||
/* this function dithers the alpha using Floyd-Steinberg */
|
||||
|
||||
char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource)
|
||||
{
|
||||
int* error=(int*)calloc(sizeof(int),width);
|
||||
int i,j,currentError=0,maskStride=(width+7)/8;
|
||||
unsigned char* result=(unsigned char*)calloc(maskStride,height);
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=0;i<width;i++) {
|
||||
int right,middle,left;
|
||||
currentError+=alphaSource[i+width*j]+error[i];
|
||||
|
||||
if(currentError<0x80) {
|
||||
/* set to transparent */
|
||||
/* alpha was treated as 0 */
|
||||
} else {
|
||||
/* set to solid */
|
||||
result[i/8+j*maskStride]|=(0x100>>(i&7));
|
||||
/* alpha was treated as 0xff */
|
||||
currentError-=0xff;
|
||||
}
|
||||
/* propagate to next row */
|
||||
right=currentError/16;
|
||||
middle=currentError*5/16;
|
||||
left=currentError*3/16;
|
||||
currentError-=right+middle+left;
|
||||
error[i]=right;
|
||||
if(i>0) {
|
||||
error[i-1]=middle;
|
||||
if(i>1)
|
||||
error[i-2]=left;
|
||||
}
|
||||
}
|
||||
free(error);
|
||||
return (char *) result;
|
||||
}
|
||||
|
||||
void rfbFreeCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
if(cursor) {
|
||||
if(cursor->cleanupRichSource && cursor->richSource)
|
||||
free(cursor->richSource);
|
||||
if(cursor->cleanupRichSource && cursor->alphaSource)
|
||||
free(cursor->alphaSource);
|
||||
if(cursor->cleanupSource && cursor->source)
|
||||
free(cursor->source);
|
||||
if(cursor->cleanupMask && cursor->mask)
|
||||
free(cursor->mask);
|
||||
if(cursor->cleanup)
|
||||
free(cursor);
|
||||
else {
|
||||
cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
|
||||
=cursor->cleanupRichSource=FALSE;
|
||||
cursor->source=cursor->mask=cursor->richSource=NULL;
|
||||
cursor->alphaSource=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* background and foregroud colour have to be set beforehand */
|
||||
void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
|
||||
width=cursor->width*bpp;
|
||||
uint32_t background;
|
||||
char *back=(char*)&background;
|
||||
unsigned char bit;
|
||||
int interp = 0, db = 0;
|
||||
|
||||
if(cursor->source && cursor->cleanupSource)
|
||||
free(cursor->source);
|
||||
cursor->source=(unsigned char*)calloc(w,cursor->height);
|
||||
cursor->cleanupSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
}
|
||||
|
||||
/* all zeros means we should interpolate to black+white ourselves */
|
||||
if (!cursor->backRed && !cursor->backGreen && !cursor->backBlue &&
|
||||
!cursor->foreRed && !cursor->foreGreen && !cursor->foreBlue) {
|
||||
if (format->trueColour && (bpp == 1 || bpp == 2 || bpp == 4)) {
|
||||
interp = 1;
|
||||
cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
background = ((format->redMax * cursor->backRed) / 0xffff) << format->redShift |
|
||||
((format->greenMax * cursor->backGreen) / 0xffff) << format->greenShift |
|
||||
((format->blueMax * cursor->backBlue) / 0xffff) << format->blueShift;
|
||||
|
||||
#define SETRGB(u) \
|
||||
r = (255 * (((format->redMax << format->redShift) & (*u)) >> format->redShift)) / format->redMax; \
|
||||
g = (255 * (((format->greenMax << format->greenShift) & (*u)) >> format->greenShift)) / format->greenMax; \
|
||||
b = (255 * (((format->blueMax << format->blueShift) & (*u)) >> format->blueShift)) / format->blueMax;
|
||||
|
||||
if (db) fprintf(stderr, "interp: %d\n", interp);
|
||||
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1) {
|
||||
if (interp) {
|
||||
int r = 0, g = 0, b = 0, grey;
|
||||
unsigned char *p = cursor->richSource+j*width+i*bpp;
|
||||
if (bpp == 1) {
|
||||
unsigned char* uc = (unsigned char*) p;
|
||||
SETRGB(uc);
|
||||
} else if (bpp == 2) {
|
||||
unsigned short* us = (unsigned short*) p;
|
||||
SETRGB(us);
|
||||
} else if (bpp == 4) {
|
||||
unsigned int* ui = (unsigned int*) p;
|
||||
SETRGB(ui);
|
||||
}
|
||||
grey = (r + g + b) / 3;
|
||||
if (grey >= 128) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
if (db) fprintf(stderr, "1");
|
||||
} else {
|
||||
if (db) fprintf(stderr, "0");
|
||||
}
|
||||
|
||||
} else if(memcmp(cursor->richSource+j*width+i*bpp, back, bpp)) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
}
|
||||
}
|
||||
if (db) fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
|
||||
uint32_t background,foreground;
|
||||
char *back=(char*)&background,*fore=(char*)&foreground;
|
||||
unsigned char *cp;
|
||||
unsigned char bit;
|
||||
|
||||
if(cursor->richSource && cursor->cleanupRichSource)
|
||||
free(cursor->richSource);
|
||||
cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
|
||||
cursor->cleanupRichSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
fore+=4-bpp;
|
||||
}
|
||||
|
||||
background=cursor->backRed<<format->redShift|
|
||||
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
|
||||
foreground=cursor->foreRed<<format->redShift|
|
||||
cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
|
||||
|
||||
for(j=0;j<cursor->height;j++)
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
|
||||
if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
|
||||
else memcpy(cp,back,bpp);
|
||||
}
|
||||
|
||||
/* functions to draw/hide cursor directly in the frame buffer */
|
||||
|
||||
void rfbHideCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes;
|
||||
LOCK(s->cursorMutex);
|
||||
if(!c) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* restore what is under the cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) x1=0;
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) y1=0;
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get saved data */
|
||||
for(j=0;j<y2;j++)
|
||||
memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
|
||||
s->underCursorBuffer+j*x2*bpp,
|
||||
x2*bpp);
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
void rfbShowCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes,
|
||||
bufSize,w;
|
||||
rfbBool wasChanged=FALSE;
|
||||
|
||||
if(!c) return;
|
||||
LOCK(s->cursorMutex);
|
||||
|
||||
bufSize=c->width*c->height*bpp;
|
||||
w=(c->width+7)/8;
|
||||
if(s->underCursorBufferLen<bufSize) {
|
||||
if(s->underCursorBuffer!=NULL)
|
||||
free(s->underCursorBuffer);
|
||||
s->underCursorBuffer=malloc(bufSize);
|
||||
s->underCursorBufferLen=bufSize;
|
||||
}
|
||||
|
||||
/* save what is under the cursor */
|
||||
i1=j1=0; /* offset in cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) { i1=-x1; x1=0; }
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) { j1=-y1; y1=0; }
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
/* save data */
|
||||
for(j=0;j<y2;j++) {
|
||||
char* dest=s->underCursorBuffer+j*x2*bpp;
|
||||
const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp;
|
||||
unsigned int count=x2*bpp;
|
||||
if(wasChanged || memcmp(dest,src,count)) {
|
||||
wasChanged=TRUE;
|
||||
memcpy(dest,src,count);
|
||||
}
|
||||
}
|
||||
|
||||
if(!c->richSource)
|
||||
rfbMakeRichCursorFromXCursor(s,c);
|
||||
|
||||
if (c->alphaSource) {
|
||||
int rmax, rshift;
|
||||
int gmax, gshift;
|
||||
int bmax, bshift;
|
||||
int amax = 255; /* alphaSource is always 8bits of info per pixel */
|
||||
unsigned int rmask, gmask, bmask;
|
||||
|
||||
rmax = s->serverFormat.redMax;
|
||||
gmax = s->serverFormat.greenMax;
|
||||
bmax = s->serverFormat.blueMax;
|
||||
rshift = s->serverFormat.redShift;
|
||||
gshift = s->serverFormat.greenShift;
|
||||
bshift = s->serverFormat.blueShift;
|
||||
|
||||
rmask = (rmax << rshift);
|
||||
gmask = (gmax << gshift);
|
||||
bmask = (bmax << bshift);
|
||||
|
||||
for(j=0;j<y2;j++) {
|
||||
for(i=0;i<x2;i++) {
|
||||
/*
|
||||
* we loop over the whole cursor ignoring c->mask[],
|
||||
* using the extracted alpha value instead.
|
||||
*/
|
||||
char *dest;
|
||||
unsigned char *src, *aptr;
|
||||
unsigned int val, dval, sval;
|
||||
int rdst, gdst, bdst; /* fb RGB */
|
||||
int asrc, rsrc, gsrc, bsrc; /* rich source ARGB */
|
||||
|
||||
dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp;
|
||||
src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp;
|
||||
aptr = c->alphaSource + (j+j1)*c->width + (i+i1);
|
||||
|
||||
asrc = *aptr;
|
||||
if (!asrc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bpp == 1) {
|
||||
dval = *((unsigned char*) dest);
|
||||
sval = *((unsigned char*) src);
|
||||
} else if (bpp == 2) {
|
||||
dval = *((unsigned short*) dest);
|
||||
sval = *((unsigned short*) src);
|
||||
} else if (bpp == 3) {
|
||||
unsigned char *dst = (unsigned char *) dest;
|
||||
dval = 0;
|
||||
dval |= ((*(dst+0)) << 0);
|
||||
dval |= ((*(dst+1)) << 8);
|
||||
dval |= ((*(dst+2)) << 16);
|
||||
sval = 0;
|
||||
sval |= ((*(src+0)) << 0);
|
||||
sval |= ((*(src+1)) << 8);
|
||||
sval |= ((*(src+2)) << 16);
|
||||
} else if (bpp == 4) {
|
||||
dval = *((unsigned int*) dest);
|
||||
sval = *((unsigned int*) src);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* extract dest and src RGB */
|
||||
rdst = (dval & rmask) >> rshift; /* fb */
|
||||
gdst = (dval & gmask) >> gshift;
|
||||
bdst = (dval & bmask) >> bshift;
|
||||
|
||||
rsrc = (sval & rmask) >> rshift; /* richcursor */
|
||||
gsrc = (sval & gmask) >> gshift;
|
||||
bsrc = (sval & bmask) >> bshift;
|
||||
|
||||
/* blend in fb data. */
|
||||
if (! c->alphaPreMultiplied) {
|
||||
rsrc = (asrc * rsrc)/amax;
|
||||
gsrc = (asrc * gsrc)/amax;
|
||||
bsrc = (asrc * bsrc)/amax;
|
||||
}
|
||||
rdst = rsrc + ((amax - asrc) * rdst)/amax;
|
||||
gdst = gsrc + ((amax - asrc) * gdst)/amax;
|
||||
bdst = bsrc + ((amax - asrc) * bdst)/amax;
|
||||
|
||||
val = 0;
|
||||
val |= (rdst << rshift);
|
||||
val |= (gdst << gshift);
|
||||
val |= (bdst << bshift);
|
||||
|
||||
/* insert the cooked pixel into the fb */
|
||||
memcpy(dest, &val, bpp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* now the cursor has to be drawn */
|
||||
for(j=0;j<y2;j++)
|
||||
for(i=0;i<x2;i++)
|
||||
if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
|
||||
memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
|
||||
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
|
||||
}
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* If enableCursorShapeUpdates is FALSE, and the cursor is hidden, make sure
|
||||
* that if the frameBuffer was transmitted with a cursor drawn, then that
|
||||
* region gets redrawn.
|
||||
*/
|
||||
|
||||
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion)
|
||||
{
|
||||
rfbScreenInfoPtr s = cl->screen;
|
||||
rfbCursorPtr c = s->cursor;
|
||||
|
||||
if(c) {
|
||||
int x,y,x2,y2;
|
||||
|
||||
x = cl->cursorX-c->xhot;
|
||||
y = cl->cursorY-c->yhot;
|
||||
x2 = x+c->width;
|
||||
y2 = y+c->height;
|
||||
|
||||
if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) {
|
||||
sraRegionPtr rect;
|
||||
rect = sraRgnCreateRect(x,y,x2,y2);
|
||||
if(updateRegion) {
|
||||
sraRgnOr(updateRegion,rect);
|
||||
} else {
|
||||
LOCK(cl->updateMutex);
|
||||
sraRgnOr(cl->modifiedRegion,rect);
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
sraRgnDestroy(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void rfbPrintXCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
int i,i1,j,w=(cursor->width+7)/8;
|
||||
unsigned char bit;
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar(':');
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
|
||||
{
|
||||
rfbClientIteratorPtr iterator;
|
||||
rfbClientPtr cl;
|
||||
|
||||
LOCK(rfbScreen->cursorMutex);
|
||||
|
||||
if(rfbScreen->cursor) {
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator)))
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
if(rfbScreen->cursor->cleanup)
|
||||
rfbFreeCursor(rfbScreen->cursor);
|
||||
}
|
||||
|
||||
rfbScreen->cursor = c;
|
||||
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator))) {
|
||||
cl->cursorWasChanged = TRUE;
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
}
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
UNLOCK(rfbScreen->cursorMutex);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* cutpaste.c - routines to deal with cut & paste buffers / selection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetXCutText sets the cut buffer to be the given string. We also clear
|
||||
* the primary selection. Ideally we'd like to set it to the same thing, but I
|
||||
* can't work out how to do that without some kind of helper X client.
|
||||
*/
|
||||
|
||||
void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len)
|
||||
{
|
||||
rfbSendServerCutText(rfbScreen, str, len);
|
||||
}
|
|
@ -1,436 +0,0 @@
|
|||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC. Also the bytebit[] array
|
||||
* has been reversed so that the most significant bit in each byte of the
|
||||
* key is ignored, not the least significant.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* D3DES (V5.09) -
|
||||
*
|
||||
* A portable, public domain, version of the Data Encryption Standard.
|
||||
*
|
||||
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
|
||||
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
|
||||
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
|
||||
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
|
||||
* for humouring me on.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||
*/
|
||||
|
||||
#include "d3des.h"
|
||||
|
||||
static void scrunch(unsigned char *, unsigned long *);
|
||||
static void unscrun(unsigned long *, unsigned char *);
|
||||
static void desfunc(unsigned long *, unsigned long *);
|
||||
static void cookey(unsigned long *);
|
||||
|
||||
static unsigned long KnL[32] = { 0L };
|
||||
/*
|
||||
static unsigned long KnR[32] = { 0L };
|
||||
static unsigned long Kn3[32] = { 0L };
|
||||
static unsigned char Df_Key[24] = {
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
|
||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
|
||||
*/
|
||||
|
||||
static unsigned short bytebit[8] = {
|
||||
01, 02, 04, 010, 020, 040, 0100, 0200 };
|
||||
|
||||
static unsigned long bigbyte[24] = {
|
||||
0x800000L, 0x400000L, 0x200000L, 0x100000L,
|
||||
0x80000L, 0x40000L, 0x20000L, 0x10000L,
|
||||
0x8000L, 0x4000L, 0x2000L, 0x1000L,
|
||||
0x800L, 0x400L, 0x200L, 0x100L,
|
||||
0x80L, 0x40L, 0x20L, 0x10L,
|
||||
0x8L, 0x4L, 0x2L, 0x1L };
|
||||
|
||||
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
|
||||
|
||||
static unsigned char pc1[56] = {
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
|
||||
|
||||
static unsigned char totrot[16] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
|
||||
|
||||
static unsigned char pc2[48] = {
|
||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
|
||||
|
||||
void rfbDesKey(unsigned char *key,
|
||||
int edf)
|
||||
{
|
||||
register int i, j, l, m, n;
|
||||
unsigned char pc1m[56], pcr[56];
|
||||
unsigned long kn[32];
|
||||
|
||||
for ( j = 0; j < 56; j++ ) {
|
||||
l = pc1[j];
|
||||
m = l & 07;
|
||||
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) {
|
||||
if( edf == DE1 ) m = (15 - i) << 1;
|
||||
else m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0L;
|
||||
for( j = 0; j < 28; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 28 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 28; j < 56; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 56 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 0; j < 24; j++ ) {
|
||||
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
|
||||
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
|
||||
}
|
||||
}
|
||||
cookey(kn);
|
||||
return;
|
||||
}
|
||||
|
||||
static void cookey(register unsigned long *raw1)
|
||||
{
|
||||
register unsigned long *cook, *raw0;
|
||||
unsigned long dough[32];
|
||||
register int i;
|
||||
|
||||
cook = dough;
|
||||
for( i = 0; i < 16; i++, raw1++ ) {
|
||||
raw0 = raw1++;
|
||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
||||
*cook++ |= (*raw1 & 0x0000003fL);
|
||||
}
|
||||
rfbUseKey(dough);
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbCPKey(register unsigned long *into)
|
||||
{
|
||||
register unsigned long *from, *endp;
|
||||
|
||||
from = KnL, endp = &KnL[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbUseKey(register unsigned long *from)
|
||||
{
|
||||
register unsigned long *to, *endp;
|
||||
|
||||
to = KnL, endp = &KnL[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbDes(unsigned char *inblock,
|
||||
unsigned char *outblock)
|
||||
{
|
||||
unsigned long work[2];
|
||||
|
||||
scrunch(inblock, work);
|
||||
desfunc(work, KnL);
|
||||
unscrun(work, outblock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void scrunch(register unsigned char *outof,
|
||||
register unsigned long *into)
|
||||
{
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into++ |= (*outof++ & 0xffL);
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into |= (*outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void unscrun(register unsigned long *outof,
|
||||
register unsigned char *into)
|
||||
{
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into++ = (unsigned char)( *outof++ & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into = (unsigned char)( *outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long SP1[64] = {
|
||||
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
|
||||
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
|
||||
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
|
||||
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
|
||||
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
|
||||
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
|
||||
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
|
||||
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
|
||||
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
|
||||
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
|
||||
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
|
||||
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
|
||||
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
|
||||
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
|
||||
|
||||
static unsigned long SP2[64] = {
|
||||
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
|
||||
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
|
||||
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
|
||||
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
|
||||
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
|
||||
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
|
||||
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
|
||||
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
|
||||
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
|
||||
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
|
||||
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
|
||||
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
|
||||
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
|
||||
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
|
||||
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
|
||||
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
|
||||
|
||||
static unsigned long SP3[64] = {
|
||||
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
|
||||
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
|
||||
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
|
||||
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
|
||||
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
|
||||
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
|
||||
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
|
||||
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
|
||||
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
|
||||
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
|
||||
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
|
||||
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
|
||||
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
|
||||
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
|
||||
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
|
||||
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
|
||||
|
||||
static unsigned long SP4[64] = {
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
|
||||
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
|
||||
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
|
||||
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
|
||||
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
|
||||
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
|
||||
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
|
||||
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
|
||||
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
|
||||
|
||||
static unsigned long SP5[64] = {
|
||||
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
|
||||
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
|
||||
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
|
||||
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
|
||||
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
|
||||
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
|
||||
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
|
||||
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
|
||||
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
|
||||
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
|
||||
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
|
||||
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
|
||||
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
|
||||
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
|
||||
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
|
||||
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
|
||||
|
||||
static unsigned long SP6[64] = {
|
||||
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
|
||||
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
|
||||
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
|
||||
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
|
||||
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
|
||||
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
|
||||
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
|
||||
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
|
||||
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
|
||||
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
|
||||
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
|
||||
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
|
||||
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
|
||||
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
|
||||
|
||||
static unsigned long SP7[64] = {
|
||||
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
|
||||
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
|
||||
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
|
||||
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
|
||||
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
|
||||
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
|
||||
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
|
||||
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
|
||||
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
|
||||
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
|
||||
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
|
||||
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
|
||||
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
|
||||
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
|
||||
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
|
||||
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
|
||||
|
||||
static unsigned long SP8[64] = {
|
||||
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
|
||||
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
|
||||
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
|
||||
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
|
||||
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
|
||||
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
|
||||
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
|
||||
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
|
||||
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
|
||||
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
|
||||
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
|
||||
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
|
||||
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
|
||||
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
|
||||
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
|
||||
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
|
||||
|
||||
static void desfunc(register unsigned long *block,
|
||||
register unsigned long *keys)
|
||||
{
|
||||
register unsigned long fval, work, right, leftt;
|
||||
register int round;
|
||||
|
||||
leftt = block[0];
|
||||
right = block[1];
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 4);
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 16);
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
||||
leftt ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 8);
|
||||
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
|
||||
|
||||
for( round = 0; round < 8; round++ ) {
|
||||
work = (right << 28) | (right >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = right ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
leftt ^= fval;
|
||||
work = (leftt << 28) | (leftt >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = leftt ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
right ^= fval;
|
||||
}
|
||||
|
||||
right = (right << 31) | (right >> 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = (leftt << 31) | (leftt >> 1);
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 8);
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
||||
right ^= work;
|
||||
leftt ^= (work << 2);
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 16);
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 4);
|
||||
*block++ = right;
|
||||
*block = leftt;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validation sets:
|
||||
*
|
||||
* Single-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : c957 4425 6a5e d31d
|
||||
*
|
||||
* Double-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : 7f1d 0a77 826b 8aff
|
||||
*
|
||||
* Double-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
|
||||
*
|
||||
* Triple-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : de0b 7c06 ae5e 0ed5
|
||||
*
|
||||
* Triple-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
|
||||
*
|
||||
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
|
||||
**********************************************************************/
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef D3DES_H
|
||||
#define D3DES_H
|
||||
|
||||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* d3des.h -
|
||||
*
|
||||
* Headers and defines for d3des.c
|
||||
* Graven Imagery, 1992.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
|
||||
* (GEnie : OUTER; CIS : [71755,204])
|
||||
*/
|
||||
|
||||
#define EN0 0 /* MODE == encrypt */
|
||||
#define DE1 1 /* MODE == decrypt */
|
||||
|
||||
extern void rfbDesKey(unsigned char *, int);
|
||||
/* hexkey[8] MODE
|
||||
* Sets the internal key register according to the hexadecimal
|
||||
* key contained in the 8 bytes of hexkey, according to the DES,
|
||||
* for encryption or decryption according to MODE.
|
||||
*/
|
||||
|
||||
extern void rfbUseKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Loads the internal key register with the data in cookedkey.
|
||||
*/
|
||||
|
||||
extern void rfbCPKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Copies the contents of the internal key register into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
extern void rfbDes(unsigned char *, unsigned char *);
|
||||
/* from[8] to[8]
|
||||
* Encrypts/Decrypts (according to the key currently loaded in the
|
||||
* internal key register) one block of eight bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
|
||||
********************************************************************/
|
||||
|
||||
#endif
|
|
@ -1,61 +0,0 @@
|
|||
#include "rfb/rfb.h"
|
||||
|
||||
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i,j;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
for(j=y1;j<y2;j++)
|
||||
for(i=x1;i<x2;i++)
|
||||
memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp);
|
||||
rfbMarkRectAsModified(s,x1,y1,x2,y2);
|
||||
}
|
||||
|
||||
#define SETPIXEL(x,y) \
|
||||
memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp)
|
||||
|
||||
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
SETPIXEL(x,y);
|
||||
rfbMarkRectAsModified(s,x,y,x+1,y+1);
|
||||
}
|
||||
|
||||
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
|
||||
#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; }
|
||||
if(abs(x1-x2)<abs(y1-y2)) {
|
||||
if(y1>y2)
|
||||
SWAPPOINTS
|
||||
for(i=y1;i<=y2;i++)
|
||||
SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i);
|
||||
/* TODO: Maybe make this more intelligently? */
|
||||
if(x2<x1) { i=x1; x1=x2; x2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
} else {
|
||||
if(x1>x2)
|
||||
SWAPPOINTS
|
||||
else if(x1==x2) {
|
||||
rfbDrawPixel(s,x1,y1,col);
|
||||
return;
|
||||
}
|
||||
for(i=x1;i<=x2;i++)
|
||||
SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1));
|
||||
if(y2<y1) { i=y1; y1=y2; y2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
}
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
#include "rfb/rfb.h"
|
||||
|
||||
int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,unsigned char c,rfbPixel col)
|
||||
{
|
||||
int i,j,width,height;
|
||||
unsigned char* data=font->data+font->metaData[c*5];
|
||||
unsigned char d=*data;
|
||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
||||
int bpp=rfbScreen->serverFormat.bitsPerPixel/8;
|
||||
char *colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
|
||||
width=font->metaData[c*5+1];
|
||||
height=font->metaData[c*5+2];
|
||||
x+=font->metaData[c*5+3];
|
||||
y+=-font->metaData[c*5+4]-height+1;
|
||||
|
||||
for(j=0;j<height;j++) {
|
||||
for(i=0;i<width;i++) {
|
||||
if((i&7)==0) {
|
||||
d=*data;
|
||||
data++;
|
||||
}
|
||||
if(d&0x80 && y+j >= 0 && y+j < rfbScreen->height &&
|
||||
x+i >= 0 && x+i < rfbScreen->width)
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp);
|
||||
d<<=1;
|
||||
}
|
||||
/* if((i&7)!=0) data++; */
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,const char* string,rfbPixel colour)
|
||||
{
|
||||
while(*string) {
|
||||
x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: these two functions need to be more efficient */
|
||||
/* if col==bcol, assume transparent background */
|
||||
int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,unsigned char c,
|
||||
int x1,int y1,int x2,int y2,
|
||||
rfbPixel col,rfbPixel bcol)
|
||||
{
|
||||
int i,j,width,height;
|
||||
unsigned char* data=font->data+font->metaData[c*5];
|
||||
unsigned char d;
|
||||
int rowstride=rfbScreen->paddedWidthInBytes;
|
||||
int bpp=rfbScreen->serverFormat.bitsPerPixel/8,extra_bytes=0;
|
||||
char* colour=(char*)&col;
|
||||
char* bcolour=(char*)&bcol;
|
||||
|
||||
if(!rfbEndianTest) {
|
||||
colour+=4-bpp;
|
||||
bcolour+=4-bpp;
|
||||
}
|
||||
|
||||
width=font->metaData[c*5+1];
|
||||
height=font->metaData[c*5+2];
|
||||
x+=font->metaData[c*5+3];
|
||||
y+=-font->metaData[c*5+4]-height+1;
|
||||
|
||||
/* after clipping, x2 will be count of bytes between rows,
|
||||
* x1 start of i, y1 start of j, width and height will be adjusted. */
|
||||
if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0;
|
||||
if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0;
|
||||
if(y2<y+height) height-=y+height-y2;
|
||||
if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; }
|
||||
|
||||
d=*data;
|
||||
for(j=y1;j<height;j++) {
|
||||
if((x1&7)!=0)
|
||||
d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */
|
||||
for(i=x1;i<width;i++) {
|
||||
if((i&7)==0) {
|
||||
d=*data;
|
||||
data++;
|
||||
}
|
||||
/* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ {
|
||||
if(d&0x80) {
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
||||
colour,bpp);
|
||||
} else if(bcol!=col) {
|
||||
memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
|
||||
bcolour,bpp);
|
||||
}
|
||||
}
|
||||
d<<=1;
|
||||
}
|
||||
/* if((i&7)==0) data++; */
|
||||
data += extra_bytes;
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
int x,int y,const char* string,
|
||||
int x1,int y1,int x2,int y2,
|
||||
rfbPixel colour,rfbPixel backColour)
|
||||
{
|
||||
while(*string) {
|
||||
x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2,
|
||||
colour,backColour);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
int rfbWidthOfString(rfbFontDataPtr font,const char* string)
|
||||
{
|
||||
int i=0;
|
||||
while(*string) {
|
||||
i+=font->metaData[*string*5+1];
|
||||
string++;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
|
||||
{
|
||||
return(font->metaData[c*5+1]+font->metaData[c*5+3]);
|
||||
}
|
||||
|
||||
void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2)
|
||||
{
|
||||
*x1+=font->metaData[c*5+3];
|
||||
*y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1;
|
||||
*x2=*x1+font->metaData[c*5+1]+1;
|
||||
*y2=*y1+font->metaData[c*5+2]+1;
|
||||
}
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
void rfbWholeFontBBox(rfbFontDataPtr font,
|
||||
int *x1, int *y1, int *x2, int *y2)
|
||||
{
|
||||
int i;
|
||||
int* m=font->metaData;
|
||||
|
||||
(*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=1-(INT_MAX);
|
||||
for(i=0;i<256;i++) {
|
||||
if(m[i*5+1]-m[i*5+3]>(*x2))
|
||||
(*x2)=m[i*5+1]-m[i*5+3];
|
||||
if(-m[i*5+2]+m[i*5+4]<(*y1))
|
||||
(*y1)=-m[i*5+2]+m[i*5+4];
|
||||
if(m[i*5+3]<(*x1))
|
||||
(*x1)=m[i*5+3];
|
||||
if(-m[i*5+4]>(*y2))
|
||||
(*y2)=-m[i*5+4];
|
||||
}
|
||||
(*x2)++;
|
||||
(*y2)++;
|
||||
}
|
||||
|
||||
rfbFontDataPtr rfbLoadConsoleFont(char *filename)
|
||||
{
|
||||
FILE *f=fopen(filename,"rb");
|
||||
rfbFontDataPtr p;
|
||||
int i;
|
||||
|
||||
if(!f) return NULL;
|
||||
|
||||
p=(rfbFontDataPtr)malloc(sizeof(rfbFontData));
|
||||
p->data=(unsigned char*)malloc(4096);
|
||||
if(1!=fread(p->data,4096,1,f)) {
|
||||
free(p->data);
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
fclose(f);
|
||||
p->metaData=(int*)malloc(256*5*sizeof(int));
|
||||
for(i=0;i<256;i++) {
|
||||
p->metaData[i*5+0]=i*16; /* offset */
|
||||
p->metaData[i*5+1]=8; /* width */
|
||||
p->metaData[i*5+2]=16; /* height */
|
||||
p->metaData[i*5+3]=0; /* xhot */
|
||||
p->metaData[i*5+4]=0; /* yhot */
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
void rfbFreeFont(rfbFontDataPtr f)
|
||||
{
|
||||
free(f->data);
|
||||
free(f->metaData);
|
||||
free(f);
|
||||
}
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* hextile.c
|
||||
*
|
||||
* Routines to implement Hextile Encoding
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingHextile(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingHextile);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
|
||||
sz_rfbFramebufferUpdateRectHeader,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
return sendHextiles8(cl, x, y, w, h);
|
||||
case 16:
|
||||
return sendHextiles16(cl, x, y, w, h);
|
||||
case 32:
|
||||
return sendHextiles32(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
|
||||
|
||||
#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
|
||||
|
||||
#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
|
||||
cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
|
||||
|
||||
|
||||
#define DEFINE_SEND_HEXTILES(bpp) \
|
||||
\
|
||||
\
|
||||
static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \
|
||||
int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\
|
||||
static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \
|
||||
rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \
|
||||
\
|
||||
\
|
||||
/* \
|
||||
* rfbSendHextiles \
|
||||
*/ \
|
||||
\
|
||||
static rfbBool \
|
||||
sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \
|
||||
int x, y, w, h; \
|
||||
int startUblen; \
|
||||
char *fbptr; \
|
||||
uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \
|
||||
rfbBool mono, solid; \
|
||||
rfbBool validBg = FALSE; \
|
||||
rfbBool validFg = FALSE; \
|
||||
uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \
|
||||
\
|
||||
for (y = ry; y < ry+rh; y += 16) { \
|
||||
for (x = rx; x < rx+rw; x += 16) { \
|
||||
w = h = 16; \
|
||||
if (rx+rw - x < 16) \
|
||||
w = rx+rw - x; \
|
||||
if (ry+rh - y < 16) \
|
||||
h = ry+rh - y; \
|
||||
\
|
||||
if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
|
||||
UPDATE_BUF_SIZE) { \
|
||||
if (!rfbSendUpdateBuf(cl)) \
|
||||
return FALSE; \
|
||||
} \
|
||||
\
|
||||
fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8))); \
|
||||
\
|
||||
(*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \
|
||||
&cl->format, fbptr, (char *)clientPixelData, \
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h); \
|
||||
\
|
||||
startUblen = cl->ublen; \
|
||||
cl->updateBuf[startUblen] = 0; \
|
||||
cl->ublen++; \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
testColours##bpp(clientPixelData, w * h, \
|
||||
&mono, &solid, &newBg, &newFg); \
|
||||
\
|
||||
if (!validBg || (newBg != bg)) { \
|
||||
validBg = TRUE; \
|
||||
bg = newBg; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
|
||||
PUT_PIXEL##bpp(bg); \
|
||||
} \
|
||||
\
|
||||
if (solid) { \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
|
||||
\
|
||||
if (mono) { \
|
||||
if (!validFg || (newFg != fg)) { \
|
||||
validFg = TRUE; \
|
||||
fg = newFg; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
|
||||
PUT_PIXEL##bpp(fg); \
|
||||
} \
|
||||
} else { \
|
||||
validFg = FALSE; \
|
||||
cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
|
||||
} \
|
||||
\
|
||||
if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
|
||||
/* encoding was too large, use raw */ \
|
||||
validBg = FALSE; \
|
||||
validFg = FALSE; \
|
||||
cl->ublen = startUblen; \
|
||||
cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
|
||||
(*cl->translateFn)(cl->translateLookupTable, \
|
||||
&(cl->screen->serverFormat), &cl->format, fbptr, \
|
||||
(char *)clientPixelData, \
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h); \
|
||||
\
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
|
||||
w * h * (bpp/8)); \
|
||||
\
|
||||
cl->ublen += w * h * (bpp/8); \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
|
||||
w * h * (bpp/8)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
static rfbBool \
|
||||
subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \
|
||||
uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \
|
||||
{ \
|
||||
uint##bpp##_t cl2; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
int nSubrectsUblen; \
|
||||
\
|
||||
nSubrectsUblen = cl->ublen; \
|
||||
cl->ublen++; \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl2 = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl2) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl2) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) { \
|
||||
hy += 1; \
|
||||
} else { \
|
||||
hyflag = 0; \
|
||||
} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and \
|
||||
* (x,y,vx,vy). We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
if (mono) { \
|
||||
newLen = cl->ublen - nSubrectsUblen + 2; \
|
||||
} else { \
|
||||
newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
|
||||
} \
|
||||
\
|
||||
if (newLen > (w * h * (bpp/8))) \
|
||||
return FALSE; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
\
|
||||
if (!mono) PUT_PIXEL##bpp(cl2); \
|
||||
\
|
||||
cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
|
||||
cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
|
||||
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
cl->updateBuf[nSubrectsUblen] = numsubs; \
|
||||
\
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
/* \
|
||||
* testColours() tests if there are one (solid), two (mono) or more \
|
||||
* colours in a tile and gets a reasonable guess at the best background \
|
||||
* pixel, and the foreground pixel for mono. \
|
||||
*/ \
|
||||
\
|
||||
static void \
|
||||
testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \
|
||||
uint##bpp##_t *bg, uint##bpp##_t *fg) { \
|
||||
uint##bpp##_t colour1 = 0, colour2 = 0; \
|
||||
int n1 = 0, n2 = 0; \
|
||||
*mono = TRUE; \
|
||||
*solid = TRUE; \
|
||||
\
|
||||
for (; size > 0; size--, data++) { \
|
||||
\
|
||||
if (n1 == 0) \
|
||||
colour1 = *data; \
|
||||
\
|
||||
if (*data == colour1) { \
|
||||
n1++; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
if (n2 == 0) { \
|
||||
*solid = FALSE; \
|
||||
colour2 = *data; \
|
||||
} \
|
||||
\
|
||||
if (*data == colour2) { \
|
||||
n2++; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
*mono = FALSE; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (n1 > n2) { \
|
||||
*bg = colour1; \
|
||||
*fg = colour2; \
|
||||
} else { \
|
||||
*bg = colour2; \
|
||||
*fg = colour1; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFINE_SEND_HEXTILES(8)
|
||||
DEFINE_SEND_HEXTILES(16)
|
||||
DEFINE_SEND_HEXTILES(32)
|
|
@ -1,600 +0,0 @@
|
|||
/*
|
||||
* httpd.c - a simple HTTP server
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#define close closesocket
|
||||
#else
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBWRAP
|
||||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#define connection_close
|
||||
#ifndef connection_close
|
||||
|
||||
#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \
|
||||
"<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>File Not Found</H1></BODY>\n"
|
||||
|
||||
#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\n\r\n" \
|
||||
"<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>Invalid request</H1></BODY>\n"
|
||||
|
||||
#define OK_STR "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
|
||||
|
||||
#else
|
||||
|
||||
#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \
|
||||
"<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>File Not Found</H1></BODY>\n"
|
||||
|
||||
#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\nConnection: close\r\n\r\n" \
|
||||
"<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \
|
||||
"<BODY><H1>Invalid request</H1></BODY>\n"
|
||||
|
||||
#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n"
|
||||
|
||||
#endif
|
||||
|
||||
static void httpProcessInput(rfbScreenInfoPtr screen);
|
||||
static rfbBool compareAndSkip(char **ptr, const char *str);
|
||||
static rfbBool parseParams(const char *request, char *result, int max_bytes);
|
||||
static rfbBool validateString(char *str);
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
|
||||
static char buf[BUF_SIZE];
|
||||
static size_t buf_filled=0;
|
||||
|
||||
/*
|
||||
* httpInitSockets sets up the TCP socket to listen for HTTP connections.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
if (rfbScreen->httpInitDone)
|
||||
return;
|
||||
|
||||
rfbScreen->httpInitDone = TRUE;
|
||||
|
||||
if (!rfbScreen->httpDir)
|
||||
return;
|
||||
|
||||
if (rfbScreen->httpPort == 0) {
|
||||
rfbScreen->httpPort = rfbScreen->port-100;
|
||||
}
|
||||
|
||||
rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
|
||||
|
||||
rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort);
|
||||
|
||||
if ((rfbScreen->httpListenSock =
|
||||
rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) {
|
||||
rfbLogPerror("ListenOnTCPPort");
|
||||
return;
|
||||
}
|
||||
|
||||
/*AddEnabledDevice(httpListenSock);*/
|
||||
}
|
||||
|
||||
void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {
|
||||
if(rfbScreen->httpSock>-1) {
|
||||
close(rfbScreen->httpSock);
|
||||
FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds);
|
||||
rfbScreen->httpSock=-1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* httpCheckFds is called from ProcessInputEvents to check for input on the
|
||||
* HTTP socket(s). If there is input to process, httpProcessInput is called.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
int nfds;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
if (!rfbScreen->httpDir)
|
||||
return;
|
||||
|
||||
if (rfbScreen->httpListenSock < 0)
|
||||
return;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(rfbScreen->httpListenSock, &fds);
|
||||
if (rfbScreen->httpSock >= 0) {
|
||||
FD_SET(rfbScreen->httpSock, &fds);
|
||||
}
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv);
|
||||
if (nfds == 0) {
|
||||
return;
|
||||
}
|
||||
if (nfds < 0) {
|
||||
#ifdef WIN32
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno != EINTR)
|
||||
rfbLogPerror("httpCheckFds: select");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
|
||||
httpProcessInput(rfbScreen);
|
||||
}
|
||||
|
||||
if (FD_ISSET(rfbScreen->httpListenSock, &fds)) {
|
||||
if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);
|
||||
|
||||
if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock,
|
||||
(struct sockaddr *)&addr, &addrlen)) < 0) {
|
||||
rfbLogPerror("httpCheckFds: accept");
|
||||
return;
|
||||
}
|
||||
#ifdef USE_LIBWRAP
|
||||
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
|
||||
STRING_UNKNOWN)) {
|
||||
rfbLog("Rejected HTTP connection from client %s\n",
|
||||
inet_ntoa(addr.sin_addr));
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock=-1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(!rfbSetNonBlocking(rfbScreen->httpSock)) {
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock=-1;
|
||||
return;
|
||||
}
|
||||
/*AddEnabledDevice(httpSock);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
httpCloseSock(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
close(rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
buf_filled = 0;
|
||||
}
|
||||
|
||||
static rfbClientRec cl;
|
||||
|
||||
/*
|
||||
* httpProcessInput is called when input is received on the HTTP socket.
|
||||
*/
|
||||
|
||||
static void
|
||||
httpProcessInput(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
char fullFname[512];
|
||||
char params[1024];
|
||||
char *ptr;
|
||||
char *fname;
|
||||
unsigned int maxFnameLen;
|
||||
FILE* fd;
|
||||
rfbBool performSubstitutions = FALSE;
|
||||
char str[256+32];
|
||||
#ifndef WIN32
|
||||
char* user=getenv("USER");
|
||||
#endif
|
||||
|
||||
cl.sock=rfbScreen->httpSock;
|
||||
|
||||
if (strlen(rfbScreen->httpDir) > 255) {
|
||||
rfbErr("-httpd directory too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
strcpy(fullFname, rfbScreen->httpDir);
|
||||
fname = &fullFname[strlen(fullFname)];
|
||||
maxFnameLen = 511 - strlen(fullFname);
|
||||
|
||||
buf_filled=0;
|
||||
|
||||
/* Read data from the HTTP client until we get a complete request. */
|
||||
while (1) {
|
||||
ssize_t got;
|
||||
|
||||
if (buf_filled > sizeof (buf)) {
|
||||
rfbErr("httpProcessInput: HTTP request is too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
got = read (rfbScreen->httpSock, buf + buf_filled,
|
||||
sizeof (buf) - buf_filled - 1);
|
||||
|
||||
if (got <= 0) {
|
||||
if (got == 0) {
|
||||
rfbErr("httpd: premature connection close\n");
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
errno=WSAGetLastError();
|
||||
#endif
|
||||
if (errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
rfbLogPerror("httpProcessInput: read");
|
||||
}
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_filled += got;
|
||||
buf[buf_filled] = '\0';
|
||||
|
||||
/* Is it complete yet (is there a blank line)? */
|
||||
if (strstr (buf, "\r\r") || strstr (buf, "\n\n") ||
|
||||
strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r"))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Process the request. */
|
||||
if(rfbScreen->httpEnableProxyConnect) {
|
||||
const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n";
|
||||
if(!strncmp(buf, "CONNECT ", 8)) {
|
||||
if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) {
|
||||
rfbErr("httpd: CONNECT format invalid.\n");
|
||||
rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
/* proxy connection */
|
||||
rfbLog("httpd: client asked for CONNECT\n");
|
||||
rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
|
||||
rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
return;
|
||||
}
|
||||
if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) {
|
||||
/* proxy connection */
|
||||
rfbLog("httpd: client asked for /proxied.connection\n");
|
||||
rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
|
||||
rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
|
||||
rfbScreen->httpSock = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(buf, "GET ", 4)) {
|
||||
rfbErr("httpd: no GET line\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
} else {
|
||||
/* Only use the first line. */
|
||||
buf[strcspn(buf, "\n\r")] = '\0';
|
||||
}
|
||||
|
||||
if (strlen(buf) > maxFnameLen) {
|
||||
rfbErr("httpd: GET line too long\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) {
|
||||
rfbErr("httpd: couldn't parse GET line\n");
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fname[0] != '/') {
|
||||
rfbErr("httpd: filename didn't begin with '/'\n");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strchr(fname+1, '/') != NULL) {
|
||||
rfbErr("httpd: asking for file in other directory\n");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
|
||||
rfbLog("httpd: get '%s' for %s\n", fname+1,
|
||||
inet_ntoa(addr.sin_addr));
|
||||
|
||||
/* Extract parameters from the URL string if necessary */
|
||||
|
||||
params[0] = '\0';
|
||||
ptr = strchr(fname, '?');
|
||||
if (ptr != NULL) {
|
||||
*ptr = '\0';
|
||||
if (!parseParams(&ptr[1], params, 1024)) {
|
||||
params[0] = '\0';
|
||||
rfbErr("httpd: bad parameters in the URL\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If we were asked for '/', actually read the file index.vnc */
|
||||
|
||||
if (strcmp(fname, "/") == 0) {
|
||||
strcpy(fname, "/index.vnc");
|
||||
rfbLog("httpd: defaulting to '%s'\n", fname+1);
|
||||
}
|
||||
|
||||
/* Substitutions are performed on files ending .vnc */
|
||||
|
||||
if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
|
||||
performSubstitutions = TRUE;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
|
||||
if ((fd = fopen(fullFname, "r")) == 0) {
|
||||
rfbLogPerror("httpProcessInput: open");
|
||||
rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
rfbWriteExact(&cl, OK_STR, strlen(OK_STR));
|
||||
|
||||
while (1) {
|
||||
int n = fread(buf, 1, BUF_SIZE-1, fd);
|
||||
if (n < 0) {
|
||||
rfbLogPerror("httpProcessInput: read");
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
if (performSubstitutions) {
|
||||
|
||||
/* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
|
||||
This won't quite work properly if the .vnc file is longer than
|
||||
BUF_SIZE, but it's reasonable to assume that .vnc files will
|
||||
always be short. */
|
||||
|
||||
char *ptr = buf;
|
||||
char *dollar;
|
||||
buf[n] = 0; /* make sure it's null-terminated */
|
||||
|
||||
while ((dollar = strchr(ptr, '$'))!=NULL) {
|
||||
rfbWriteExact(&cl, ptr, (dollar - ptr));
|
||||
|
||||
ptr = dollar;
|
||||
|
||||
if (compareAndSkip(&ptr, "$WIDTH")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->width);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$HEIGHT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->height);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->width);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->height + 32);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$PORT")) {
|
||||
|
||||
sprintf(str, "%d", rfbScreen->port);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$DESKTOP")) {
|
||||
|
||||
rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$DISPLAY")) {
|
||||
|
||||
sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900);
|
||||
rfbWriteExact(&cl, str, strlen(str));
|
||||
|
||||
} else if (compareAndSkip(&ptr, "$USER")) {
|
||||
#ifndef WIN32
|
||||
if (user) {
|
||||
rfbWriteExact(&cl, user,
|
||||
strlen(user));
|
||||
} else
|
||||
#endif
|
||||
rfbWriteExact(&cl, "?", 1);
|
||||
} else if (compareAndSkip(&ptr, "$PARAMS")) {
|
||||
if (params[0] != '\0')
|
||||
rfbWriteExact(&cl, params, strlen(params));
|
||||
} else {
|
||||
if (!compareAndSkip(&ptr, "$$"))
|
||||
ptr++;
|
||||
|
||||
if (rfbWriteExact(&cl, "$", 1) < 0) {
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0)
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
/* For files not ending .vnc, just write out the buffer */
|
||||
|
||||
if (rfbWriteExact(&cl, buf, n) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
httpCloseSock(rfbScreen);
|
||||
}
|
||||
|
||||
|
||||
static rfbBool
|
||||
compareAndSkip(char **ptr, const char *str)
|
||||
{
|
||||
if (strncmp(*ptr, str, strlen(str)) == 0) {
|
||||
*ptr += strlen(str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the request tail after the '?' character, and format a sequence
|
||||
* of <param> tags for inclusion into an HTML page with embedded applet.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
parseParams(const char *request, char *result, int max_bytes)
|
||||
{
|
||||
char param_request[128];
|
||||
char param_formatted[196];
|
||||
const char *tail;
|
||||
char *delim_ptr;
|
||||
char *value_str;
|
||||
int cur_bytes, len;
|
||||
|
||||
result[0] = '\0';
|
||||
cur_bytes = 0;
|
||||
|
||||
tail = request;
|
||||
for (;;) {
|
||||
/* Copy individual "name=value" string into a buffer */
|
||||
delim_ptr = strchr((char *)tail, '&');
|
||||
if (delim_ptr == NULL) {
|
||||
if (strlen(tail) >= sizeof(param_request)) {
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(param_request, tail);
|
||||
} else {
|
||||
len = delim_ptr - tail;
|
||||
if (len >= sizeof(param_request)) {
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(param_request, tail, len);
|
||||
param_request[len] = '\0';
|
||||
}
|
||||
|
||||
/* Split the request into parameter name and value */
|
||||
value_str = strchr(¶m_request[1], '=');
|
||||
if (value_str == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
*value_str++ = '\0';
|
||||
if (strlen(value_str) == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Validate both parameter name and value */
|
||||
if (!validateString(param_request) || !validateString(value_str)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Prepare HTML-formatted representation of the name=value pair */
|
||||
len = sprintf(param_formatted,
|
||||
"<PARAM NAME=\"%s\" VALUE=\"%s\">\n",
|
||||
param_request, value_str);
|
||||
if (cur_bytes + len + 1 > max_bytes) {
|
||||
return FALSE;
|
||||
}
|
||||
strcat(result, param_formatted);
|
||||
cur_bytes += len;
|
||||
|
||||
/* Go to the next parameter */
|
||||
if (delim_ptr == NULL) {
|
||||
break;
|
||||
}
|
||||
tail = delim_ptr + 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the string consists only of alphanumeric characters, '+'
|
||||
* signs, underscores, and dots. Replace all '+' signs with spaces.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
validateString(char *str)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (ptr = str; *ptr != '\0'; ptr++) {
|
||||
if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') {
|
||||
if (*ptr == '+') {
|
||||
*ptr = ' ';
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
#ifndef _RFB_RFBCONFIG_H
|
||||
#define _RFB_RFBCONFIG_H
|
||||
|
||||
/* rfb/rfbconfig.h. Generated automatically by cmake. */
|
||||
|
||||
/* Enable 24 bit per pixel in native framebuffer */
|
||||
#cmakedefine LIBVNCSERVER_ALLOW24BPP 1
|
||||
|
||||
/* work around when write() returns ENOENT but does not mean it */
|
||||
#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `jpeg' library (-ljpeg). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1
|
||||
|
||||
/* Need a typedef for in_addr_t */
|
||||
#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* Define to 1 if libgcrypt is present */
|
||||
#cmakedefine LIBVNCSERVER_WITH_CLIENT_GCRYPT 1
|
||||
|
||||
/* Define to 1 if GnuTLS is present */
|
||||
#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#cmakedefine const @CMAKE_CONST@
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
#cmakedefine inline @CMAKE_INLINE@
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_PID_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_PID_T
|
||||
typedef int pid_t;
|
||||
#endif
|
||||
|
||||
/* The type for size_t */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_SIZE_T
|
||||
typedef int size_t;
|
||||
#endif
|
||||
|
||||
/* The type for socklen */
|
||||
#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1
|
||||
#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
/* once: _RFB_RFBCONFIG_H */
|
||||
#endif
|
|
@ -1,419 +0,0 @@
|
|||
/* lzoconf.h -- configuration for the LZO real-time data compression library
|
||||
|
||||
This file is part of the LZO real-time data compression library.
|
||||
|
||||
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
The LZO library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
The LZO library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the LZO library; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LZOCONF_H_INCLUDED
|
||||
#define __LZOCONF_H_INCLUDED 1
|
||||
|
||||
#define LZO_VERSION 0x2040
|
||||
#define LZO_VERSION_STRING "2.04"
|
||||
#define LZO_VERSION_DATE "Oct 31 2010"
|
||||
|
||||
/* internal Autoconf configuration file - only used when building LZO */
|
||||
#if defined(LZO_HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// LZO requires a conforming <limits.h>
|
||||
************************************************************************/
|
||||
|
||||
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
|
||||
# error "invalid CHAR_BIT"
|
||||
#endif
|
||||
#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
|
||||
# error "check your compiler installation"
|
||||
#endif
|
||||
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
|
||||
# error "your limits.h macros are broken"
|
||||
#endif
|
||||
|
||||
/* get OS and architecture defines */
|
||||
#ifndef __LZODEFS_H_INCLUDED
|
||||
#include "lzodefs.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// some core defines
|
||||
************************************************************************/
|
||||
|
||||
#if !defined(LZO_UINT32_C)
|
||||
# if (UINT_MAX < LZO_0xffffffffL)
|
||||
# define LZO_UINT32_C(c) c ## UL
|
||||
# else
|
||||
# define LZO_UINT32_C(c) ((c) + 0U)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* memory checkers */
|
||||
#if !defined(__LZO_CHECKER)
|
||||
# if defined(__BOUNDS_CHECKING_ON)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__CHECKER__)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__INSURE__)
|
||||
# define __LZO_CHECKER 1
|
||||
# elif defined(__PURIFY__)
|
||||
# define __LZO_CHECKER 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// integral and pointer types
|
||||
************************************************************************/
|
||||
|
||||
/* lzo_uint should match size_t */
|
||||
#if !defined(LZO_UINT_MAX)
|
||||
# if defined(LZO_ABI_LLP64) /* WIN64 */
|
||||
# if defined(LZO_OS_WIN64)
|
||||
typedef unsigned __int64 lzo_uint;
|
||||
typedef __int64 lzo_int;
|
||||
# else
|
||||
typedef unsigned long long lzo_uint;
|
||||
typedef long long lzo_int;
|
||||
# endif
|
||||
# define LZO_UINT_MAX 0xffffffffffffffffull
|
||||
# define LZO_INT_MAX 9223372036854775807LL
|
||||
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
|
||||
# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
|
||||
typedef unsigned int lzo_uint;
|
||||
typedef int lzo_int;
|
||||
# define LZO_UINT_MAX UINT_MAX
|
||||
# define LZO_INT_MAX INT_MAX
|
||||
# define LZO_INT_MIN INT_MIN
|
||||
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned long lzo_uint;
|
||||
typedef long lzo_int;
|
||||
# define LZO_UINT_MAX ULONG_MAX
|
||||
# define LZO_INT_MAX LONG_MAX
|
||||
# define LZO_INT_MIN LONG_MIN
|
||||
# else
|
||||
# error "lzo_uint"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Integral types with 32 bits or more. */
|
||||
#if !defined(LZO_UINT32_MAX)
|
||||
# if (UINT_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned int lzo_uint32;
|
||||
typedef int lzo_int32;
|
||||
# define LZO_UINT32_MAX UINT_MAX
|
||||
# define LZO_INT32_MAX INT_MAX
|
||||
# define LZO_INT32_MIN INT_MIN
|
||||
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||
typedef unsigned long lzo_uint32;
|
||||
typedef long lzo_int32;
|
||||
# define LZO_UINT32_MAX ULONG_MAX
|
||||
# define LZO_INT32_MAX LONG_MAX
|
||||
# define LZO_INT32_MIN LONG_MIN
|
||||
# else
|
||||
# error "lzo_uint32"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The larger type of lzo_uint and lzo_uint32. */
|
||||
#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
|
||||
# define lzo_xint lzo_uint
|
||||
#else
|
||||
# define lzo_xint lzo_uint32
|
||||
#endif
|
||||
|
||||
/* Memory model that allows to access memory at offsets of lzo_uint. */
|
||||
#if !defined(__LZO_MMODEL)
|
||||
# if (LZO_UINT_MAX <= UINT_MAX)
|
||||
# define __LZO_MMODEL /*empty*/
|
||||
# elif defined(LZO_HAVE_MM_HUGE_PTR)
|
||||
# define __LZO_MMODEL_HUGE 1
|
||||
# define __LZO_MMODEL __huge
|
||||
# else
|
||||
# define __LZO_MMODEL /*empty*/
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* no typedef here because of const-pointer issues */
|
||||
#define lzo_bytep unsigned char __LZO_MMODEL *
|
||||
#define lzo_charp char __LZO_MMODEL *
|
||||
#define lzo_voidp void __LZO_MMODEL *
|
||||
#define lzo_shortp short __LZO_MMODEL *
|
||||
#define lzo_ushortp unsigned short __LZO_MMODEL *
|
||||
#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
|
||||
#define lzo_int32p lzo_int32 __LZO_MMODEL *
|
||||
#define lzo_uintp lzo_uint __LZO_MMODEL *
|
||||
#define lzo_intp lzo_int __LZO_MMODEL *
|
||||
#define lzo_xintp lzo_xint __LZO_MMODEL *
|
||||
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
|
||||
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
|
||||
/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
|
||||
#define lzo_byte unsigned char __LZO_MMODEL
|
||||
|
||||
typedef int lzo_bool;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// function types
|
||||
************************************************************************/
|
||||
|
||||
/* name mangling */
|
||||
#if !defined(__LZO_EXTERN_C)
|
||||
# ifdef __cplusplus
|
||||
# define __LZO_EXTERN_C extern "C"
|
||||
# else
|
||||
# define __LZO_EXTERN_C extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* calling convention */
|
||||
#if !defined(__LZO_CDECL)
|
||||
# define __LZO_CDECL __lzo_cdecl
|
||||
#endif
|
||||
|
||||
/* DLL export information */
|
||||
#if !defined(__LZO_EXPORT1)
|
||||
# define __LZO_EXPORT1 /*empty*/
|
||||
#endif
|
||||
#if !defined(__LZO_EXPORT2)
|
||||
# define __LZO_EXPORT2 /*empty*/
|
||||
#endif
|
||||
|
||||
/* __cdecl calling convention for public C and assembly functions */
|
||||
#if !defined(LZO_PUBLIC)
|
||||
# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
|
||||
#endif
|
||||
#if !defined(LZO_EXTERN)
|
||||
# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
|
||||
#endif
|
||||
#if !defined(LZO_PRIVATE)
|
||||
# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
|
||||
#endif
|
||||
|
||||
/* function types */
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem,
|
||||
const lzo_bytep dict, lzo_uint dict_len );
|
||||
|
||||
typedef int
|
||||
(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem,
|
||||
const lzo_bytep dict, lzo_uint dict_len );
|
||||
|
||||
|
||||
/* Callback interface. Currently only the progress indicator ("nprogress")
|
||||
* is used, but this may change in a future release. */
|
||||
|
||||
struct lzo_callback_t;
|
||||
typedef struct lzo_callback_t lzo_callback_t;
|
||||
#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
|
||||
|
||||
/* malloc & free function types */
|
||||
typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
|
||||
(lzo_callback_p self, lzo_uint items, lzo_uint size);
|
||||
typedef void (__LZO_CDECL *lzo_free_func_t)
|
||||
(lzo_callback_p self, lzo_voidp ptr);
|
||||
|
||||
/* a progress indicator callback function */
|
||||
typedef void (__LZO_CDECL *lzo_progress_func_t)
|
||||
(lzo_callback_p, lzo_uint, lzo_uint, int);
|
||||
|
||||
struct lzo_callback_t
|
||||
{
|
||||
/* custom allocators (set to 0 to disable) */
|
||||
lzo_alloc_func_t nalloc; /* [not used right now] */
|
||||
lzo_free_func_t nfree; /* [not used right now] */
|
||||
|
||||
/* a progress indicator callback function (set to 0 to disable) */
|
||||
lzo_progress_func_t nprogress;
|
||||
|
||||
/* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
|
||||
* callbacks points back to this struct, so you are free to store
|
||||
* some extra info in the following variables. */
|
||||
lzo_voidp user1;
|
||||
lzo_xint user2;
|
||||
lzo_xint user3;
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// error codes and prototypes
|
||||
************************************************************************/
|
||||
|
||||
/* Error codes for the compression/decompression functions. Negative
|
||||
* values are errors, positive values will be used for special but
|
||||
* normal events.
|
||||
*/
|
||||
#define LZO_E_OK 0
|
||||
#define LZO_E_ERROR (-1)
|
||||
#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
|
||||
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
|
||||
#define LZO_E_INPUT_OVERRUN (-4)
|
||||
#define LZO_E_OUTPUT_OVERRUN (-5)
|
||||
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
|
||||
#define LZO_E_EOF_NOT_FOUND (-7)
|
||||
#define LZO_E_INPUT_NOT_CONSUMED (-8)
|
||||
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
|
||||
|
||||
|
||||
#ifndef lzo_sizeof_dict_t
|
||||
# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
|
||||
#endif
|
||||
|
||||
/* lzo_init() should be the first function you call.
|
||||
* Check the return code !
|
||||
*
|
||||
* lzo_init() is a macro to allow checking that the library and the
|
||||
* compiler's view of various types are consistent.
|
||||
*/
|
||||
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
|
||||
(int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
|
||||
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
|
||||
(int)sizeof(lzo_callback_t))
|
||||
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
|
||||
|
||||
/* version functions (useful for shared libraries) */
|
||||
LZO_EXTERN(unsigned) lzo_version(void);
|
||||
LZO_EXTERN(const char *) lzo_version_string(void);
|
||||
LZO_EXTERN(const char *) lzo_version_date(void);
|
||||
LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
|
||||
LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
|
||||
|
||||
/* string functions */
|
||||
LZO_EXTERN(int)
|
||||
lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||
LZO_EXTERN(lzo_voidp)
|
||||
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
|
||||
|
||||
/* checksum functions */
|
||||
LZO_EXTERN(lzo_uint32)
|
||||
lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||
LZO_EXTERN(lzo_uint32)
|
||||
lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||
LZO_EXTERN(const lzo_uint32p)
|
||||
lzo_get_crc32_table(void);
|
||||
|
||||
/* misc. */
|
||||
LZO_EXTERN(int) _lzo_config_check(void);
|
||||
typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
|
||||
typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
|
||||
typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
|
||||
|
||||
/* align a char pointer on a boundary that is a multiple of 'size' */
|
||||
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
|
||||
#define LZO_PTR_ALIGN_UP(p,size) \
|
||||
((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// deprecated macros - only for backward compatibility with LZO v1.xx
|
||||
************************************************************************/
|
||||
|
||||
#if defined(LZO_CFG_COMPAT)
|
||||
|
||||
#define __LZOCONF_H 1
|
||||
|
||||
#if defined(LZO_ARCH_I086)
|
||||
# define __LZO_i386 1
|
||||
#elif defined(LZO_ARCH_I386)
|
||||
# define __LZO_i386 1
|
||||
#endif
|
||||
|
||||
#if defined(LZO_OS_DOS16)
|
||||
# define __LZO_DOS 1
|
||||
# define __LZO_DOS16 1
|
||||
#elif defined(LZO_OS_DOS32)
|
||||
# define __LZO_DOS 1
|
||||
#elif defined(LZO_OS_WIN16)
|
||||
# define __LZO_WIN 1
|
||||
# define __LZO_WIN16 1
|
||||
#elif defined(LZO_OS_WIN32)
|
||||
# define __LZO_WIN 1
|
||||
#endif
|
||||
|
||||
#define __LZO_CMODEL /*empty*/
|
||||
#define __LZO_DMODEL /*empty*/
|
||||
#define __LZO_ENTRY __LZO_CDECL
|
||||
#define LZO_EXTERN_CDECL LZO_EXTERN
|
||||
#define LZO_ALIGN LZO_PTR_ALIGN_UP
|
||||
|
||||
#define lzo_compress_asm_t lzo_compress_t
|
||||
#define lzo_decompress_asm_t lzo_decompress_t
|
||||
|
||||
#endif /* LZO_CFG_COMPAT */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/* vim:set ts=4 et: */
|
File diff suppressed because it is too large
Load Diff
1181
libvncserver/main.c
1181
libvncserver/main.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +0,0 @@
|
|||
/* minilzo.h -- mini subset of the LZO real-time data compression library
|
||||
|
||||
This file is part of the LZO real-time data compression library.
|
||||
|
||||
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
The LZO library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
The LZO library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the LZO library; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* the full LZO package can be found at
|
||||
* http://www.oberhumer.com/opensource/lzo/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MINILZO_H
|
||||
#define __MINILZO_H 1
|
||||
|
||||
#define MINILZO_VERSION 0x2040
|
||||
|
||||
#ifdef __LZOCONF_H
|
||||
# error "you cannot use both LZO and miniLZO"
|
||||
#endif
|
||||
|
||||
#undef LZO_HAVE_CONFIG_H
|
||||
#include "lzoconf.h"
|
||||
|
||||
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
|
||||
# error "version mismatch in header files"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
//
|
||||
************************************************************************/
|
||||
|
||||
/* Memory required for the wrkmem parameter.
|
||||
* When the required size is 0, you can also pass a NULL pointer.
|
||||
*/
|
||||
|
||||
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
|
||||
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
|
||||
#define LZO1X_MEM_DECOMPRESS (0)
|
||||
|
||||
|
||||
/* compression */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem );
|
||||
|
||||
/* decompression */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem /* NOT USED */ );
|
||||
|
||||
/* safe decompression with overrun testing */
|
||||
LZO_EXTERN(int)
|
||||
lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
|
||||
lzo_bytep dst, lzo_uintp dst_len,
|
||||
lzo_voidp wrkmem /* NOT USED */ );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* already included */
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef RFB_PRIVATE_H
|
||||
#define RFB_PRIVATE_H
|
||||
|
||||
/* from cursor.c */
|
||||
|
||||
void rfbShowCursor(rfbClientPtr cl);
|
||||
void rfbHideCursor(rfbClientPtr cl);
|
||||
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion);
|
||||
|
||||
/* from main.c */
|
||||
|
||||
rfbClientPtr rfbClientIteratorHead(rfbClientIteratorPtr i);
|
||||
|
||||
/* from tight.c */
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
|
||||
extern void rfbTightCleanup(rfbScreenInfoPtr screen);
|
||||
#endif
|
||||
|
||||
/* from zlib.c */
|
||||
extern void rfbZlibCleanup(rfbScreenInfoPtr screen);
|
||||
|
||||
/* from zrle.c */
|
||||
void rfbFreeZrleData(rfbClientPtr cl);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* from ultra.c */
|
||||
|
||||
extern void rfbFreeUltraData(rfbClientPtr cl);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
static unsigned char default8x16FontData[4096+1]={
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00,
|
||||
0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,
|
||||
0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00,
|
||||
0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,
|
||||
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,
|
||||
0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00,
|
||||
0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00,
|
||||
0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00,
|
||||
0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00,
|
||||
0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00,
|
||||
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
|
||||
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||
0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
|
||||
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00,
|
||||
0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
static int default8x16FontMetaData[256*5+1]={
|
||||
0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,};
|
||||
static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData };
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,430 +0,0 @@
|
|||
#ifndef RFBCLIENT_H
|
||||
#define RFBCLIENT_H
|
||||
|
||||
/**
|
||||
* @defgroup libvncclient_api LibVNCClient API Reference
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rfbclient.h
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "rfbproto.h"
|
||||
#include "keysym.h"
|
||||
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
#define rfbClientSwap16IfLE(s) \
|
||||
(*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
|
||||
|
||||
#define rfbClientSwap32IfLE(l) \
|
||||
(*(char *)&client->endianTest ? ((((l) & 0xff000000) >> 24) | \
|
||||
(((l) & 0x00ff0000) >> 8) | \
|
||||
(((l) & 0x0000ff00) << 8) | \
|
||||
(((l) & 0x000000ff) << 24)) : (l))
|
||||
|
||||
#define rfbClientSwap64IfLE(l) \
|
||||
(*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \
|
||||
(((l) & 0x00ff000000000000ULL) >> 40) | \
|
||||
(((l) & 0x0000ff0000000000ULL) >> 24) | \
|
||||
(((l) & 0x000000ff00000000ULL) >> 8) | \
|
||||
(((l) & 0x00000000ff000000ULL) << 8) | \
|
||||
(((l) & 0x0000000000ff0000ULL) << 24) | \
|
||||
(((l) & 0x000000000000ff00ULL) << 40) | \
|
||||
(((l) & 0x00000000000000ffULL) << 56)) : (l))
|
||||
|
||||
#define FLASH_PORT_OFFSET 5400
|
||||
#define LISTEN_PORT_OFFSET 5500
|
||||
#define TUNNEL_PORT_OFFSET 5500
|
||||
#define SERVER_PORT_OFFSET 5900
|
||||
|
||||
#define DEFAULT_SSH_CMD "/usr/bin/ssh"
|
||||
#define DEFAULT_TUNNEL_CMD \
|
||||
(DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20")
|
||||
#define DEFAULT_VIA_CMD \
|
||||
(DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20")
|
||||
|
||||
#if(defined __cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** vncrec */
|
||||
|
||||
typedef struct {
|
||||
FILE* file;
|
||||
struct timeval tv;
|
||||
rfbBool readTimestamp;
|
||||
rfbBool doNotSleep;
|
||||
} rfbVNCRec;
|
||||
|
||||
/** client data */
|
||||
|
||||
typedef struct rfbClientData {
|
||||
void* tag;
|
||||
void* data;
|
||||
struct rfbClientData* next;
|
||||
} rfbClientData;
|
||||
|
||||
/** app data (belongs into rfbClient?) */
|
||||
|
||||
typedef struct {
|
||||
rfbBool shareDesktop;
|
||||
rfbBool viewOnly;
|
||||
|
||||
const char* encodingsString;
|
||||
|
||||
rfbBool useBGR233;
|
||||
int nColours;
|
||||
rfbBool forceOwnCmap;
|
||||
rfbBool forceTrueColour;
|
||||
int requestedDepth;
|
||||
|
||||
int compressLevel;
|
||||
int qualityLevel;
|
||||
rfbBool enableJPEG;
|
||||
rfbBool useRemoteCursor;
|
||||
rfbBool palmVNC; /**< use palmvnc specific SetScale (vs ultravnc) */
|
||||
int scaleSetting; /**< 0 means no scale set, else 1/scaleSetting */
|
||||
} AppData;
|
||||
|
||||
/** For GetCredentialProc callback function to return */
|
||||
typedef union _rfbCredential
|
||||
{
|
||||
/** X509 (VeNCrypt) */
|
||||
struct
|
||||
{
|
||||
char *x509CACertFile;
|
||||
char *x509CACrlFile;
|
||||
char *x509ClientCertFile;
|
||||
char *x509ClientKeyFile;
|
||||
} x509Credential;
|
||||
/** Plain (VeNCrypt), MSLogon (UltraVNC) */
|
||||
struct
|
||||
{
|
||||
char *username;
|
||||
char *password;
|
||||
} userCredential;
|
||||
} rfbCredential;
|
||||
|
||||
#define rfbCredentialTypeX509 1
|
||||
#define rfbCredentialTypeUser 2
|
||||
|
||||
struct _rfbClient;
|
||||
|
||||
typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text);
|
||||
typedef void (*HandleXvpMsgProc)(struct _rfbClient* client, uint8_t version, uint8_t opcode);
|
||||
typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad);
|
||||
typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y);
|
||||
typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h);
|
||||
typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client);
|
||||
typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h);
|
||||
typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client);
|
||||
typedef char* (*GetPasswordProc)(struct _rfbClient* client);
|
||||
typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType);
|
||||
typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client);
|
||||
typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen);
|
||||
typedef void (*BellProc)(struct _rfbClient* client);
|
||||
|
||||
typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel);
|
||||
typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y);
|
||||
|
||||
typedef struct _rfbClient {
|
||||
uint8_t* frameBuffer;
|
||||
int width, height;
|
||||
|
||||
int endianTest;
|
||||
|
||||
AppData appData;
|
||||
|
||||
const char* programName;
|
||||
char* serverHost;
|
||||
int serverPort; /**< if -1, then use file recorded by vncrec */
|
||||
rfbBool listenSpecified;
|
||||
int listenPort, flashPort;
|
||||
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
} updateRect;
|
||||
|
||||
/** Note that the CoRRE encoding uses this buffer and assumes it is big enough
|
||||
to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes.
|
||||
Hextile also assumes it is big enough to hold 16 * 16 * 32 bits.
|
||||
Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */
|
||||
|
||||
#define RFB_BUFFER_SIZE (640*480)
|
||||
char buffer[RFB_BUFFER_SIZE];
|
||||
|
||||
/* rfbproto.c */
|
||||
|
||||
int sock;
|
||||
rfbBool canUseCoRRE;
|
||||
rfbBool canUseHextile;
|
||||
char *desktopName;
|
||||
rfbPixelFormat format;
|
||||
rfbServerInitMsg si;
|
||||
|
||||
/* listen.c */
|
||||
int listenSock;
|
||||
|
||||
/* sockets.c */
|
||||
#define RFB_BUF_SIZE 8192
|
||||
char buf[RFB_BUF_SIZE];
|
||||
char *bufoutptr;
|
||||
int buffered;
|
||||
|
||||
/* The zlib encoding requires expansion/decompression/deflation of the
|
||||
compressed data in the "buffer" above into another, result buffer.
|
||||
However, the size of the result buffer can be determined precisely
|
||||
based on the bitsPerPixel, height and width of the rectangle. We
|
||||
allocate this buffer one time to be the full size of the buffer. */
|
||||
|
||||
/* Ultra Encoding uses this buffer too */
|
||||
|
||||
int ultra_buffer_size;
|
||||
char *ultra_buffer;
|
||||
|
||||
int raw_buffer_size;
|
||||
char *raw_buffer;
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
z_stream decompStream;
|
||||
rfbBool decompStreamInited;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBZ
|
||||
/*
|
||||
* Variables for the ``tight'' encoding implementation.
|
||||
*/
|
||||
|
||||
/** Separate buffer for compressed data. */
|
||||
#define ZLIB_BUFFER_SIZE 30000
|
||||
char zlib_buffer[ZLIB_BUFFER_SIZE];
|
||||
|
||||
/* Four independent compression streams for zlib library. */
|
||||
z_stream zlibStream[4];
|
||||
rfbBool zlibStreamActive[4];
|
||||
|
||||
/* Filter stuff. Should be initialized by filter initialization code. */
|
||||
rfbBool cutZeros;
|
||||
int rectWidth, rectColors;
|
||||
char tightPalette[256*4];
|
||||
uint8_t tightPrevRow[2048*3*sizeof(uint16_t)];
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
|
||||
/** JPEG decoder state. */
|
||||
rfbBool jpegError;
|
||||
|
||||
struct jpeg_source_mgr* jpegSrcManager;
|
||||
void* jpegBufferPtr;
|
||||
size_t jpegBufferLen;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* cursor.c */
|
||||
uint8_t *rcSource, *rcMask;
|
||||
|
||||
/** private data pointer */
|
||||
rfbClientData* clientData;
|
||||
|
||||
rfbVNCRec* vncRec;
|
||||
|
||||
/* Keyboard State support (is 'Caps Lock' set on the remote display???) */
|
||||
int KeyboardLedStateEnabled;
|
||||
int CurrentKeyboardLedState;
|
||||
|
||||
int canHandleNewFBSize;
|
||||
|
||||
/* hooks */
|
||||
HandleTextChatProc HandleTextChat;
|
||||
HandleKeyboardLedStateProc HandleKeyboardLedState;
|
||||
HandleCursorPosProc HandleCursorPos;
|
||||
SoftCursorLockAreaProc SoftCursorLockArea;
|
||||
SoftCursorUnlockScreenProc SoftCursorUnlockScreen;
|
||||
GotFrameBufferUpdateProc GotFrameBufferUpdate;
|
||||
FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate;
|
||||
/** the pointer returned by GetPassword will be freed after use! */
|
||||
GetPasswordProc GetPassword;
|
||||
MallocFrameBufferProc MallocFrameBuffer;
|
||||
GotXCutTextProc GotXCutText;
|
||||
BellProc Bell;
|
||||
|
||||
GotCursorShapeProc GotCursorShape;
|
||||
GotCopyRectProc GotCopyRect;
|
||||
|
||||
/** Which messages are supported by the server
|
||||
* This is a *guess* for most servers.
|
||||
* (If we can even detect the type of server)
|
||||
*
|
||||
* If the server supports the "rfbEncodingSupportedMessages"
|
||||
* then this will be updated when the encoding is received to
|
||||
* accurately reflect the servers capabilities.
|
||||
*/
|
||||
rfbSupportedMessages supportedMessages;
|
||||
|
||||
/** negotiated protocol version */
|
||||
int major, minor;
|
||||
|
||||
/** The selected security types */
|
||||
uint32_t authScheme, subAuthScheme;
|
||||
|
||||
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
|
||||
/** The TLS session for Anonymous TLS and VeNCrypt */
|
||||
gnutls_session_t tlsSession;
|
||||
#endif
|
||||
|
||||
/** To support security types that requires user input (except VNC password
|
||||
* authentication), for example VeNCrypt and MSLogon, this callback function
|
||||
* must be set before the authentication. Otherwise, it implicates that the
|
||||
* caller application does not support it and related security types should
|
||||
* be bypassed.
|
||||
*/
|
||||
GetCredentialProc GetCredential;
|
||||
|
||||
/** The 0-terminated security types supported by the client.
|
||||
* Set by function SetClientAuthSchemes() */
|
||||
uint32_t *clientAuthSchemes;
|
||||
|
||||
/** When the server is a repeater, this specifies the final destination */
|
||||
char *destHost;
|
||||
int destPort;
|
||||
|
||||
/** the QoS IP DSCP for this client */
|
||||
int QoS_DSCP;
|
||||
|
||||
/** hook to handle xvp server messages */
|
||||
HandleXvpMsgProc HandleXvpMsg;
|
||||
} rfbClient;
|
||||
|
||||
/* cursor.c */
|
||||
|
||||
extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc);
|
||||
|
||||
/* listen.c */
|
||||
|
||||
extern void listenForIncomingConnections(rfbClient* viewer);
|
||||
extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout);
|
||||
|
||||
/* rfbproto.c */
|
||||
|
||||
extern rfbBool rfbEnableClientLogging;
|
||||
typedef void (*rfbClientLogProc)(const char *format, ...);
|
||||
extern rfbClientLogProc rfbClientLog,rfbClientErr;
|
||||
extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port);
|
||||
extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort);
|
||||
extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size);
|
||||
extern rfbBool InitialiseRFBConnection(rfbClient* client);
|
||||
extern rfbBool SetFormatAndEncodings(rfbClient* client);
|
||||
extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client);
|
||||
extern rfbBool SendFramebufferUpdateRequest(rfbClient* client,
|
||||
int x, int y, int w, int h,
|
||||
rfbBool incremental);
|
||||
extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting);
|
||||
extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask);
|
||||
extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down);
|
||||
extern rfbBool SendClientCutText(rfbClient* client,char *str, int len);
|
||||
extern rfbBool HandleRFBServerMessage(rfbClient* client);
|
||||
|
||||
extern rfbBool TextChatSend(rfbClient* client, char *text);
|
||||
extern rfbBool TextChatOpen(rfbClient* client);
|
||||
extern rfbBool TextChatClose(rfbClient* client);
|
||||
extern rfbBool TextChatFinish(rfbClient* client);
|
||||
extern rfbBool PermitServerInput(rfbClient* client, int enabled);
|
||||
extern rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code);
|
||||
|
||||
extern void PrintPixelFormat(rfbPixelFormat *format);
|
||||
|
||||
extern rfbBool SupportsClient2Server(rfbClient* client, int messageType);
|
||||
extern rfbBool SupportsServer2Client(rfbClient* client, int messageType);
|
||||
|
||||
/* client data */
|
||||
|
||||
void rfbClientSetClientData(rfbClient* client, void* tag, void* data);
|
||||
void* rfbClientGetClientData(rfbClient* client, void* tag);
|
||||
|
||||
/* protocol extensions */
|
||||
|
||||
typedef struct _rfbClientProtocolExtension {
|
||||
int* encodings;
|
||||
/** returns TRUE if the encoding was handled */
|
||||
rfbBool (*handleEncoding)(rfbClient* cl,
|
||||
rfbFramebufferUpdateRectHeader* rect);
|
||||
/** returns TRUE if it handled the message */
|
||||
rfbBool (*handleMessage)(rfbClient* cl,
|
||||
rfbServerToClientMsg* message);
|
||||
struct _rfbClientProtocolExtension* next;
|
||||
} rfbClientProtocolExtension;
|
||||
|
||||
void rfbClientRegisterExtension(rfbClientProtocolExtension* e);
|
||||
|
||||
/* sockets.c */
|
||||
|
||||
extern rfbBool errorMessageOnReadFailure;
|
||||
|
||||
extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n);
|
||||
extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n);
|
||||
extern int FindFreeTcpPort(void);
|
||||
extern int ListenAtTcpPort(int port);
|
||||
extern int ConnectClientToTcpAddr(unsigned int host, int port);
|
||||
extern int ConnectClientToTcpAddr6(const char *hostname, int port);
|
||||
extern int ConnectClientToUnixSock(const char *sockFile);
|
||||
extern int AcceptTcpConnection(int listenSock);
|
||||
extern rfbBool SetNonBlocking(int sock);
|
||||
extern rfbBool SetDSCP(int sock, int dscp);
|
||||
|
||||
extern rfbBool StringToIPAddr(const char *str, unsigned int *addr);
|
||||
extern rfbBool SameMachine(int sock);
|
||||
extern int WaitForMessage(rfbClient* client,unsigned int usecs);
|
||||
|
||||
/* vncviewer.c */
|
||||
rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel);
|
||||
rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv);
|
||||
/** rfbClientCleanup() does not touch client->frameBuffer */
|
||||
void rfbClientCleanup(rfbClient* client);
|
||||
|
||||
#if(defined __cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
@page libvncclient_doc LibVNCClient Documentation
|
||||
@section example_code Example Code
|
||||
See SDLvncviewer.c for a rather complete client example.
|
||||
*/
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,65 +0,0 @@
|
|||
#ifndef SRAREGION_H
|
||||
#define SRAREGION_H
|
||||
|
||||
/* -=- SRA - Simple Region Algorithm
|
||||
* A simple rectangular region implementation.
|
||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
||||
*/
|
||||
|
||||
/* -=- sraRect */
|
||||
|
||||
typedef struct _rect {
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
} sraRect;
|
||||
|
||||
typedef struct sraRegion sraRegion;
|
||||
|
||||
/* -=- Region manipulation functions */
|
||||
|
||||
extern sraRegion *sraRgnCreate();
|
||||
extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2);
|
||||
extern sraRegion *sraRgnCreateRgn(const sraRegion *src);
|
||||
|
||||
extern void sraRgnDestroy(sraRegion *rgn);
|
||||
extern void sraRgnMakeEmpty(sraRegion *rgn);
|
||||
extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src);
|
||||
extern void sraRgnOr(sraRegion *dst, const sraRegion *src);
|
||||
extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src);
|
||||
|
||||
extern void sraRgnOffset(sraRegion *dst, int dx, int dy);
|
||||
|
||||
extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect,
|
||||
unsigned long flags);
|
||||
|
||||
extern unsigned long sraRgnCountRects(const sraRegion *rgn);
|
||||
extern rfbBool sraRgnEmpty(const sraRegion *rgn);
|
||||
|
||||
extern sraRegion *sraRgnBBox(const sraRegion *src);
|
||||
|
||||
/* -=- rectangle iterator */
|
||||
|
||||
typedef struct sraRectangleIterator {
|
||||
rfbBool reverseX,reverseY;
|
||||
int ptrSize,ptrPos;
|
||||
struct sraSpan** sPtrs;
|
||||
} sraRectangleIterator;
|
||||
|
||||
extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s);
|
||||
extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY);
|
||||
extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r);
|
||||
extern void sraRgnReleaseIterator(sraRectangleIterator *i);
|
||||
|
||||
void sraRgnPrint(const sraRegion *s);
|
||||
|
||||
/* -=- Rectangle clipper (for speed) */
|
||||
|
||||
extern rfbBool sraClipRect(int *x, int *y, int *w, int *h,
|
||||
int cx, int cy, int cw, int ch);
|
||||
|
||||
extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2,
|
||||
int cx, int cy, int cx2, int cy2);
|
||||
|
||||
#endif
|
|
@ -1,886 +0,0 @@
|
|||
/* -=- sraRegion.c
|
||||
* Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
|
||||
*
|
||||
* A general purpose region clipping library
|
||||
* Only deals with rectangular regions, though.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
|
||||
/* -=- Internal Span structure */
|
||||
|
||||
struct sraRegion;
|
||||
|
||||
typedef struct sraSpan {
|
||||
struct sraSpan *_next;
|
||||
struct sraSpan *_prev;
|
||||
int start;
|
||||
int end;
|
||||
struct sraRegion *subspan;
|
||||
} sraSpan;
|
||||
|
||||
typedef struct sraRegion {
|
||||
sraSpan front;
|
||||
sraSpan back;
|
||||
} sraSpanList;
|
||||
|
||||
/* -=- Span routines */
|
||||
|
||||
sraSpanList *sraSpanListDup(const sraSpanList *src);
|
||||
void sraSpanListDestroy(sraSpanList *list);
|
||||
|
||||
static sraSpan *
|
||||
sraSpanCreate(int start, int end, const sraSpanList *subspan) {
|
||||
sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
|
||||
item->_next = item->_prev = NULL;
|
||||
item->start = start;
|
||||
item->end = end;
|
||||
item->subspan = sraSpanListDup(subspan);
|
||||
return item;
|
||||
}
|
||||
|
||||
static sraSpan *
|
||||
sraSpanDup(const sraSpan *src) {
|
||||
sraSpan *span;
|
||||
if (!src) return NULL;
|
||||
span = sraSpanCreate(src->start, src->end, src->subspan);
|
||||
return span;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
|
||||
newspan->_next = after->_next;
|
||||
newspan->_prev = after;
|
||||
after->_next->_prev = newspan;
|
||||
after->_next = newspan;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
|
||||
newspan->_next = before;
|
||||
newspan->_prev = before->_prev;
|
||||
before->_prev->_next = newspan;
|
||||
before->_prev = newspan;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanRemove(sraSpan *span) {
|
||||
span->_prev->_next = span->_next;
|
||||
span->_next->_prev = span->_prev;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanDestroy(sraSpan *span) {
|
||||
if (span->subspan) sraSpanListDestroy(span->subspan);
|
||||
free(span);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
sraSpanCheck(const sraSpan *span, const char *text) {
|
||||
/* Check the span is valid! */
|
||||
if (span->start == span->end) {
|
||||
printf(text);
|
||||
printf(":%d-%d\n", span->start, span->end);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -=- SpanList routines */
|
||||
|
||||
static void sraSpanPrint(const sraSpan *s);
|
||||
|
||||
static void
|
||||
sraSpanListPrint(const sraSpanList *l) {
|
||||
sraSpan *curr;
|
||||
if (!l) {
|
||||
printf("NULL");
|
||||
return;
|
||||
}
|
||||
curr = l->front._next;
|
||||
printf("[");
|
||||
while (curr != &(l->back)) {
|
||||
sraSpanPrint(curr);
|
||||
curr = curr->_next;
|
||||
}
|
||||
printf("]");
|
||||
}
|
||||
|
||||
void
|
||||
sraSpanPrint(const sraSpan *s) {
|
||||
printf("(%d-%d)", (s->start), (s->end));
|
||||
if (s->subspan)
|
||||
sraSpanListPrint(s->subspan);
|
||||
}
|
||||
|
||||
static sraSpanList *
|
||||
sraSpanListCreate(void) {
|
||||
sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
|
||||
item->front._next = &(item->back);
|
||||
item->front._prev = NULL;
|
||||
item->back._prev = &(item->front);
|
||||
item->back._next = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
sraSpanList *
|
||||
sraSpanListDup(const sraSpanList *src) {
|
||||
sraSpanList *newlist;
|
||||
sraSpan *newspan, *curr;
|
||||
|
||||
if (!src) return NULL;
|
||||
newlist = sraSpanListCreate();
|
||||
curr = src->front._next;
|
||||
while (curr != &(src->back)) {
|
||||
newspan = sraSpanDup(curr);
|
||||
sraSpanInsertBefore(newspan, &(newlist->back));
|
||||
curr = curr->_next;
|
||||
}
|
||||
|
||||
return newlist;
|
||||
}
|
||||
|
||||
void
|
||||
sraSpanListDestroy(sraSpanList *list) {
|
||||
sraSpan *curr, *next;
|
||||
while (list->front._next != &(list->back)) {
|
||||
curr = list->front._next;
|
||||
next = curr->_next;
|
||||
sraSpanRemove(curr);
|
||||
sraSpanDestroy(curr);
|
||||
curr = next;
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanListMakeEmpty(sraSpanList *list) {
|
||||
sraSpan *curr, *next;
|
||||
while (list->front._next != &(list->back)) {
|
||||
curr = list->front._next;
|
||||
next = curr->_next;
|
||||
sraSpanRemove(curr);
|
||||
sraSpanDestroy(curr);
|
||||
curr = next;
|
||||
}
|
||||
list->front._next = &(list->back);
|
||||
list->front._prev = NULL;
|
||||
list->back._prev = &(list->front);
|
||||
list->back._next = NULL;
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
|
||||
sraSpan *sp1, *sp2;
|
||||
|
||||
if (!s1) {
|
||||
if (!s2) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
sp1 = s1->front._next;
|
||||
sp2 = s2->front._next;
|
||||
while ((sp1 != &(s1->back)) &&
|
||||
(sp2 != &(s2->back))) {
|
||||
if ((sp1->start != sp2->start) ||
|
||||
(sp1->end != sp2->end) ||
|
||||
(!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
|
||||
return 0;
|
||||
}
|
||||
sp1 = sp1->_next;
|
||||
sp2 = sp2->_next;
|
||||
}
|
||||
|
||||
if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListEmpty(const sraSpanList *list) {
|
||||
return (list->front._next == &(list->back));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sraSpanListCount(const sraSpanList *list) {
|
||||
sraSpan *curr = list->front._next;
|
||||
unsigned long count = 0;
|
||||
while (curr != &(list->back)) {
|
||||
if (curr->subspan) {
|
||||
count += sraSpanListCount(curr->subspan);
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
curr = curr->_next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanMergePrevious(sraSpan *dest) {
|
||||
sraSpan *prev = dest->_prev;
|
||||
|
||||
while ((prev->_prev) &&
|
||||
(prev->end == dest->start) &&
|
||||
(sraSpanListEqual(prev->subspan, dest->subspan))) {
|
||||
/*
|
||||
printf("merge_prev:");
|
||||
sraSpanPrint(prev);
|
||||
printf(" & ");
|
||||
sraSpanPrint(dest);
|
||||
printf("\n");
|
||||
*/
|
||||
dest->start = prev->start;
|
||||
sraSpanRemove(prev);
|
||||
sraSpanDestroy(prev);
|
||||
prev = dest->_prev;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanMergeNext(sraSpan *dest) {
|
||||
sraSpan *next = dest->_next;
|
||||
while ((next->_next) &&
|
||||
(next->start == dest->end) &&
|
||||
(sraSpanListEqual(next->subspan, dest->subspan))) {
|
||||
/*
|
||||
printf("merge_next:");
|
||||
sraSpanPrint(dest);
|
||||
printf(" & ");
|
||||
sraSpanPrint(next);
|
||||
printf("\n");
|
||||
*/
|
||||
dest->end = next->end;
|
||||
sraSpanRemove(next);
|
||||
sraSpanDestroy(next);
|
||||
next = dest->_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr;
|
||||
int s_start, s_end;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return;
|
||||
} else {
|
||||
rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
while (s_curr != &(src->back)) {
|
||||
|
||||
/* - If we are at end of destination list OR
|
||||
If the new span comes before the next destination one */
|
||||
if ((d_curr == &(dest->back)) ||
|
||||
(d_curr->start >= s_end)) {
|
||||
/* - Add the span */
|
||||
sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
|
||||
s_curr->subspan),
|
||||
d_curr);
|
||||
if (d_curr != &(dest->back))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
s_curr = s_curr->_next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
} else {
|
||||
|
||||
/* - If the new span overlaps the existing one */
|
||||
if ((s_start < d_curr->end) &&
|
||||
(s_end > d_curr->start)) {
|
||||
|
||||
/* - Insert new span before the existing destination one? */
|
||||
if (s_start < d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(s_start,
|
||||
d_curr->start,
|
||||
s_curr->subspan),
|
||||
d_curr);
|
||||
sraSpanMergePrevious(d_curr);
|
||||
}
|
||||
|
||||
/* Split the existing span if necessary */
|
||||
if (s_end < d_curr->end) {
|
||||
sraSpanInsertAfter(sraSpanCreate(s_end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_end;
|
||||
}
|
||||
if (s_start > d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
||||
s_start,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->start = s_start;
|
||||
}
|
||||
|
||||
/* Recursively OR subspans */
|
||||
sraSpanListOr(d_curr->subspan, s_curr->subspan);
|
||||
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
if (d_curr->_next != &(dest->back))
|
||||
sraSpanMergeNext(d_curr);
|
||||
|
||||
/* Move onto the next pair to compare */
|
||||
if (s_end > d_curr->end) {
|
||||
s_start = d_curr->end;
|
||||
d_curr = d_curr->_next;
|
||||
} else {
|
||||
s_curr = s_curr->_next;
|
||||
s_start = s_curr->start;
|
||||
s_end = s_curr->end;
|
||||
}
|
||||
} else {
|
||||
/* - No overlap. Move to the next destination span */
|
||||
d_curr = d_curr->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr, *d_next;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
||||
|
||||
/* - If we haven't reached a destination span yet then move on */
|
||||
if (d_curr->start >= s_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we are beyond the current destination span then remove it */
|
||||
if (d_curr->end <= s_curr->start) {
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we partially overlap a span then split it up or remove bits */
|
||||
if (s_curr->start > d_curr->start) {
|
||||
/* - The top bit of the span does not match */
|
||||
d_curr->start = s_curr->start;
|
||||
}
|
||||
if (s_curr->end < d_curr->end) {
|
||||
/* - The end of the span does not match */
|
||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_curr->end;
|
||||
}
|
||||
|
||||
/* - Now recursively process the affected span */
|
||||
if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
|
||||
/* - The destination subspan is now empty, so we should remove it */
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
} else {
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
|
||||
/* - Move on to the next span */
|
||||
d_next = d_curr;
|
||||
if (s_curr->end >= d_curr->end) {
|
||||
d_next = d_curr->_next;
|
||||
}
|
||||
if (s_curr->end <= d_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
}
|
||||
d_curr = d_next;
|
||||
}
|
||||
}
|
||||
|
||||
while (d_curr != &(dest->back)) {
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr=next;
|
||||
}
|
||||
|
||||
return !sraSpanListEmpty(dest);
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
|
||||
sraSpan *d_curr, *s_curr;
|
||||
|
||||
if (!dest) {
|
||||
if (!src) {
|
||||
return 1;
|
||||
} else {
|
||||
rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
d_curr = dest->front._next;
|
||||
s_curr = src->front._next;
|
||||
while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
|
||||
|
||||
/* - If we haven't reached a destination span yet then move on */
|
||||
if (d_curr->start >= s_curr->end) {
|
||||
s_curr = s_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we are beyond the current destination span then skip it */
|
||||
if (d_curr->end <= s_curr->start) {
|
||||
d_curr = d_curr->_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* - If we partially overlap the current span then split it up */
|
||||
if (s_curr->start > d_curr->start) {
|
||||
sraSpanInsertBefore(sraSpanCreate(d_curr->start,
|
||||
s_curr->start,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->start = s_curr->start;
|
||||
}
|
||||
if (s_curr->end < d_curr->end) {
|
||||
sraSpanInsertAfter(sraSpanCreate(s_curr->end,
|
||||
d_curr->end,
|
||||
d_curr->subspan),
|
||||
d_curr);
|
||||
d_curr->end = s_curr->end;
|
||||
}
|
||||
|
||||
/* - Now recursively process the affected span */
|
||||
if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
|
||||
/* - The destination subspan is now empty, so we should remove it */
|
||||
sraSpan *next = d_curr->_next;
|
||||
sraSpanRemove(d_curr);
|
||||
sraSpanDestroy(d_curr);
|
||||
d_curr = next;
|
||||
} else {
|
||||
/* Merge this span with previous or next? */
|
||||
if (d_curr->_prev != &(dest->front))
|
||||
sraSpanMergePrevious(d_curr);
|
||||
if (d_curr->_next != &(dest->back))
|
||||
sraSpanMergeNext(d_curr);
|
||||
|
||||
/* - Move on to the next span */
|
||||
if (s_curr->end > d_curr->end) {
|
||||
d_curr = d_curr->_next;
|
||||
} else {
|
||||
s_curr = s_curr->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !sraSpanListEmpty(dest);
|
||||
}
|
||||
|
||||
/* -=- Region routines */
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreate(void) {
|
||||
return (sraRegion*)sraSpanListCreate();
|
||||
}
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreateRect(int x1, int y1, int x2, int y2) {
|
||||
sraSpanList *vlist, *hlist;
|
||||
sraSpan *vspan, *hspan;
|
||||
|
||||
/* - Build the horizontal portion of the span */
|
||||
hlist = sraSpanListCreate();
|
||||
hspan = sraSpanCreate(x1, x2, NULL);
|
||||
sraSpanInsertAfter(hspan, &(hlist->front));
|
||||
|
||||
/* - Build the vertical portion of the span */
|
||||
vlist = sraSpanListCreate();
|
||||
vspan = sraSpanCreate(y1, y2, hlist);
|
||||
sraSpanInsertAfter(vspan, &(vlist->front));
|
||||
|
||||
sraSpanListDestroy(hlist);
|
||||
|
||||
return (sraRegion*)vlist;
|
||||
}
|
||||
|
||||
sraRegion *
|
||||
sraRgnCreateRgn(const sraRegion *src) {
|
||||
return (sraRegion*)sraSpanListDup((sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnDestroy(sraRegion *rgn) {
|
||||
sraSpanListDestroy((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnMakeEmpty(sraRegion *rgn) {
|
||||
sraSpanListMakeEmpty((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
/* -=- Boolean Region ops */
|
||||
|
||||
rfbBool
|
||||
sraRgnAnd(sraRegion *dst, const sraRegion *src) {
|
||||
return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnOr(sraRegion *dst, const sraRegion *src) {
|
||||
sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
|
||||
return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnOffset(sraRegion *dst, int dx, int dy) {
|
||||
sraSpan *vcurr, *hcurr;
|
||||
|
||||
vcurr = ((sraSpanList*)dst)->front._next;
|
||||
while (vcurr != &(((sraSpanList*)dst)->back)) {
|
||||
vcurr->start += dy;
|
||||
vcurr->end += dy;
|
||||
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
while (hcurr != &(vcurr->subspan->back)) {
|
||||
hcurr->start += dx;
|
||||
hcurr->end += dx;
|
||||
hcurr = hcurr->_next;
|
||||
}
|
||||
|
||||
vcurr = vcurr->_next;
|
||||
}
|
||||
}
|
||||
|
||||
sraRegion *sraRgnBBox(const sraRegion *src) {
|
||||
int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
|
||||
sraSpan *vcurr, *hcurr;
|
||||
|
||||
if(!src)
|
||||
return sraRgnCreate();
|
||||
|
||||
vcurr = ((sraSpanList*)src)->front._next;
|
||||
while (vcurr != &(((sraSpanList*)src)->back)) {
|
||||
if(vcurr->start<ymin)
|
||||
ymin=vcurr->start;
|
||||
if(vcurr->end>ymax)
|
||||
ymax=vcurr->end;
|
||||
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
while (hcurr != &(vcurr->subspan->back)) {
|
||||
if(hcurr->start<xmin)
|
||||
xmin=hcurr->start;
|
||||
if(hcurr->end>xmax)
|
||||
xmax=hcurr->end;
|
||||
hcurr = hcurr->_next;
|
||||
}
|
||||
|
||||
vcurr = vcurr->_next;
|
||||
}
|
||||
|
||||
if(xmax<xmin || ymax<ymin)
|
||||
return sraRgnCreate();
|
||||
|
||||
return sraRgnCreateRect(xmin,ymin,xmax,ymax);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
|
||||
sraSpan *vcurr, *hcurr;
|
||||
sraSpan *vend, *hend;
|
||||
rfbBool right2left = (flags & 2) == 2;
|
||||
rfbBool bottom2top = (flags & 1) == 1;
|
||||
|
||||
/* - Pick correct order */
|
||||
if (bottom2top) {
|
||||
vcurr = ((sraSpanList*)rgn)->back._prev;
|
||||
vend = &(((sraSpanList*)rgn)->front);
|
||||
} else {
|
||||
vcurr = ((sraSpanList*)rgn)->front._next;
|
||||
vend = &(((sraSpanList*)rgn)->back);
|
||||
}
|
||||
|
||||
if (vcurr != vend) {
|
||||
rect->y1 = vcurr->start;
|
||||
rect->y2 = vcurr->end;
|
||||
|
||||
/* - Pick correct order */
|
||||
if (right2left) {
|
||||
hcurr = vcurr->subspan->back._prev;
|
||||
hend = &(vcurr->subspan->front);
|
||||
} else {
|
||||
hcurr = vcurr->subspan->front._next;
|
||||
hend = &(vcurr->subspan->back);
|
||||
}
|
||||
|
||||
if (hcurr != hend) {
|
||||
rect->x1 = hcurr->start;
|
||||
rect->x2 = hcurr->end;
|
||||
|
||||
sraSpanRemove(hcurr);
|
||||
sraSpanDestroy(hcurr);
|
||||
|
||||
if (sraSpanListEmpty(vcurr->subspan)) {
|
||||
sraSpanRemove(vcurr);
|
||||
sraSpanDestroy(vcurr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("poprect:(%dx%d)-(%dx%d)\n",
|
||||
rect->x1, rect->y1, rect->x2, rect->y2);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
sraRgnCountRects(const sraRegion *rgn) {
|
||||
unsigned long count = sraSpanListCount((sraSpanList*)rgn);
|
||||
return count;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraRgnEmpty(const sraRegion *rgn) {
|
||||
return sraSpanListEmpty((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
/* iterator stuff */
|
||||
sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
|
||||
{
|
||||
/* these values have to be multiples of 4 */
|
||||
#define DEFSIZE 4
|
||||
#define DEFSTEP 8
|
||||
sraRectangleIterator *i =
|
||||
(sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
|
||||
if(!i)
|
||||
return NULL;
|
||||
|
||||
/* we have to recurse eventually. So, the first sPtr is the pointer to
|
||||
the sraSpan in the first level. the second sPtr is the pointer to
|
||||
the sraRegion.back. The third and fourth sPtr are for the second
|
||||
recursion level and so on. */
|
||||
i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
|
||||
if(!i->sPtrs) {
|
||||
free(i);
|
||||
return NULL;
|
||||
}
|
||||
i->ptrSize = DEFSIZE;
|
||||
i->sPtrs[0] = &(s->front);
|
||||
i->sPtrs[1] = &(s->back);
|
||||
i->ptrPos = 0;
|
||||
i->reverseX = 0;
|
||||
i->reverseY = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY)
|
||||
{
|
||||
sraRectangleIterator *i = sraRgnGetIterator(s);
|
||||
if(reverseY) {
|
||||
i->sPtrs[1] = &(s->front);
|
||||
i->sPtrs[0] = &(s->back);
|
||||
}
|
||||
i->reverseX = reverseX;
|
||||
i->reverseY = reverseY;
|
||||
return(i);
|
||||
}
|
||||
|
||||
static rfbBool sraReverse(sraRectangleIterator *i)
|
||||
{
|
||||
return( ((i->ptrPos&2) && i->reverseX) ||
|
||||
(!(i->ptrPos&2) && i->reverseY));
|
||||
}
|
||||
|
||||
static sraSpan* sraNextSpan(sraRectangleIterator *i)
|
||||
{
|
||||
if(sraReverse(i))
|
||||
return(i->sPtrs[i->ptrPos]->_prev);
|
||||
else
|
||||
return(i->sPtrs[i->ptrPos]->_next);
|
||||
}
|
||||
|
||||
rfbBool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
|
||||
{
|
||||
/* is the subspan finished? */
|
||||
while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
|
||||
i->ptrPos -= 2;
|
||||
if(i->ptrPos < 0) /* the end */
|
||||
return(0);
|
||||
}
|
||||
|
||||
i->sPtrs[i->ptrPos] = sraNextSpan(i);
|
||||
|
||||
/* is this a new subspan? */
|
||||
while(i->sPtrs[i->ptrPos]->subspan) {
|
||||
if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
|
||||
i->ptrSize += DEFSTEP;
|
||||
i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
|
||||
}
|
||||
i->ptrPos =+ 2;
|
||||
if(sraReverse(i)) {
|
||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
|
||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
|
||||
} else {
|
||||
i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
|
||||
i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
|
||||
}
|
||||
}
|
||||
|
||||
if((i->ptrPos%4)!=2) {
|
||||
rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r->y1 = i->sPtrs[i->ptrPos-2]->start;
|
||||
r->y2 = i->sPtrs[i->ptrPos-2]->end;
|
||||
r->x1 = i->sPtrs[i->ptrPos]->start;
|
||||
r->x2 = i->sPtrs[i->ptrPos]->end;
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void sraRgnReleaseIterator(sraRectangleIterator* i)
|
||||
{
|
||||
free(i->sPtrs);
|
||||
free(i);
|
||||
}
|
||||
|
||||
void
|
||||
sraRgnPrint(const sraRegion *rgn) {
|
||||
sraSpanListPrint((sraSpanList*)rgn);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraClipRect(int *x, int *y, int *w, int *h,
|
||||
int cx, int cy, int cw, int ch) {
|
||||
if (*x < cx) {
|
||||
*w -= (cx-*x);
|
||||
*x = cx;
|
||||
}
|
||||
if (*y < cy) {
|
||||
*h -= (cy-*y);
|
||||
*y = cy;
|
||||
}
|
||||
if (*x+*w > cx+cw) {
|
||||
*w = (cx+cw)-*x;
|
||||
}
|
||||
if (*y+*h > cy+ch) {
|
||||
*h = (cy+ch)-*y;
|
||||
}
|
||||
return (*w>0) && (*h>0);
|
||||
}
|
||||
|
||||
rfbBool
|
||||
sraClipRect2(int *x, int *y, int *x2, int *y2,
|
||||
int cx, int cy, int cx2, int cy2) {
|
||||
if (*x < cx)
|
||||
*x = cx;
|
||||
if (*y < cy)
|
||||
*y = cy;
|
||||
if (*x >= cx2)
|
||||
*x = cx2-1;
|
||||
if (*y >= cy2)
|
||||
*y = cy2-1;
|
||||
if (*x2 <= cx)
|
||||
*x2 = cx+1;
|
||||
if (*y2 <= cy)
|
||||
*y2 = cy+1;
|
||||
if (*x2 > cx2)
|
||||
*x2 = cx2;
|
||||
if (*y2 > cy2)
|
||||
*y2 = cy2;
|
||||
return (*x2>*x) && (*y2>*y);
|
||||
}
|
||||
|
||||
/* test */
|
||||
|
||||
#ifdef SRA_TEST
|
||||
/* pipe the output to sort|uniq -u and you'll get the errors. */
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
sraRegionPtr region, region1, region2;
|
||||
sraRectangleIterator* i;
|
||||
sraRect rect;
|
||||
rfbBool b;
|
||||
|
||||
region = sraRgnCreateRect(10, 10, 600, 300);
|
||||
region1 = sraRgnCreateRect(40, 50, 350, 200);
|
||||
region2 = sraRgnCreateRect(0, 0, 20, 40);
|
||||
|
||||
sraRgnPrint(region);
|
||||
printf("\n[(10-300)[(10-600)]]\n\n");
|
||||
|
||||
b = sraRgnSubtract(region, region1);
|
||||
printf("%s ",b?"true":"false");
|
||||
sraRgnPrint(region);
|
||||
printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
|
||||
|
||||
sraRgnOr(region, region2);
|
||||
printf("%ld\n6\n\n", sraRgnCountRects(region));
|
||||
|
||||
i = sraRgnGetIterator(region);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
|
||||
|
||||
i = sraRgnGetReverseIterator(region,1,0);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
|
||||
|
||||
i = sraRgnGetReverseIterator(region,1,1);
|
||||
while(sraRgnIteratorNext(i, &rect))
|
||||
printf("%dx%d+%d+%d ",
|
||||
rect.x2-rect.x1,rect.y2-rect.y1,
|
||||
rect.x1,rect.y1);
|
||||
sraRgnReleaseIterator(i);
|
||||
printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
|
||||
|
||||
sraRgnDestroy(region);
|
||||
sraRgnDestroy(region1);
|
||||
sraRgnDestroy(region2);
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
* rre.c
|
||||
*
|
||||
* Routines to implement Rise-and-Run-length Encoding (RRE). This
|
||||
* code is based on krw's original javatel rfbserver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the RRE encoded version. If the RRE encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
|
||||
static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
|
||||
static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
|
||||
static uint32_t getBgColour(char *data, int size, int bpp);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbRREHeader hdr;
|
||||
int nSubrects;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
if (cl->afterEncBufSize < maxRawSize) {
|
||||
cl->afterEncBufSize = maxRawSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
(*cl->translateFn)(cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat),
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 16:
|
||||
nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 32:
|
||||
nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
default:
|
||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nSubrects < 0) {
|
||||
|
||||
/* RRE encoding was too large, use raw */
|
||||
|
||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingRRE,
|
||||
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingRRE);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
||||
cl->ublen += sz_rfbRREHeader;
|
||||
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
||||
* colour overwritten by single-coloured rectangles. It returns the number
|
||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
||||
* fit in the buffer. It puts the encoded rectangles in cl->afterEncBuf. The
|
||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
||||
* coordinate position.
|
||||
*
|
||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
||||
* <subrect> is [<colour><x><y><w><h>].
|
||||
*/
|
||||
|
||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
||||
static int \
|
||||
subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
|
||||
uint##bpp##_t cl; \
|
||||
rfbRectangle subrect; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
|
||||
\
|
||||
*((uint##bpp##_t*)client->afterEncBuf) = bg; \
|
||||
\
|
||||
client->afterEncBufLen = (bpp/8); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
||||
* We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
subrect.x = Swap16IfLE(thex); \
|
||||
subrect.y = Swap16IfLE(they); \
|
||||
subrect.w = Swap16IfLE(thew); \
|
||||
subrect.h = Swap16IfLE(theh); \
|
||||
\
|
||||
newLen = client->afterEncBufLen + (bpp/8) + sz_rfbRectangle; \
|
||||
if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
|
||||
return -1; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
*((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
|
||||
client->afterEncBufLen += (bpp/8); \
|
||||
memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbRectangle); \
|
||||
client->afterEncBufLen += sz_rfbRectangle; \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return numsubs; \
|
||||
}
|
||||
|
||||
DEFINE_SUBRECT_ENCODE(8)
|
||||
DEFINE_SUBRECT_ENCODE(16)
|
||||
DEFINE_SUBRECT_ENCODE(32)
|
||||
|
||||
|
||||
/*
|
||||
* getBgColour() gets the most prevalent colour in a byte array.
|
||||
*/
|
||||
static uint32_t
|
||||
getBgColour(char *data, int size, int bpp)
|
||||
{
|
||||
|
||||
#define NUMCLRS 256
|
||||
|
||||
static int counts[NUMCLRS];
|
||||
int i,j,k;
|
||||
|
||||
int maxcount = 0;
|
||||
uint8_t maxclr = 0;
|
||||
|
||||
if (bpp != 8) {
|
||||
if (bpp == 16) {
|
||||
return ((uint16_t *)data)[0];
|
||||
} else if (bpp == 32) {
|
||||
return ((uint32_t *)data)[0];
|
||||
} else {
|
||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUMCLRS; i++) {
|
||||
counts[i] = 0;
|
||||
}
|
||||
|
||||
for (j=0; j<size; j++) {
|
||||
k = (int)(((uint8_t *)data)[j]);
|
||||
if (k >= NUMCLRS) {
|
||||
rfbErr("getBgColour: unusual colour = %d\n", k);
|
||||
return 0;
|
||||
}
|
||||
counts[k] += 1;
|
||||
if (counts[k] > maxcount) {
|
||||
maxcount = counts[k];
|
||||
maxclr = ((uint8_t *)data)[j];
|
||||
}
|
||||
}
|
||||
|
||||
return maxclr;
|
||||
}
|
|
@ -1,416 +0,0 @@
|
|||
/*
|
||||
* scale.c - deal with server-side scaling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
#include "private.h"
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define write(sock,buf,len) send(sock,buf,len,0)
|
||||
#else
|
||||
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGPROTO
|
||||
#undef DEBUGPROTO
|
||||
#define DEBUGPROTO(x) x
|
||||
#else
|
||||
#define DEBUGPROTO(x)
|
||||
#endif
|
||||
|
||||
/****************************/
|
||||
#define CEIL(x) ( (double) ((int) (x)) == (x) ? \
|
||||
(double) ((int) (x)) : (double) ((int) (x) + 1) )
|
||||
#define FLOOR(x) ( (double) ((int) (x)) )
|
||||
|
||||
|
||||
int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x)
|
||||
{
|
||||
if ((from==to) || (from==NULL) || (to==NULL)) return x;
|
||||
return ((int)(((double) x / (double)from->width) * (double)to->width ));
|
||||
}
|
||||
|
||||
int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y)
|
||||
{
|
||||
if ((from==to) || (from==NULL) || (to==NULL)) return y;
|
||||
return ((int)(((double) y / (double)from->height) * (double)to->height ));
|
||||
}
|
||||
|
||||
/* So, all of the encodings point to the ->screen->frameBuffer,
|
||||
* We need to change this!
|
||||
*/
|
||||
void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, const char *function)
|
||||
{
|
||||
double x1,y1,w1,h1, x2, y2, w2, h2;
|
||||
double scaleW = ((double) to->width) / ((double) from->width);
|
||||
double scaleH = ((double) to->height) / ((double) from->height);
|
||||
|
||||
|
||||
/*
|
||||
* rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n",
|
||||
* from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h);
|
||||
*/
|
||||
|
||||
/* If it's the original framebuffer... */
|
||||
if (from==to) return;
|
||||
|
||||
x1 = ((double) *x) * scaleW;
|
||||
y1 = ((double) *y) * scaleH;
|
||||
w1 = ((double) *w) * scaleW;
|
||||
h1 = ((double) *h) * scaleH;
|
||||
|
||||
|
||||
/*cast from double to int is same as "*x = floor(x1);" */
|
||||
x2 = FLOOR(x1);
|
||||
y2 = FLOOR(y1);
|
||||
|
||||
/* include into W and H the jitter of scaling X and Y */
|
||||
w2 = CEIL(w1 + ( x1 - x2 ));
|
||||
h2 = CEIL(h1 + ( y1 - y2 ));
|
||||
|
||||
/*
|
||||
* rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n",
|
||||
* function, *x, *y, *w, *h, x2, y2, w2, h2,
|
||||
* from->width, from->height, to->width, to->height);
|
||||
*/
|
||||
|
||||
/* simulate ceil() without math library */
|
||||
*x = (int)x2;
|
||||
*y = (int)y2;
|
||||
*w = (int)w2;
|
||||
*h = (int)h2;
|
||||
|
||||
/* Small changes for a thumbnail may be scaled to zero */
|
||||
if (*w==0) (*w)++;
|
||||
if (*h==0) (*h)++;
|
||||
/* scaling from small to big may overstep the size a bit */
|
||||
if (*x+*w > to->width) *w=to->width - *x;
|
||||
if (*y+*h > to->height) *h=to->height - *y;
|
||||
}
|
||||
|
||||
void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0)
|
||||
{
|
||||
int x,y,w,v,z;
|
||||
int x1, y1, w1, h1;
|
||||
int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2;
|
||||
unsigned char *srcptr, *dstptr;
|
||||
|
||||
/* Nothing to do!!! */
|
||||
if (screen==ptr) return;
|
||||
|
||||
x1 = x0;
|
||||
y1 = y0;
|
||||
w1 = w0;
|
||||
h1 = h0;
|
||||
|
||||
rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect");
|
||||
x0 = ScaleX(ptr, screen, x1);
|
||||
y0 = ScaleY(ptr, screen, y1);
|
||||
w0 = ScaleX(ptr, screen, w1);
|
||||
h0 = ScaleY(ptr, screen, h1);
|
||||
|
||||
bitsPerPixel = screen->bitsPerPixel;
|
||||
bytesPerPixel = bitsPerPixel / 8;
|
||||
bytesPerLine = w1 * bytesPerPixel;
|
||||
srcptr = (unsigned char *)(screen->frameBuffer +
|
||||
(y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel));
|
||||
dstptr = (unsigned char *)(ptr->frameBuffer +
|
||||
( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel));
|
||||
/* The area of the source framebuffer for each destination pixel */
|
||||
areaX = ScaleX(ptr,screen,1);
|
||||
areaY = ScaleY(ptr,screen,1);
|
||||
area2 = areaX*areaY;
|
||||
|
||||
|
||||
/* Ensure that we do not go out of bounds */
|
||||
if ((x1+w1) > (ptr->width))
|
||||
{
|
||||
if (x1==0) w1=ptr->width; else x1 = ptr->width - w1;
|
||||
}
|
||||
if ((y1+h1) > (ptr->height))
|
||||
{
|
||||
if (y1==0) h1=ptr->height; else y1 = ptr->height - h1;
|
||||
}
|
||||
/*
|
||||
* rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n",
|
||||
* x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY,
|
||||
* screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer);
|
||||
*/
|
||||
|
||||
if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */
|
||||
unsigned char *srcptr2;
|
||||
unsigned long pixel_value, red, green, blue;
|
||||
unsigned int redShift = screen->serverFormat.redShift;
|
||||
unsigned int greenShift = screen->serverFormat.greenShift;
|
||||
unsigned int blueShift = screen->serverFormat.blueShift;
|
||||
unsigned long redMax = screen->serverFormat.redMax;
|
||||
unsigned long greenMax = screen->serverFormat.greenMax;
|
||||
unsigned long blueMax = screen->serverFormat.blueMax;
|
||||
|
||||
/* for each *destination* pixel... */
|
||||
for (y = 0; y < h1; y++) {
|
||||
for (x = 0; x < w1; x++) {
|
||||
red = green = blue = 0;
|
||||
/* Get the totals for rgb from the source grid... */
|
||||
for (w = 0; w < areaX; w++) {
|
||||
for (v = 0; v < areaY; v++) {
|
||||
srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) +
|
||||
(v * screen->paddedWidthInBytes)];
|
||||
pixel_value = 0;
|
||||
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 4: pixel_value = *((unsigned int *)srcptr2); break;
|
||||
case 2: pixel_value = *((unsigned short *)srcptr2); break;
|
||||
case 1: pixel_value = *((unsigned char *)srcptr2); break;
|
||||
default:
|
||||
/* fixme: endianess problem? */
|
||||
for (z = 0; z < bytesPerPixel; z++)
|
||||
pixel_value += (srcptr2[z] << (8 * z));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
srcptr2 += bytesPerPixel;
|
||||
*/
|
||||
|
||||
red += ((pixel_value >> redShift) & redMax);
|
||||
green += ((pixel_value >> greenShift) & greenMax);
|
||||
blue += ((pixel_value >> blueShift) & blueMax);
|
||||
|
||||
}
|
||||
}
|
||||
/* We now have a total for all of the colors, find the average! */
|
||||
red /= area2;
|
||||
green /= area2;
|
||||
blue /= area2;
|
||||
/* Stuff the new value back into memory */
|
||||
pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift);
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break;
|
||||
case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break;
|
||||
case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break;
|
||||
default:
|
||||
/* fixme: endianess problem? */
|
||||
for (z = 0; z < bytesPerPixel; z++)
|
||||
dstptr[z]=(pixel_value >> (8 * z)) & 0xff;
|
||||
break;
|
||||
}
|
||||
dstptr += bytesPerPixel;
|
||||
}
|
||||
srcptr += (screen->paddedWidthInBytes * areaY);
|
||||
dstptr += (ptr->paddedWidthInBytes - bytesPerLine);
|
||||
}
|
||||
} else
|
||||
{ /* Not truecolour, so we can't blend. Just use the top-left pixel instead */
|
||||
for (y = y1; y < (y1+h1); y++) {
|
||||
for (x = x1; x < (x1+w1); x++)
|
||||
memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)],
|
||||
&screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
/* ok, now the task is to update each and every scaled version of the framebuffer
|
||||
* and we only have to do this for this specific changed rectangle!
|
||||
*/
|
||||
rfbScreenInfoPtr ptr;
|
||||
int count=0;
|
||||
|
||||
/* We don't point to cl->screen as it is the original */
|
||||
for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext)
|
||||
{
|
||||
/* Only update if it has active clients... */
|
||||
if (ptr->scaledScreenRefCount>0)
|
||||
{
|
||||
rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new scaled version of the framebuffer */
|
||||
rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
ptr = malloc(sizeof(rfbScreenInfo));
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
/* copy *everything* (we don't use most of it, but just in case) */
|
||||
memcpy(ptr, cl->screen, sizeof(rfbScreenInfo));
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width;
|
||||
|
||||
/* Need to by multiples of 4 for Sparc systems */
|
||||
ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4);
|
||||
|
||||
/* Reset the reference count to 0! */
|
||||
ptr->scaledScreenRefCount = 0;
|
||||
|
||||
ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height;
|
||||
ptr->serverFormat = cl->screen->serverFormat;
|
||||
|
||||
ptr->frameBuffer = malloc(ptr->sizeInBytes);
|
||||
if (ptr->frameBuffer!=NULL)
|
||||
{
|
||||
/* Reset to a known condition: scale the entire framebuffer */
|
||||
rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height);
|
||||
/* Now, insert into the chain */
|
||||
LOCK(cl->updateMutex);
|
||||
ptr->scaledScreenNext = cl->screen->scaledScreenNext;
|
||||
cl->screen->scaledScreenNext = ptr;
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to malloc the new frameBuffer, cleanup */
|
||||
free(ptr);
|
||||
ptr=NULL;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Find an active scaled version of the framebuffer
|
||||
* TODO: implement a refcount per scaled screen to prevent
|
||||
* unreferenced scaled screens from hanging around
|
||||
*/
|
||||
rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
/* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */
|
||||
for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext)
|
||||
{
|
||||
if ((ptr->width==width) && (ptr->height==height))
|
||||
return ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Future needs "scale to 320x240, as that's the client's screen size */
|
||||
void rfbScalingSetup(rfbClientPtr cl, int width, int height)
|
||||
{
|
||||
rfbScreenInfoPtr ptr;
|
||||
|
||||
ptr = rfbScalingFind(cl,width,height);
|
||||
if (ptr==NULL)
|
||||
ptr = rfbScaledScreenAllocate(cl,width,height);
|
||||
/* Now, there is a new screen available (if ptr is not NULL) */
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
/* Update it! */
|
||||
if (ptr->scaledScreenRefCount<1)
|
||||
rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height);
|
||||
/*
|
||||
* rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n",
|
||||
* cl->scaledScreen->width, cl->scaledScreen->height,
|
||||
* cl->scaledScreen->scaledScreenRefCount,
|
||||
* ptr->width, ptr->height, ptr->scaledScreenRefCount);
|
||||
*/
|
||||
|
||||
LOCK(cl->updateMutex);
|
||||
cl->scaledScreen->scaledScreenRefCount--;
|
||||
ptr->scaledScreenRefCount++;
|
||||
cl->scaledScreen=ptr;
|
||||
cl->newFBSizePending = TRUE;
|
||||
UNLOCK(cl->updateMutex);
|
||||
|
||||
rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount);
|
||||
}
|
||||
else
|
||||
rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height);
|
||||
}
|
||||
|
||||
int rfbSendNewScaleSize(rfbClientPtr cl)
|
||||
{
|
||||
/* if the client supports newFBsize Encoding, use it */
|
||||
if (cl->useNewFBSize && cl->newFBSizePending)
|
||||
return FALSE;
|
||||
|
||||
LOCK(cl->updateMutex);
|
||||
cl->newFBSizePending = FALSE;
|
||||
UNLOCK(cl->updateMutex);
|
||||
|
||||
if (cl->PalmVNC==TRUE)
|
||||
{
|
||||
rfbPalmVNCReSizeFrameBufferMsg pmsg;
|
||||
pmsg.type = rfbPalmVNCReSizeFrameBuffer;
|
||||
pmsg.pad1 = 0;
|
||||
pmsg.desktop_w = Swap16IfLE(cl->screen->width);
|
||||
pmsg.desktop_h = Swap16IfLE(cl->screen->height);
|
||||
pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width);
|
||||
pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height);
|
||||
pmsg.pad2 = 0;
|
||||
|
||||
rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height);
|
||||
if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) {
|
||||
rfbLogPerror("rfbNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
rfbClientConnectionGone(cl);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rfbResizeFrameBufferMsg rmsg;
|
||||
rmsg.type = rfbResizeFrameBuffer;
|
||||
rmsg.pad1=0;
|
||||
rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width);
|
||||
rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height);
|
||||
rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height);
|
||||
if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) {
|
||||
rfbLogPerror("rfbNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
rfbClientConnectionGone(cl);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/****************************/
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x);
|
||||
int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y);
|
||||
void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, const char *function);
|
||||
void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0);
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
|
||||
rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height);
|
||||
rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height);
|
||||
void rfbScalingSetup(rfbClientPtr cl, int width, int height);
|
||||
int rfbSendNewScaleSize(rfbClientPtr cl);
|
|
@ -1,300 +0,0 @@
|
|||
#include <ctype.h>
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/keysym.h"
|
||||
|
||||
typedef struct {
|
||||
rfbScreenInfoPtr screen;
|
||||
rfbFontDataPtr font;
|
||||
char** list;
|
||||
int listSize;
|
||||
int selected;
|
||||
int displayStart;
|
||||
int x1,y1,x2,y2,textH,pageH;
|
||||
int xhot,yhot;
|
||||
int buttonWidth,okBX,cancelBX,okX,cancelX,okY;
|
||||
rfbBool okInverted,cancelInverted;
|
||||
int lastButtons;
|
||||
rfbPixel colour,backColour;
|
||||
SelectionChangedHookPtr selChangedHook;
|
||||
enum { SELECTING, OK, CANCEL } state;
|
||||
} rfbSelectData;
|
||||
|
||||
static const char* okStr="OK";
|
||||
static const char* cancelStr="Cancel";
|
||||
|
||||
static void selPaintButtons(rfbSelectData* m,rfbBool invertOk,rfbBool invertCancel)
|
||||
{
|
||||
rfbScreenInfoPtr s = m->screen;
|
||||
rfbPixel bcolour = m->backColour;
|
||||
rfbPixel colour = m->colour;
|
||||
|
||||
rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour);
|
||||
|
||||
if(invertOk) {
|
||||
rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour);
|
||||
rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,
|
||||
m->x1,m->okY-m->textH,m->x2,m->okY,
|
||||
bcolour,colour);
|
||||
} else
|
||||
rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour);
|
||||
|
||||
if(invertCancel) {
|
||||
rfbFillRect(s,m->cancelBX,m->okY-m->textH,
|
||||
m->cancelBX+m->buttonWidth,m->okY,colour);
|
||||
rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,
|
||||
cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY,
|
||||
bcolour,colour);
|
||||
} else
|
||||
rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour);
|
||||
|
||||
m->okInverted = invertOk;
|
||||
m->cancelInverted = invertCancel;
|
||||
}
|
||||
|
||||
/* line is relative to displayStart */
|
||||
static void selPaintLine(rfbSelectData* m,int line,rfbBool invert)
|
||||
{
|
||||
int y1 = m->y1+line*m->textH, y2 = y1+m->textH;
|
||||
if(y2>m->y2)
|
||||
y2=m->y2;
|
||||
rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour);
|
||||
if(m->displayStart+line<m->listSize)
|
||||
rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot,
|
||||
m->list[m->displayStart+line],
|
||||
m->x1,y1,m->x2,y2,
|
||||
invert?m->backColour:m->colour,
|
||||
invert?m->backColour:m->colour);
|
||||
}
|
||||
|
||||
static void selSelect(rfbSelectData* m,int _index)
|
||||
{
|
||||
int delta;
|
||||
|
||||
if(_index==m->selected || _index<0 || _index>=m->listSize)
|
||||
return;
|
||||
|
||||
if(m->selected>=0)
|
||||
selPaintLine(m,m->selected-m->displayStart,FALSE);
|
||||
|
||||
if(_index<m->displayStart || _index>=m->displayStart+m->pageH) {
|
||||
/* targetLine is the screen line in which the selected line will
|
||||
be displayed.
|
||||
targetLine = m->pageH/2 doesn't look so nice */
|
||||
int targetLine = m->selected-m->displayStart;
|
||||
int lineStart,lineEnd;
|
||||
|
||||
/* scroll */
|
||||
if(_index<targetLine)
|
||||
targetLine = _index;
|
||||
else if(_index+m->pageH-targetLine>=m->listSize)
|
||||
targetLine = _index+m->pageH-m->listSize;
|
||||
delta = _index-(m->displayStart+targetLine);
|
||||
|
||||
if(delta>-m->pageH && delta<m->pageH) {
|
||||
if(delta>0) {
|
||||
lineStart = m->pageH-delta;
|
||||
lineEnd = m->pageH;
|
||||
rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH,
|
||||
0,-delta*m->textH);
|
||||
} else {
|
||||
lineStart = 0;
|
||||
lineEnd = -delta;
|
||||
rfbDoCopyRect(m->screen,
|
||||
m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2,
|
||||
0,-delta*m->textH);
|
||||
}
|
||||
} else {
|
||||
lineStart = 0;
|
||||
lineEnd = m->pageH;
|
||||
}
|
||||
m->displayStart += delta;
|
||||
for(delta=lineStart;delta<lineEnd;delta++)
|
||||
if(delta!=_index)
|
||||
selPaintLine(m,delta,FALSE);
|
||||
}
|
||||
|
||||
m->selected = _index;
|
||||
selPaintLine(m,m->selected-m->displayStart,TRUE);
|
||||
|
||||
if(m->selChangedHook)
|
||||
m->selChangedHook(_index);
|
||||
|
||||
/* todo: scrollbars */
|
||||
}
|
||||
|
||||
static void selKbdAddEvent(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)
|
||||
{
|
||||
if(down) {
|
||||
if(keySym>' ' && keySym<0xff) {
|
||||
int i;
|
||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
||||
char c = tolower(keySym);
|
||||
|
||||
for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++);
|
||||
if(!m->list[i])
|
||||
for(i=0;i<m->selected && tolower(m->list[i][0])!=c;i++);
|
||||
selSelect(m,i);
|
||||
} else if(keySym==XK_Escape) {
|
||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
||||
m->state = CANCEL;
|
||||
} else if(keySym==XK_Return) {
|
||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
||||
m->state = OK;
|
||||
} else {
|
||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
||||
int curSel=m->selected;
|
||||
if(keySym==XK_Up) {
|
||||
if(curSel>0)
|
||||
selSelect(m,curSel-1);
|
||||
} else if(keySym==XK_Down) {
|
||||
if(curSel+1<m->listSize)
|
||||
selSelect(m,curSel+1);
|
||||
} else {
|
||||
if(keySym==XK_Page_Down) {
|
||||
if(curSel+m->pageH<m->listSize)
|
||||
selSelect(m,curSel+m->pageH);
|
||||
else
|
||||
selSelect(m,m->listSize-1);
|
||||
} else if(keySym==XK_Page_Up) {
|
||||
if(curSel-m->pageH>=0)
|
||||
selSelect(m,curSel-m->pageH);
|
||||
else
|
||||
selSelect(m,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
|
||||
{
|
||||
rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
|
||||
if(y<m->okY && y>=m->okY-m->textH) {
|
||||
if(x>=m->okBX && x<m->okBX+m->buttonWidth) {
|
||||
if(!m->okInverted)
|
||||
selPaintButtons(m,TRUE,FALSE);
|
||||
if(buttonMask)
|
||||
m->state = OK;
|
||||
} else if(x>=m->cancelBX && x<m->cancelBX+m->buttonWidth) {
|
||||
if(!m->cancelInverted)
|
||||
selPaintButtons(m,FALSE,TRUE);
|
||||
if(buttonMask)
|
||||
m->state = CANCEL;
|
||||
} else if(m->okInverted || m->cancelInverted)
|
||||
selPaintButtons(m,FALSE,FALSE);
|
||||
} else {
|
||||
if(m->okInverted || m->cancelInverted)
|
||||
selPaintButtons(m,FALSE,FALSE);
|
||||
if(!m->lastButtons && buttonMask) {
|
||||
if(x>=m->x1 && x<m->x2 && y>=m->y1 && y<m->y2)
|
||||
selSelect(m,m->displayStart+(y-m->y1)/m->textH);
|
||||
}
|
||||
}
|
||||
m->lastButtons = buttonMask;
|
||||
|
||||
/* todo: scrollbars */
|
||||
}
|
||||
|
||||
static rfbCursorPtr selGetCursorPtr(rfbClientPtr cl)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
||||
char** list,
|
||||
int x1,int y1,int x2,int y2,
|
||||
rfbPixel colour,rfbPixel backColour,
|
||||
int border,SelectionChangedHookPtr selChangedHook)
|
||||
{
|
||||
int bpp = rfbScreen->bitsPerPixel/8;
|
||||
char* frameBufferBackup;
|
||||
void* screenDataBackup = rfbScreen->screenData;
|
||||
rfbKbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent;
|
||||
rfbPtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent;
|
||||
rfbGetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr;
|
||||
rfbDisplayHookPtr displayHookBackup = rfbScreen->displayHook;
|
||||
rfbSelectData selData;
|
||||
int i,j,k;
|
||||
int fx1,fy1,fx2,fy2; /* for font bbox */
|
||||
|
||||
if(list==0 || *list==0)
|
||||
return(-1);
|
||||
|
||||
rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2);
|
||||
selData.textH = fy2-fy1;
|
||||
/* I need at least one line for the choice and one for the buttons */
|
||||
if(y2-y1<selData.textH*2+3*border)
|
||||
return(-1);
|
||||
selData.xhot = -fx1;
|
||||
selData.yhot = -fy2;
|
||||
selData.x1 = x1+border;
|
||||
selData.y1 = y1+border;
|
||||
selData.y2 = y2-selData.textH-3*border;
|
||||
selData.x2 = x2-2*border;
|
||||
selData.pageH = (selData.y2-selData.y1)/selData.textH;
|
||||
|
||||
i = rfbWidthOfString(font,okStr);
|
||||
j = rfbWidthOfString(font,cancelStr);
|
||||
selData.buttonWidth= k = 4*border+(i<j)?j:i;
|
||||
selData.okBX = x1+(x2-x1-2*k)/3;
|
||||
if(selData.okBX<x1+border) /* too narrow! */
|
||||
return(-1);
|
||||
selData.cancelBX = x1+k+(x2-x1-2*k)*2/3;
|
||||
selData.okX = selData.okBX+(k-i)/2;
|
||||
selData.cancelX = selData.cancelBX+(k-j)/2;
|
||||
selData.okY = y2-border;
|
||||
|
||||
frameBufferBackup = (char*)malloc(bpp*(x2-x1)*(y2-y1));
|
||||
|
||||
selData.state = SELECTING;
|
||||
selData.screen = rfbScreen;
|
||||
selData.font = font;
|
||||
selData.list = list;
|
||||
selData.colour = colour;
|
||||
selData.backColour = backColour;
|
||||
for(i=0;list[i];i++);
|
||||
selData.selected = i;
|
||||
selData.listSize = i;
|
||||
selData.displayStart = i;
|
||||
selData.lastButtons = 0;
|
||||
selData.selChangedHook = selChangedHook;
|
||||
|
||||
rfbScreen->screenData = &selData;
|
||||
rfbScreen->kbdAddEvent = selKbdAddEvent;
|
||||
rfbScreen->ptrAddEvent = selPtrAddEvent;
|
||||
rfbScreen->getCursorPtr = selGetCursorPtr;
|
||||
rfbScreen->displayHook = NULL;
|
||||
|
||||
/* backup screen */
|
||||
for(j=0;j<y2-y1;j++)
|
||||
memcpy(frameBufferBackup+j*(x2-x1)*bpp,
|
||||
rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
|
||||
(x2-x1)*bpp);
|
||||
|
||||
/* paint list and buttons */
|
||||
rfbFillRect(rfbScreen,x1,y1,x2,y2,colour);
|
||||
selPaintButtons(&selData,FALSE,FALSE);
|
||||
selSelect(&selData,0);
|
||||
|
||||
/* modal loop */
|
||||
while(selData.state == SELECTING)
|
||||
rfbProcessEvents(rfbScreen,20000);
|
||||
|
||||
/* copy back screen data */
|
||||
for(j=0;j<y2-y1;j++)
|
||||
memcpy(rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
|
||||
frameBufferBackup+j*(x2-x1)*bpp,
|
||||
(x2-x1)*bpp);
|
||||
free(frameBufferBackup);
|
||||
rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2);
|
||||
rfbScreen->screenData = screenDataBackup;
|
||||
rfbScreen->kbdAddEvent = kbdAddEventBackup;
|
||||
rfbScreen->ptrAddEvent = ptrAddEventBackup;
|
||||
rfbScreen->getCursorPtr = getCursorPtrBackup;
|
||||
rfbScreen->displayHook = displayHookBackup;
|
||||
|
||||
if(selData.state==CANCEL)
|
||||
selData.selected=-1;
|
||||
return(selData.selected);
|
||||
}
|
||||
|
|
@ -1,738 +0,0 @@
|
|||
/*
|
||||
* sockets.c - deal with TCP & UDP sockets.
|
||||
*
|
||||
* This code should be independent of any changes in the RFB protocol. It just
|
||||
* deals with the X server scheduling stuff, calling rfbNewClientConnection and
|
||||
* rfbProcessClientMessage to actually deal with the protocol. If a socket
|
||||
* needs to be closed for any reason then rfbCloseClient should be called, and
|
||||
* this in turn will call rfbClientConnectionGone. To make an active
|
||||
* connection out, call rfbConnect - note that this does _not_ call
|
||||
* rfbNewClientConnection.
|
||||
*
|
||||
* This file is divided into two types of function. Those beginning with
|
||||
* "rfb" are specific to sockets using the RFB protocol. Those without the
|
||||
* "rfb" prefix are more general socket routines (which are used by the http
|
||||
* code).
|
||||
*
|
||||
* Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN
|
||||
* not EWOULDBLOCK.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(NEED_TIMEVAL)
|
||||
struct timeval
|
||||
{
|
||||
long int tv_sec,tv_usec;
|
||||
}
|
||||
;
|
||||
#endif
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef USE_LIBWRAP
|
||||
#include <syslog.h>
|
||||
#include <tcpd.h>
|
||||
int allow_severity=LOG_INFO;
|
||||
int deny_severity=LOG_WARNING;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#ifndef __MINGW32__
|
||||
#pragma warning (disable: 4018 4761)
|
||||
#endif
|
||||
#define read(sock,buf,len) recv(sock,buf,len,0)
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#define write(sock,buf,len) send(sock,buf,len,0)
|
||||
#else
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
|
||||
gone away - needed to stop us hanging */
|
||||
|
||||
/*
|
||||
* rfbInitSockets sets up the TCP and UDP sockets to listen for RFB
|
||||
* connections. It does nothing if called again.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbInitSockets(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
in_addr_t iface = rfbScreen->listenInterface;
|
||||
|
||||
if (rfbScreen->socketState == RFB_SOCKET_READY) {
|
||||
return;
|
||||
}
|
||||
|
||||
rfbScreen->socketState = RFB_SOCKET_READY;
|
||||
|
||||
if (rfbScreen->inetdSock != -1) {
|
||||
const int one = 1;
|
||||
|
||||
if(!rfbSetNonBlocking(rfbScreen->inetdSock))
|
||||
return;
|
||||
|
||||
if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)&one, sizeof(one)) < 0) {
|
||||
rfbLogPerror("setsockopt");
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&(rfbScreen->allFds));
|
||||
FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
|
||||
rfbScreen->maxFd = rfbScreen->inetdSock;
|
||||
return;
|
||||
}
|
||||
|
||||
if(rfbScreen->autoPort) {
|
||||
int i;
|
||||
rfbLog("Autoprobing TCP port \n");
|
||||
for (i = 5900; i < 6000; i++) {
|
||||
if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) {
|
||||
rfbScreen->port = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 6000) {
|
||||
rfbLogPerror("Failure autoprobing");
|
||||
return;
|
||||
}
|
||||
|
||||
rfbLog("Autoprobing selected port %d\n", rfbScreen->port);
|
||||
FD_ZERO(&(rfbScreen->allFds));
|
||||
FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
|
||||
rfbScreen->maxFd = rfbScreen->listenSock;
|
||||
}
|
||||
else if(rfbScreen->port>0) {
|
||||
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);
|
||||
|
||||
if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {
|
||||
rfbLogPerror("ListenOnTCPPort");
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&(rfbScreen->allFds));
|
||||
FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
|
||||
rfbScreen->maxFd = rfbScreen->listenSock;
|
||||
}
|
||||
|
||||
if (rfbScreen->udpPort != 0) {
|
||||
rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);
|
||||
|
||||
if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) {
|
||||
rfbLogPerror("ListenOnUDPPort");
|
||||
return;
|
||||
}
|
||||
FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
|
||||
rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
|
||||
}
|
||||
}
|
||||
|
||||
void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
if (rfbScreen->socketState!=RFB_SOCKET_READY)
|
||||
return;
|
||||
|
||||
rfbScreen->socketState = RFB_SOCKET_SHUTDOWN;
|
||||
|
||||
if(rfbScreen->inetdSock>-1) {
|
||||
closesocket(rfbScreen->inetdSock);
|
||||
FD_CLR(rfbScreen->inetdSock,&rfbScreen->allFds);
|
||||
rfbScreen->inetdSock=-1;
|
||||
}
|
||||
|
||||
if(rfbScreen->listenSock>-1) {
|
||||
closesocket(rfbScreen->listenSock);
|
||||
FD_CLR(rfbScreen->listenSock,&rfbScreen->allFds);
|
||||
rfbScreen->listenSock=-1;
|
||||
}
|
||||
|
||||
if(rfbScreen->udpSock>-1) {
|
||||
closesocket(rfbScreen->udpSock);
|
||||
FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds);
|
||||
rfbScreen->udpSock=-1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
|
||||
* socket(s). If there is input to process, the appropriate function in the
|
||||
* RFB server code will be called (rfbNewClientConnection,
|
||||
* rfbProcessClientMessage, etc).
|
||||
*/
|
||||
|
||||
int
|
||||
rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
|
||||
{
|
||||
int nfds;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
char buf[6];
|
||||
rfbClientIteratorPtr i;
|
||||
rfbClientPtr cl;
|
||||
int result = 0;
|
||||
|
||||
if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
|
||||
rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock);
|
||||
rfbScreen->inetdInitDone = TRUE;
|
||||
}
|
||||
|
||||
do {
|
||||
memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = usec;
|
||||
nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
|
||||
if (nfds == 0) {
|
||||
/* timed out, check for async events */
|
||||
i = rfbGetClientIterator(rfbScreen);
|
||||
while((cl = rfbClientIteratorNext(i))) {
|
||||
if (cl->onHold)
|
||||
continue;
|
||||
if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
|
||||
rfbSendFileTransferChunk(cl);
|
||||
}
|
||||
rfbReleaseClientIterator(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (nfds < 0) {
|
||||
#ifdef WIN32
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno != EINTR)
|
||||
rfbLogPerror("rfbCheckFds: select");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result += nfds;
|
||||
|
||||
if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) {
|
||||
|
||||
if (!rfbProcessNewConnection(rfbScreen))
|
||||
return -1;
|
||||
|
||||
FD_CLR(rfbScreen->listenSock, &fds);
|
||||
if (--nfds == 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
|
||||
if(!rfbScreen->udpClient)
|
||||
rfbNewUDPClient(rfbScreen);
|
||||
if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
|
||||
(struct sockaddr *)&addr, &addrlen) < 0) {
|
||||
rfbLogPerror("rfbCheckFds: UDP: recvfrom");
|
||||
rfbDisconnectUDPSock(rfbScreen);
|
||||
rfbScreen->udpSockConnected = FALSE;
|
||||
} else {
|
||||
if (!rfbScreen->udpSockConnected ||
|
||||
(memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
|
||||
{
|
||||
/* new remote end */
|
||||
rfbLog("rfbCheckFds: UDP: got connection\n");
|
||||
|
||||
memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
|
||||
rfbScreen->udpSockConnected = TRUE;
|
||||
|
||||
if (connect(rfbScreen->udpSock,
|
||||
(struct sockaddr *)&addr, addrlen) < 0) {
|
||||
rfbLogPerror("rfbCheckFds: UDP: connect");
|
||||
rfbDisconnectUDPSock(rfbScreen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
|
||||
}
|
||||
|
||||
rfbProcessUDPInput(rfbScreen);
|
||||
}
|
||||
|
||||
FD_CLR(rfbScreen->udpSock, &fds);
|
||||
if (--nfds == 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
i = rfbGetClientIterator(rfbScreen);
|
||||
while((cl = rfbClientIteratorNext(i))) {
|
||||
|
||||
if (cl->onHold)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
|
||||
{
|
||||
if (FD_ISSET(cl->sock, &fds))
|
||||
rfbProcessClientMessage(cl);
|
||||
else
|
||||
rfbSendFileTransferChunk(cl);
|
||||
}
|
||||
}
|
||||
rfbReleaseClientIterator(i);
|
||||
} while(rfbScreen->handleEventsEagerly);
|
||||
return result;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
const int one = 1;
|
||||
int sock = -1;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
if ((sock = accept(rfbScreen->listenSock,
|
||||
(struct sockaddr *)&addr, &addrlen)) < 0) {
|
||||
rfbLogPerror("rfbCheckFds: accept");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!rfbSetNonBlocking(sock)) {
|
||||
closesocket(sock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)&one, sizeof(one)) < 0) {
|
||||
rfbLogPerror("rfbCheckFds: setsockopt");
|
||||
closesocket(sock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef USE_LIBWRAP
|
||||
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
|
||||
STRING_UNKNOWN)) {
|
||||
rfbLog("Rejected connection from client %s\n",
|
||||
inet_ntoa(addr.sin_addr));
|
||||
closesocket(sock);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
|
||||
|
||||
rfbNewClient(rfbScreen,sock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen)
|
||||
{
|
||||
rfbScreen->udpSockConnected = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rfbCloseClient(rfbClientPtr cl)
|
||||
{
|
||||
rfbExtensionData* extension;
|
||||
|
||||
for(extension=cl->extensions; extension; extension=extension->next)
|
||||
if(extension->extension->close)
|
||||
extension->extension->close(cl, extension->data);
|
||||
|
||||
LOCK(cl->updateMutex);
|
||||
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
|
||||
if (cl->sock != -1)
|
||||
#endif
|
||||
{
|
||||
FD_CLR(cl->sock,&(cl->screen->allFds));
|
||||
if(cl->sock==cl->screen->maxFd)
|
||||
while(cl->screen->maxFd>0
|
||||
&& !FD_ISSET(cl->screen->maxFd,&(cl->screen->allFds)))
|
||||
cl->screen->maxFd--;
|
||||
#ifndef __MINGW32__
|
||||
shutdown(cl->sock,SHUT_RDWR);
|
||||
#endif
|
||||
closesocket(cl->sock);
|
||||
cl->sock = -1;
|
||||
}
|
||||
TSIGNAL(cl->updateCond);
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbConnect is called to make a connection out to a given TCP address.
|
||||
*/
|
||||
|
||||
int
|
||||
rfbConnect(rfbScreenInfoPtr rfbScreen,
|
||||
char *host,
|
||||
int port)
|
||||
{
|
||||
int sock;
|
||||
int one = 1;
|
||||
|
||||
rfbLog("Making connection to client on host %s port %d\n",
|
||||
host,port);
|
||||
|
||||
if ((sock = rfbConnectToTcpAddr(host, port)) < 0) {
|
||||
rfbLogPerror("connection failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!rfbSetNonBlocking(sock)) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)&one, sizeof(one)) < 0) {
|
||||
rfbLogPerror("setsockopt failed");
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* AddEnabledDevice(sock); */
|
||||
FD_SET(sock, &rfbScreen->allFds);
|
||||
rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* ReadExact reads an exact number of bytes from a client. Returns 1 if
|
||||
* those bytes have been read, 0 if the other end has closed, or -1 if an error
|
||||
* occurred (errno is set to ETIMEDOUT if it timed out).
|
||||
*/
|
||||
|
||||
int
|
||||
rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
|
||||
{
|
||||
int sock = cl->sock;
|
||||
int n;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
while (len > 0) {
|
||||
n = read(sock, buf, len);
|
||||
|
||||
if (n > 0) {
|
||||
|
||||
buf += n;
|
||||
len -= n;
|
||||
|
||||
} else if (n == 0) {
|
||||
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
#ifdef LIBVNCSERVER_ENOENT_WORKAROUND
|
||||
if (errno != ENOENT)
|
||||
#endif
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
return n;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
n = select(sock+1, &fds, NULL, &fds, &tv);
|
||||
if (n < 0) {
|
||||
rfbLogPerror("ReadExact: select");
|
||||
return n;
|
||||
}
|
||||
if (n == 0) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DEBUG_READ_EXACT
|
||||
#ifdef DEBUG_READ_EXACT
|
||||
rfbLog("ReadExact %d bytes\n",len);
|
||||
for(n=0;n<len;n++)
|
||||
fprintf(stderr,"%02x ",(unsigned char)buf[n]);
|
||||
fprintf(stderr,"\n");
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rfbReadExact(rfbClientPtr cl,char* buf,int len)
|
||||
{
|
||||
/* favor the per-screen value if set */
|
||||
if(cl->screen && cl->screen->maxClientWait)
|
||||
return(rfbReadExactTimeout(cl,buf,len,cl->screen->maxClientWait));
|
||||
else
|
||||
return(rfbReadExactTimeout(cl,buf,len,rfbMaxClientWait));
|
||||
}
|
||||
|
||||
/*
|
||||
* WriteExact writes an exact number of bytes to a client. Returns 1 if
|
||||
* those bytes have been written, or -1 if an error occurred (errno is set to
|
||||
* ETIMEDOUT if it timed out).
|
||||
*/
|
||||
|
||||
int
|
||||
rfbWriteExact(rfbClientPtr cl,
|
||||
const char *buf,
|
||||
int len)
|
||||
{
|
||||
int sock = cl->sock;
|
||||
int n;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int totalTimeWaited = 0;
|
||||
const int timeout = (cl->screen && cl->screen->maxClientWait) ? cl->screen->maxClientWait : rfbMaxClientWait;
|
||||
|
||||
#undef DEBUG_WRITE_EXACT
|
||||
#ifdef DEBUG_WRITE_EXACT
|
||||
rfbLog("WriteExact %d bytes\n",len);
|
||||
for(n=0;n<len;n++)
|
||||
fprintf(stderr,"%02x ",(unsigned char)buf[n]);
|
||||
fprintf(stderr,"\n");
|
||||
#endif
|
||||
|
||||
LOCK(cl->outputMutex);
|
||||
while (len > 0) {
|
||||
n = write(sock, buf, len);
|
||||
|
||||
if (n > 0) {
|
||||
|
||||
buf += n;
|
||||
len -= n;
|
||||
|
||||
} else if (n == 0) {
|
||||
|
||||
rfbErr("WriteExact: write returned 0?\n");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
UNLOCK(cl->outputMutex);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Retry every 5 seconds until we exceed timeout. We
|
||||
need to do this because select doesn't necessarily return
|
||||
immediately when the other end has gone away */
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
tv.tv_sec = 5;
|
||||
tv.tv_usec = 0;
|
||||
n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv);
|
||||
if (n < 0) {
|
||||
#ifdef WIN32
|
||||
errno=WSAGetLastError();
|
||||
#endif
|
||||
if(errno==EINTR)
|
||||
continue;
|
||||
rfbLogPerror("WriteExact: select");
|
||||
UNLOCK(cl->outputMutex);
|
||||
return n;
|
||||
}
|
||||
if (n == 0) {
|
||||
totalTimeWaited += 5000;
|
||||
if (totalTimeWaited >= timeout) {
|
||||
errno = ETIMEDOUT;
|
||||
UNLOCK(cl->outputMutex);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
totalTimeWaited = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK(cl->outputMutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* currently private, called by rfbProcessArguments() */
|
||||
int
|
||||
rfbStringToAddr(char *str, in_addr_t *addr) {
|
||||
if (str == NULL || *str == '\0' || strcmp(str, "any") == 0) {
|
||||
*addr = htonl(INADDR_ANY);
|
||||
} else if (strcmp(str, "localhost") == 0) {
|
||||
*addr = htonl(INADDR_LOOPBACK);
|
||||
} else {
|
||||
struct hostent *hp;
|
||||
if ((*addr = inet_addr(str)) == htonl(INADDR_NONE)) {
|
||||
if (!(hp = gethostbyname(str))) {
|
||||
return 0;
|
||||
}
|
||||
*addr = *(unsigned long *)hp->h_addr;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rfbListenOnTCPPort(int port,
|
||||
in_addr_t iface)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
int one = 1;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = iface;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&one, sizeof(one)) < 0) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
if (listen(sock, 32) < 0) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int
|
||||
rfbConnectToTcpAddr(char *host,
|
||||
int port)
|
||||
{
|
||||
struct hostent *hp;
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if ((addr.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE))
|
||||
{
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
|
||||
}
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int
|
||||
rfbListenOnUDPPort(int port,
|
||||
in_addr_t iface)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
int one = 1;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = iface;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&one, sizeof(one)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbSetNonBlocking sets a socket into non-blocking mode.
|
||||
*/
|
||||
rfbBool
|
||||
rfbSetNonBlocking(int sock)
|
||||
{
|
||||
#ifdef WIN32
|
||||
unsigned long block=1;
|
||||
if(ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR) {
|
||||
errno=WSAGetLastError();
|
||||
#else
|
||||
int flags = fcntl(sock, F_GETFL);
|
||||
if(flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
#endif
|
||||
rfbLogPerror("Setting socket to non-blocking failed");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
|
@ -1,478 +0,0 @@
|
|||
/*
|
||||
* stats.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
char *messageNameServer2Client(uint32_t type, char *buf, int len);
|
||||
char *messageNameClient2Server(uint32_t type, char *buf, int len);
|
||||
char *encodingName(uint32_t enc, char *buf, int len);
|
||||
|
||||
rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type);
|
||||
rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type);
|
||||
|
||||
void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
|
||||
void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
|
||||
void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
|
||||
void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
|
||||
void rfbResetStats(rfbClientPtr cl);
|
||||
void rfbPrintStats(rfbClientPtr cl);
|
||||
|
||||
|
||||
|
||||
|
||||
char *messageNameServer2Client(uint32_t type, char *buf, int len) {
|
||||
if (buf==NULL) return "error";
|
||||
switch (type) {
|
||||
case rfbFramebufferUpdate: snprintf(buf, len, "FramebufferUpdate"); break;
|
||||
case rfbSetColourMapEntries: snprintf(buf, len, "SetColourMapEntries"); break;
|
||||
case rfbBell: snprintf(buf, len, "Bell"); break;
|
||||
case rfbServerCutText: snprintf(buf, len, "ServerCutText"); break;
|
||||
case rfbResizeFrameBuffer: snprintf(buf, len, "ResizeFrameBuffer"); break;
|
||||
case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
|
||||
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
|
||||
case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break;
|
||||
case rfbXvp: snprintf(buf, len, "XvpServerMessage"); break;
|
||||
default:
|
||||
snprintf(buf, len, "svr2cli-0x%08X", 0xFF);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *messageNameClient2Server(uint32_t type, char *buf, int len) {
|
||||
if (buf==NULL) return "error";
|
||||
switch (type) {
|
||||
case rfbSetPixelFormat: snprintf(buf, len, "SetPixelFormat"); break;
|
||||
case rfbFixColourMapEntries: snprintf(buf, len, "FixColourMapEntries"); break;
|
||||
case rfbSetEncodings: snprintf(buf, len, "SetEncodings"); break;
|
||||
case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break;
|
||||
case rfbKeyEvent: snprintf(buf, len, "KeyEvent"); break;
|
||||
case rfbPointerEvent: snprintf(buf, len, "PointerEvent"); break;
|
||||
case rfbClientCutText: snprintf(buf, len, "ClientCutText"); break;
|
||||
case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
|
||||
case rfbSetScale: snprintf(buf, len, "SetScale"); break;
|
||||
case rfbSetServerInput: snprintf(buf, len, "SetServerInput"); break;
|
||||
case rfbSetSW: snprintf(buf, len, "SetSingleWindow"); break;
|
||||
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
|
||||
case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break;
|
||||
case rfbXvp: snprintf(buf, len, "XvpClientMessage"); break;
|
||||
default:
|
||||
snprintf(buf, len, "cli2svr-0x%08X", type);
|
||||
|
||||
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Encoding name must be <=16 characters to fit nicely on the status output in
|
||||
* an 80 column terminal window
|
||||
*/
|
||||
char *encodingName(uint32_t type, char *buf, int len) {
|
||||
if (buf==NULL) return "error";
|
||||
|
||||
switch (type) {
|
||||
case rfbEncodingRaw: snprintf(buf, len, "raw"); break;
|
||||
case rfbEncodingCopyRect: snprintf(buf, len, "copyRect"); break;
|
||||
case rfbEncodingRRE: snprintf(buf, len, "RRE"); break;
|
||||
case rfbEncodingCoRRE: snprintf(buf, len, "CoRRE"); break;
|
||||
case rfbEncodingHextile: snprintf(buf, len, "hextile"); break;
|
||||
case rfbEncodingZlib: snprintf(buf, len, "zlib"); break;
|
||||
case rfbEncodingTight: snprintf(buf, len, "tight"); break;
|
||||
case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break;
|
||||
case rfbEncodingUltra: snprintf(buf, len, "ultra"); break;
|
||||
case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break;
|
||||
case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); break;
|
||||
case rfbEncodingCache: snprintf(buf, len, "cache"); break;
|
||||
case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break;
|
||||
case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break;
|
||||
case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break;
|
||||
case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break;
|
||||
case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break;
|
||||
case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break;
|
||||
case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break;
|
||||
case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break;
|
||||
case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break;
|
||||
|
||||
case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break;
|
||||
case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break;
|
||||
case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break;
|
||||
|
||||
case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break;
|
||||
case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break;
|
||||
case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break;
|
||||
case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessage"); break;
|
||||
case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break;
|
||||
case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break;
|
||||
|
||||
/* The following lookups do not report in stats */
|
||||
case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break;
|
||||
case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break;
|
||||
case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break;
|
||||
case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break;
|
||||
case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break;
|
||||
case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break;
|
||||
case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break;
|
||||
case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break;
|
||||
case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break;
|
||||
case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break;
|
||||
|
||||
case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break;
|
||||
case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break;
|
||||
case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break;
|
||||
case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break;
|
||||
case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break;
|
||||
case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break;
|
||||
case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break;
|
||||
case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break;
|
||||
case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break;
|
||||
case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break;
|
||||
|
||||
|
||||
default:
|
||||
snprintf(buf, len, "Enc(0x%08X)", type);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
if (cl==NULL) return NULL;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
if (ptr->type==type) return ptr;
|
||||
}
|
||||
/* Well, we are here... need to *CREATE* an entry */
|
||||
ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
memset((char *)ptr, 0, sizeof(rfbStatList));
|
||||
ptr->type = type;
|
||||
/* add to the top of the list */
|
||||
ptr->Next = cl->statEncList;
|
||||
cl->statEncList = ptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
if (cl==NULL) return NULL;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
if (ptr->type==type) return ptr;
|
||||
}
|
||||
/* Well, we are here... need to *CREATE* an entry */
|
||||
ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
memset((char *)ptr, 0, sizeof(rfbStatList));
|
||||
ptr->type = type;
|
||||
/* add to the top of the list */
|
||||
ptr->Next = cl->statMsgList;
|
||||
cl->statMsgList = ptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
|
||||
ptr = rfbStatLookupEncoding(cl, type);
|
||||
if (ptr!=NULL)
|
||||
ptr->bytesSent += byteCount;
|
||||
}
|
||||
|
||||
|
||||
void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
|
||||
ptr = rfbStatLookupEncoding(cl, type);
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
ptr->sentCount++;
|
||||
ptr->bytesSent += byteCount;
|
||||
ptr->bytesSentIfRaw += byteIfRaw;
|
||||
}
|
||||
}
|
||||
|
||||
void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
|
||||
ptr = rfbStatLookupEncoding(cl, type);
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
ptr->rcvdCount++;
|
||||
ptr->bytesRcvd += byteCount;
|
||||
ptr->bytesRcvdIfRaw += byteIfRaw;
|
||||
}
|
||||
}
|
||||
|
||||
void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
|
||||
ptr = rfbStatLookupMessage(cl, type);
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
ptr->sentCount++;
|
||||
ptr->bytesSent += byteCount;
|
||||
ptr->bytesSentIfRaw += byteIfRaw;
|
||||
}
|
||||
}
|
||||
|
||||
void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
|
||||
ptr = rfbStatLookupMessage(cl, type);
|
||||
if (ptr!=NULL)
|
||||
{
|
||||
ptr->rcvdCount++;
|
||||
ptr->bytesRcvd += byteCount;
|
||||
ptr->bytesRcvdIfRaw += byteIfRaw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rfbStatGetSentBytes(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
int bytes=0;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesSent;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesSent;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int rfbStatGetSentBytesIfRaw(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
int bytes=0;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesSentIfRaw;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesSentIfRaw;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int rfbStatGetRcvdBytes(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
int bytes=0;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesRcvd;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesRcvd;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
int bytes=0;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesRcvdIfRaw;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
bytes += ptr->bytesRcvdIfRaw;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
if (ptr->type==type) return ptr->sentCount;
|
||||
return 0;
|
||||
}
|
||||
int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
if (ptr->type==type) return ptr->rcvdCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
if (ptr->type==type) return ptr->sentCount;
|
||||
return 0;
|
||||
}
|
||||
int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
if (cl==NULL) return 0;
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
if (ptr->type==type) return ptr->rcvdCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void rfbResetStats(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr;
|
||||
if (cl==NULL) return;
|
||||
while (cl->statEncList!=NULL)
|
||||
{
|
||||
ptr = cl->statEncList;
|
||||
cl->statEncList = ptr->Next;
|
||||
free(ptr);
|
||||
}
|
||||
while (cl->statMsgList!=NULL)
|
||||
{
|
||||
ptr = cl->statMsgList;
|
||||
cl->statMsgList = ptr->Next;
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rfbPrintStats(rfbClientPtr cl)
|
||||
{
|
||||
rfbStatList *ptr=NULL;
|
||||
char encBuf[64];
|
||||
double savings=0.0;
|
||||
int totalRects=0;
|
||||
double totalBytes=0.0;
|
||||
double totalBytesIfRaw=0.0;
|
||||
|
||||
char *name=NULL;
|
||||
int bytes=0;
|
||||
int bytesIfRaw=0;
|
||||
int count=0;
|
||||
|
||||
if (cl==NULL) return;
|
||||
|
||||
rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved");
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf));
|
||||
count = ptr->sentCount;
|
||||
bytes = ptr->bytesSent;
|
||||
bytesIfRaw = ptr->bytesSentIfRaw;
|
||||
|
||||
savings = 0.0;
|
||||
if (bytesIfRaw>0.0)
|
||||
savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
|
||||
if ((bytes>0) || (count>0) || (bytesIfRaw>0))
|
||||
rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
|
||||
name, count, bytes, bytesIfRaw, savings);
|
||||
totalRects += count;
|
||||
totalBytes += bytes;
|
||||
totalBytesIfRaw += bytesIfRaw;
|
||||
}
|
||||
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
name = encodingName(ptr->type, encBuf, sizeof(encBuf));
|
||||
count = ptr->sentCount;
|
||||
bytes = ptr->bytesSent;
|
||||
bytesIfRaw = ptr->bytesSentIfRaw;
|
||||
savings = 0.0;
|
||||
|
||||
if (bytesIfRaw>0.0)
|
||||
savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
|
||||
if ((bytes>0) || (count>0) || (bytesIfRaw>0))
|
||||
rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
|
||||
name, count, bytes, bytesIfRaw, savings);
|
||||
totalRects += count;
|
||||
totalBytes += bytes;
|
||||
totalBytesIfRaw += bytesIfRaw;
|
||||
}
|
||||
savings=0.0;
|
||||
if (totalBytesIfRaw>0.0)
|
||||
savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
|
||||
rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
|
||||
"TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);
|
||||
|
||||
totalRects=0.0;
|
||||
totalBytes=0.0;
|
||||
totalBytesIfRaw=0.0;
|
||||
|
||||
rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved");
|
||||
for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf));
|
||||
count = ptr->rcvdCount;
|
||||
bytes = ptr->bytesRcvd;
|
||||
bytesIfRaw = ptr->bytesRcvdIfRaw;
|
||||
savings = 0.0;
|
||||
|
||||
if (bytesIfRaw>0.0)
|
||||
savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
|
||||
if ((bytes>0) || (count>0) || (bytesIfRaw>0))
|
||||
rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
|
||||
name, count, bytes, bytesIfRaw, savings);
|
||||
totalRects += count;
|
||||
totalBytes += bytes;
|
||||
totalBytesIfRaw += bytesIfRaw;
|
||||
}
|
||||
for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
|
||||
{
|
||||
name = encodingName(ptr->type, encBuf, sizeof(encBuf));
|
||||
count = ptr->rcvdCount;
|
||||
bytes = ptr->bytesRcvd;
|
||||
bytesIfRaw = ptr->bytesRcvdIfRaw;
|
||||
savings = 0.0;
|
||||
|
||||
if (bytesIfRaw>0.0)
|
||||
savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
|
||||
if ((bytes>0) || (count>0) || (bytesIfRaw>0))
|
||||
rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
|
||||
name, count, bytes, bytesIfRaw, savings);
|
||||
totalRects += count;
|
||||
totalBytes += bytes;
|
||||
totalBytesIfRaw += bytesIfRaw;
|
||||
}
|
||||
savings=0.0;
|
||||
if (totalBytesIfRaw>0.0)
|
||||
savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
|
||||
rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
|
||||
"TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);
|
||||
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
24 bit
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift,int swap);
|
||||
|
||||
|
||||
static void
|
||||
rfbInitColourMapSingleTable24(char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,rfbColourMap* colourMap)
|
||||
{
|
||||
uint32_t i, r, g, b, outValue;
|
||||
uint8_t *t;
|
||||
uint8_t c;
|
||||
unsigned int nEntries = 1 << in->bitsPerPixel;
|
||||
int shift = colourMap->is16?16:8;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc(nEntries * 3 + 1);
|
||||
t = (uint8_t *)*table;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
r = g = b = 0;
|
||||
if(i < colourMap->count) {
|
||||
if(colourMap->is16) {
|
||||
r = colourMap->data.shorts[3*i+0];
|
||||
g = colourMap->data.shorts[3*i+1];
|
||||
b = colourMap->data.shorts[3*i+2];
|
||||
} else {
|
||||
r = colourMap->data.bytes[3*i+0];
|
||||
g = colourMap->data.bytes[3*i+1];
|
||||
b = colourMap->data.bytes[3*i+2];
|
||||
}
|
||||
}
|
||||
outValue = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
|
||||
(((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
|
||||
(((b * (1 + out->blueMax)) >> shift) << out->blueShift));
|
||||
*(uint32_t*)&t[3*i] = outValue;
|
||||
if(!rfbEndianTest)
|
||||
memmove(t+3*i,t+3*i+1,3);
|
||||
if (out->bigEndian != in->bigEndian) {
|
||||
c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
|
||||
* translation.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbInitTrueColourSingleTable24 (char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out)
|
||||
{
|
||||
int i,outValue;
|
||||
int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
|
||||
uint8_t *t;
|
||||
uint8_t c;
|
||||
int nEntries = 1 << in->bitsPerPixel;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc(nEntries * 3 + 1);
|
||||
t = (uint8_t *)*table;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
inRed = (i >> in->redShift) & in->redMax;
|
||||
inGreen = (i >> in->greenShift) & in->greenMax;
|
||||
inBlue = (i >> in->blueShift) & in->blueMax;
|
||||
|
||||
outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
|
||||
outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
|
||||
outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
|
||||
|
||||
outValue = ((outRed << out->redShift) |
|
||||
(outGreen << out->greenShift) |
|
||||
(outBlue << out->blueShift));
|
||||
*(uint32_t*)&t[3*i] = outValue;
|
||||
if(!rfbEndianTest)
|
||||
memmove(t+3*i,t+3*i+1,3);
|
||||
if (out->bigEndian != in->bigEndian) {
|
||||
c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbInitTrueColourRGBTables sets up three separate lookup tables for the
|
||||
* red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbInitTrueColourRGBTables24 (char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out)
|
||||
{
|
||||
uint8_t *redTable;
|
||||
uint8_t *greenTable;
|
||||
uint8_t *blueTable;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
|
||||
* 3 + 1);
|
||||
redTable = (uint8_t *)*table;
|
||||
greenTable = redTable + 3*(in->redMax + 1);
|
||||
blueTable = greenTable + 3*(in->greenMax + 1);
|
||||
|
||||
rfbInitOneRGBTable24 (redTable, in->redMax, out->redMax,
|
||||
out->redShift, (out->bigEndian != in->bigEndian));
|
||||
rfbInitOneRGBTable24 (greenTable, in->greenMax, out->greenMax,
|
||||
out->greenShift, (out->bigEndian != in->bigEndian));
|
||||
rfbInitOneRGBTable24 (blueTable, in->blueMax, out->blueMax,
|
||||
out->blueShift, (out->bigEndian != in->bigEndian));
|
||||
}
|
||||
|
||||
static void
|
||||
rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift,
|
||||
int swap)
|
||||
{
|
||||
int i;
|
||||
int nEntries = inMax + 1;
|
||||
uint32_t outValue;
|
||||
uint8_t c;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
outValue = ((i * outMax + inMax / 2) / inMax) << outShift;
|
||||
*(uint32_t *)&table[3*i] = outValue;
|
||||
if(!rfbEndianTest)
|
||||
memmove(table+3*i,table+3*i+1,3);
|
||||
if (swap) {
|
||||
c = table[3*i]; table[3*i] = table[3*i+2];
|
||||
table[3*i+2] = c;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* tableinitcmtemplate.c - template for initialising lookup tables for
|
||||
* translation from a colour map to true colour.
|
||||
*
|
||||
* This file shouldn't be compiled. It is included multiple times by
|
||||
* translate.c, each time with a different definition of the macro OUT.
|
||||
* For each value of OUT, this file defines a function which allocates an
|
||||
* appropriately sized lookup table and initialises it.
|
||||
*
|
||||
* I know this code isn't nice to read because of all the macros, but
|
||||
* efficiency is important here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#if !defined(OUT)
|
||||
#error "This file shouldn't be compiled."
|
||||
#error "It is included as part of translate.c"
|
||||
#endif
|
||||
|
||||
#define OUT_T CONCAT3E(uint,OUT,_t)
|
||||
#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
|
||||
#define rfbInitColourMapSingleTableOUT \
|
||||
CONCAT2E(rfbInitColourMapSingleTable,OUT)
|
||||
|
||||
static void
|
||||
rfbInitColourMapSingleTableOUT(char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,rfbColourMap* colourMap)
|
||||
{
|
||||
uint32_t i, r, g, b;
|
||||
OUT_T *t;
|
||||
uint32_t nEntries = 1 << in->bitsPerPixel;
|
||||
int shift = colourMap->is16?16:8;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc(nEntries * sizeof(OUT_T));
|
||||
t = (OUT_T *)*table;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
r = g = b = 0;
|
||||
if(i < colourMap->count) {
|
||||
if(colourMap->is16) {
|
||||
r = colourMap->data.shorts[3*i+0];
|
||||
g = colourMap->data.shorts[3*i+1];
|
||||
b = colourMap->data.shorts[3*i+2];
|
||||
} else {
|
||||
r = colourMap->data.bytes[3*i+0];
|
||||
g = colourMap->data.bytes[3*i+1];
|
||||
b = colourMap->data.bytes[3*i+2];
|
||||
}
|
||||
}
|
||||
t[i] = ((((r * (1 + out->redMax)) >> shift) << out->redShift) |
|
||||
(((g * (1 + out->greenMax)) >> shift) << out->greenShift) |
|
||||
(((b * (1 + out->blueMax)) >> shift) << out->blueShift));
|
||||
#if (OUT != 8)
|
||||
if (out->bigEndian != in->bigEndian) {
|
||||
t[i] = SwapOUT(t[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef OUT_T
|
||||
#undef SwapOUT
|
||||
#undef rfbInitColourMapSingleTableOUT
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* tableinittctemplate.c - template for initialising lookup tables for
|
||||
* truecolour to truecolour translation.
|
||||
*
|
||||
* This file shouldn't be compiled. It is included multiple times by
|
||||
* translate.c, each time with a different definition of the macro OUT.
|
||||
* For each value of OUT, this file defines two functions for initialising
|
||||
* lookup tables. One is for truecolour translation using a single lookup
|
||||
* table, the other is for truecolour translation using three separate
|
||||
* lookup tables for the red, green and blue values.
|
||||
*
|
||||
* I know this code isn't nice to read because of all the macros, but
|
||||
* efficiency is important here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#if !defined(OUT)
|
||||
#error "This file shouldn't be compiled."
|
||||
#error "It is included as part of translate.c"
|
||||
#endif
|
||||
|
||||
#define OUT_T CONCAT3E(uint,OUT,_t)
|
||||
#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
|
||||
#define rfbInitTrueColourSingleTableOUT \
|
||||
CONCAT2E(rfbInitTrueColourSingleTable,OUT)
|
||||
#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT)
|
||||
#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT)
|
||||
|
||||
static void
|
||||
rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
|
||||
int swap);
|
||||
|
||||
|
||||
/*
|
||||
* rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
|
||||
* translation.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbInitTrueColourSingleTableOUT (char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out)
|
||||
{
|
||||
int i;
|
||||
int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
|
||||
OUT_T *t;
|
||||
int nEntries = 1 << in->bitsPerPixel;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc(nEntries * sizeof(OUT_T));
|
||||
t = (OUT_T *)*table;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
inRed = (i >> in->redShift) & in->redMax;
|
||||
inGreen = (i >> in->greenShift) & in->greenMax;
|
||||
inBlue = (i >> in->blueShift) & in->blueMax;
|
||||
|
||||
outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
|
||||
outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
|
||||
outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
|
||||
|
||||
t[i] = ((outRed << out->redShift) |
|
||||
(outGreen << out->greenShift) |
|
||||
(outBlue << out->blueShift));
|
||||
#if (OUT != 8)
|
||||
if (out->bigEndian != in->bigEndian) {
|
||||
t[i] = SwapOUT(t[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbInitTrueColourRGBTables sets up three separate lookup tables for the
|
||||
* red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbInitTrueColourRGBTablesOUT (char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out)
|
||||
{
|
||||
OUT_T *redTable;
|
||||
OUT_T *greenTable;
|
||||
OUT_T *blueTable;
|
||||
|
||||
if (*table) free(*table);
|
||||
*table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
|
||||
* sizeof(OUT_T));
|
||||
redTable = (OUT_T *)*table;
|
||||
greenTable = redTable + in->redMax + 1;
|
||||
blueTable = greenTable + in->greenMax + 1;
|
||||
|
||||
rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax,
|
||||
out->redShift, (out->bigEndian != in->bigEndian));
|
||||
rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax,
|
||||
out->greenShift, (out->bigEndian != in->bigEndian));
|
||||
rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax,
|
||||
out->blueShift, (out->bigEndian != in->bigEndian));
|
||||
}
|
||||
|
||||
static void
|
||||
rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
|
||||
int swap)
|
||||
{
|
||||
int i;
|
||||
int nEntries = inMax + 1;
|
||||
|
||||
for (i = 0; i < nEntries; i++) {
|
||||
table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
|
||||
#if (OUT != 8)
|
||||
if (swap) {
|
||||
table[i] = SwapOUT(table[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef OUT_T
|
||||
#undef SwapOUT
|
||||
#undef rfbInitTrueColourSingleTableOUT
|
||||
#undef rfbInitTrueColourRGBTablesOUT
|
||||
#undef rfbInitOneRGBTableOUT
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* tabletranstemplate.c - template for translation using lookup tables.
|
||||
*
|
||||
* This file shouldn't be compiled. It is included multiple times by
|
||||
* translate.c, each time with different definitions of the macros IN and OUT.
|
||||
*
|
||||
* For each pair of values IN and OUT, this file defines two functions for
|
||||
* translating a given rectangle of pixel data. One uses a single lookup
|
||||
* table, and the other uses three separate lookup tables for the red, green
|
||||
* and blue values.
|
||||
*
|
||||
* I know this code isn't nice to read because of all the macros, but
|
||||
* efficiency is important here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#if !defined(BPP)
|
||||
#error "This file shouldn't be compiled."
|
||||
#error "It is included as part of translate.c"
|
||||
#endif
|
||||
|
||||
#if BPP == 24
|
||||
|
||||
/*
|
||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
||||
* using a single lookup table.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithSingleTable24to24 (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
uint8_t *ip = (uint8_t *)iptr;
|
||||
uint8_t *op = (uint8_t *)optr;
|
||||
int ipextra = bytesBetweenInputLines - width * 3;
|
||||
uint8_t *opLineEnd;
|
||||
uint8_t *t = (uint8_t *)table;
|
||||
int shift = rfbEndianTest?0:8;
|
||||
uint8_t c;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op + width*3;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
*(uint32_t*)op = t[((*(uint32_t *)ip)>>shift)&0x00ffffff];
|
||||
if(!rfbEndianTest)
|
||||
memmove(op,op+1,3);
|
||||
if (out->bigEndian != in->bigEndian) {
|
||||
c = op[0]; op[0] = op[2]; op[2] = c;
|
||||
}
|
||||
op += 3;
|
||||
ip += 3;
|
||||
}
|
||||
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
||||
* using three separate lookup tables for the red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithRGBTables24to24 (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
uint8_t *ip = (uint8_t *)iptr;
|
||||
uint8_t *op = (uint8_t *)optr;
|
||||
int ipextra = bytesBetweenInputLines - width*3;
|
||||
uint8_t *opLineEnd;
|
||||
uint8_t *redTable = (uint8_t *)table;
|
||||
uint8_t *greenTable = redTable + 3*(in->redMax + 1);
|
||||
uint8_t *blueTable = greenTable + 3*(in->greenMax + 1);
|
||||
uint32_t outValue,inValue;
|
||||
int shift = rfbEndianTest?0:8;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op+3*width;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff;
|
||||
outValue = (redTable[(inValue >> in->redShift) & in->redMax] |
|
||||
greenTable[(inValue >> in->greenShift) & in->greenMax] |
|
||||
blueTable[(inValue >> in->blueShift) & in->blueMax]);
|
||||
memcpy(op,&outValue,3);
|
||||
op += 3;
|
||||
ip+=3;
|
||||
}
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define IN_T CONCAT3E(uint,BPP,_t)
|
||||
#define OUT_T CONCAT3E(uint,BPP,_t)
|
||||
#define rfbTranslateWithSingleTable24toOUT \
|
||||
CONCAT4E(rfbTranslateWithSingleTable,24,to,BPP)
|
||||
#define rfbTranslateWithSingleTableINto24 \
|
||||
CONCAT4E(rfbTranslateWithSingleTable,BPP,to,24)
|
||||
#define rfbTranslateWithRGBTables24toOUT \
|
||||
CONCAT4E(rfbTranslateWithRGBTables,24,to,BPP)
|
||||
#define rfbTranslateWithRGBTablesINto24 \
|
||||
CONCAT4E(rfbTranslateWithRGBTables,BPP,to,24)
|
||||
|
||||
/*
|
||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
||||
* using a single lookup table.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithSingleTable24toOUT (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
uint8_t *ip = (uint8_t *)iptr;
|
||||
OUT_T *op = (OUT_T *)optr;
|
||||
int ipextra = bytesBetweenInputLines - width*3;
|
||||
OUT_T *opLineEnd;
|
||||
OUT_T *t = (OUT_T *)table;
|
||||
int shift = rfbEndianTest?0:8;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op + width;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
*(op++) = t[((*(uint32_t *)ip)>>shift)&0x00ffffff];
|
||||
ip+=3;
|
||||
}
|
||||
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
||||
* using three separate lookup tables for the red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithRGBTables24toOUT (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
uint8_t *ip = (uint8_t *)iptr;
|
||||
OUT_T *op = (OUT_T *)optr;
|
||||
int ipextra = bytesBetweenInputLines - width*3;
|
||||
OUT_T *opLineEnd;
|
||||
OUT_T *redTable = (OUT_T *)table;
|
||||
OUT_T *greenTable = redTable + in->redMax + 1;
|
||||
OUT_T *blueTable = greenTable + in->greenMax + 1;
|
||||
uint32_t inValue;
|
||||
int shift = rfbEndianTest?0:8;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = &op[width];
|
||||
|
||||
while (op < opLineEnd) {
|
||||
inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff;
|
||||
*(op++) = (redTable[(inValue >> in->redShift) & in->redMax] |
|
||||
greenTable[(inValue >> in->greenShift) & in->greenMax] |
|
||||
blueTable[(inValue >> in->blueShift) & in->blueMax]);
|
||||
ip+=3;
|
||||
}
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbTranslateWithSingleTableINto24 translates a rectangle of pixel data
|
||||
* using a single lookup table.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithSingleTableINto24 (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
IN_T *ip = (IN_T *)iptr;
|
||||
uint8_t *op = (uint8_t *)optr;
|
||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
||||
uint8_t *opLineEnd;
|
||||
uint8_t *t = (uint8_t *)table;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op + width * 3;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
memcpy(op,&t[3*(*(ip++))],3);
|
||||
op += 3;
|
||||
}
|
||||
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbTranslateWithRGBTablesINto24 translates a rectangle of pixel data
|
||||
* using three separate lookup tables for the red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithRGBTablesINto24 (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
IN_T *ip = (IN_T *)iptr;
|
||||
uint8_t *op = (uint8_t *)optr;
|
||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
||||
uint8_t *opLineEnd;
|
||||
uint8_t *redTable = (uint8_t *)table;
|
||||
uint8_t *greenTable = redTable + 3*(in->redMax + 1);
|
||||
uint8_t *blueTable = greenTable + 3*(in->greenMax + 1);
|
||||
uint32_t outValue;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op+3*width;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
outValue = (redTable[(*ip >> in->redShift) & in->redMax] |
|
||||
greenTable[(*ip >> in->greenShift) & in->greenMax] |
|
||||
blueTable[(*ip >> in->blueShift) & in->blueMax]);
|
||||
memcpy(op,&outValue,3);
|
||||
op += 3;
|
||||
ip++;
|
||||
}
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
#undef IN_T
|
||||
#undef OUT_T
|
||||
#undef rfbTranslateWithSingleTable24toOUT
|
||||
#undef rfbTranslateWithRGBTables24toOUT
|
||||
#undef rfbTranslateWithSingleTableINto24
|
||||
#undef rfbTranslateWithRGBTablesINto24
|
||||
|
||||
#endif
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* tabletranstemplate.c - template for translation using lookup tables.
|
||||
*
|
||||
* This file shouldn't be compiled. It is included multiple times by
|
||||
* translate.c, each time with different definitions of the macros IN and OUT.
|
||||
*
|
||||
* For each pair of values IN and OUT, this file defines two functions for
|
||||
* translating a given rectangle of pixel data. One uses a single lookup
|
||||
* table, and the other uses three separate lookup tables for the red, green
|
||||
* and blue values.
|
||||
*
|
||||
* I know this code isn't nice to read because of all the macros, but
|
||||
* efficiency is important here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#if !defined(IN) || !defined(OUT)
|
||||
#error "This file shouldn't be compiled."
|
||||
#error "It is included as part of translate.c"
|
||||
#endif
|
||||
|
||||
#define IN_T CONCAT3E(uint,IN,_t)
|
||||
#define OUT_T CONCAT3E(uint,OUT,_t)
|
||||
#define rfbTranslateWithSingleTableINtoOUT \
|
||||
CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT)
|
||||
#define rfbTranslateWithRGBTablesINtoOUT \
|
||||
CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT)
|
||||
|
||||
/*
|
||||
* rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
|
||||
* using a single lookup table.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithSingleTableINtoOUT (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
IN_T *ip = (IN_T *)iptr;
|
||||
OUT_T *op = (OUT_T *)optr;
|
||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
||||
OUT_T *opLineEnd;
|
||||
OUT_T *t = (OUT_T *)table;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = op + width;
|
||||
|
||||
while (op < opLineEnd) {
|
||||
*(op++) = t[*(ip++)];
|
||||
}
|
||||
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
|
||||
* using three separate lookup tables for the red, green and blue values.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbTranslateWithRGBTablesINtoOUT (char *table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,
|
||||
char *iptr, char *optr,
|
||||
int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
IN_T *ip = (IN_T *)iptr;
|
||||
OUT_T *op = (OUT_T *)optr;
|
||||
int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width;
|
||||
OUT_T *opLineEnd;
|
||||
OUT_T *redTable = (OUT_T *)table;
|
||||
OUT_T *greenTable = redTable + in->redMax + 1;
|
||||
OUT_T *blueTable = greenTable + in->greenMax + 1;
|
||||
|
||||
while (height > 0) {
|
||||
opLineEnd = &op[width];
|
||||
|
||||
while (op < opLineEnd) {
|
||||
*(op++) = (redTable[(*ip >> in->redShift) & in->redMax] |
|
||||
greenTable[(*ip >> in->greenShift) & in->greenMax] |
|
||||
blueTable[(*ip >> in->blueShift) & in->blueMax]);
|
||||
ip++;
|
||||
}
|
||||
ip += ipextra;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
#undef IN_T
|
||||
#undef OUT_T
|
||||
#undef rfbTranslateWithSingleTableINtoOUT
|
||||
#undef rfbTranslateWithRGBTablesINtoOUT
|
1824
libvncserver/tight.c
1824
libvncserver/tight.c
File diff suppressed because it is too large
Load Diff
|
@ -1,477 +0,0 @@
|
|||
/*
|
||||
* translate.c - translate between different pixel formats
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
|
||||
static void PrintPixelFormat(rfbPixelFormat *pf);
|
||||
static rfbBool rfbSetClientColourMapBGR233(rfbClientPtr cl);
|
||||
|
||||
rfbBool rfbEconomicTranslate = FALSE;
|
||||
|
||||
/*
|
||||
* Some standard pixel formats.
|
||||
*/
|
||||
|
||||
static const rfbPixelFormat BGR233Format = {
|
||||
8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Macro to compare pixel formats.
|
||||
*/
|
||||
|
||||
#define PF_EQ(x,y) \
|
||||
((x.bitsPerPixel == y.bitsPerPixel) && \
|
||||
(x.depth == y.depth) && \
|
||||
((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \
|
||||
(x.trueColour == y.trueColour) && \
|
||||
(!x.trueColour || ((x.redMax == y.redMax) && \
|
||||
(x.greenMax == y.greenMax) && \
|
||||
(x.blueMax == y.blueMax) && \
|
||||
(x.redShift == y.redShift) && \
|
||||
(x.greenShift == y.greenShift) && \
|
||||
(x.blueShift == y.blueShift))))
|
||||
|
||||
#define CONCAT2(a,b) a##b
|
||||
#define CONCAT2E(a,b) CONCAT2(a,b)
|
||||
#define CONCAT3(a,b,c) a##b##c
|
||||
#define CONCAT3E(a,b,c) CONCAT3(a,b,c)
|
||||
#define CONCAT4(a,b,c,d) a##b##c##d
|
||||
#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)
|
||||
|
||||
#undef OUT
|
||||
#undef IN
|
||||
|
||||
#define OUT 8
|
||||
#include "tableinitcmtemplate.c"
|
||||
#include "tableinittctemplate.c"
|
||||
#define IN 8
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 16
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 32
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
#define OUT 16
|
||||
#include "tableinitcmtemplate.c"
|
||||
#include "tableinittctemplate.c"
|
||||
#define IN 8
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 16
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 32
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
#define OUT 32
|
||||
#include "tableinitcmtemplate.c"
|
||||
#include "tableinittctemplate.c"
|
||||
#define IN 8
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 16
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#define IN 32
|
||||
#include "tabletranstemplate.c"
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
#define COUNT_OFFSETS 4
|
||||
#define BPP2OFFSET(bpp) ((bpp)/8-1)
|
||||
#include "tableinit24.c"
|
||||
#define BPP 8
|
||||
#include "tabletrans24template.c"
|
||||
#undef BPP
|
||||
#define BPP 16
|
||||
#include "tabletrans24template.c"
|
||||
#undef BPP
|
||||
#define BPP 24
|
||||
#include "tabletrans24template.c"
|
||||
#undef BPP
|
||||
#define BPP 32
|
||||
#include "tabletrans24template.c"
|
||||
#undef BPP
|
||||
#else
|
||||
#define COUNT_OFFSETS 3
|
||||
#define BPP2OFFSET(bpp) ((int)(bpp)/16)
|
||||
#endif
|
||||
|
||||
typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out,rfbColourMap* cm);
|
||||
typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in,
|
||||
rfbPixelFormat *out);
|
||||
|
||||
static rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = {
|
||||
rfbInitColourMapSingleTable8,
|
||||
rfbInitColourMapSingleTable16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbInitColourMapSingleTable24,
|
||||
#endif
|
||||
rfbInitColourMapSingleTable32
|
||||
};
|
||||
|
||||
static rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = {
|
||||
rfbInitTrueColourSingleTable8,
|
||||
rfbInitTrueColourSingleTable16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbInitTrueColourSingleTable24,
|
||||
#endif
|
||||
rfbInitTrueColourSingleTable32
|
||||
};
|
||||
|
||||
static rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = {
|
||||
rfbInitTrueColourRGBTables8,
|
||||
rfbInitTrueColourRGBTables16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbInitTrueColourRGBTables24,
|
||||
#endif
|
||||
rfbInitTrueColourRGBTables32
|
||||
};
|
||||
|
||||
static rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
|
||||
{ rfbTranslateWithSingleTable8to8,
|
||||
rfbTranslateWithSingleTable8to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithSingleTable8to24,
|
||||
#endif
|
||||
rfbTranslateWithSingleTable8to32 },
|
||||
{ rfbTranslateWithSingleTable16to8,
|
||||
rfbTranslateWithSingleTable16to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithSingleTable16to24,
|
||||
#endif
|
||||
rfbTranslateWithSingleTable16to32 },
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
{ rfbTranslateWithSingleTable24to8,
|
||||
rfbTranslateWithSingleTable24to16,
|
||||
rfbTranslateWithSingleTable24to24,
|
||||
rfbTranslateWithSingleTable24to32 },
|
||||
#endif
|
||||
{ rfbTranslateWithSingleTable32to8,
|
||||
rfbTranslateWithSingleTable32to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithSingleTable32to24,
|
||||
#endif
|
||||
rfbTranslateWithSingleTable32to32 }
|
||||
};
|
||||
|
||||
static rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
|
||||
{ rfbTranslateWithRGBTables8to8,
|
||||
rfbTranslateWithRGBTables8to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithRGBTables8to24,
|
||||
#endif
|
||||
rfbTranslateWithRGBTables8to32 },
|
||||
{ rfbTranslateWithRGBTables16to8,
|
||||
rfbTranslateWithRGBTables16to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithRGBTables16to24,
|
||||
#endif
|
||||
rfbTranslateWithRGBTables16to32 },
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
{ rfbTranslateWithRGBTables24to8,
|
||||
rfbTranslateWithRGBTables24to16,
|
||||
rfbTranslateWithRGBTables24to24,
|
||||
rfbTranslateWithRGBTables24to32 },
|
||||
#endif
|
||||
{ rfbTranslateWithRGBTables32to8,
|
||||
rfbTranslateWithRGBTables32to16,
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
rfbTranslateWithRGBTables32to24,
|
||||
#endif
|
||||
rfbTranslateWithRGBTables32to32 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbTranslateNone is used when no translation is required.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
|
||||
char *iptr, char *optr, int bytesBetweenInputLines,
|
||||
int width, int height)
|
||||
{
|
||||
int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
|
||||
|
||||
while (height > 0) {
|
||||
memcpy(optr, iptr, bytesPerOutputLine);
|
||||
iptr += bytesBetweenInputLines;
|
||||
optr += bytesPerOutputLine;
|
||||
height--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetTranslateFunction sets the translation function.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSetTranslateFunction(rfbClientPtr cl)
|
||||
{
|
||||
rfbLog("Pixel format for client %s:\n",cl->host);
|
||||
PrintPixelFormat(&cl->format);
|
||||
|
||||
/*
|
||||
* Check that bits per pixel values are valid
|
||||
*/
|
||||
|
||||
if ((cl->screen->serverFormat.bitsPerPixel != 8) &&
|
||||
(cl->screen->serverFormat.bitsPerPixel != 16) &&
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
(cl->screen->serverFormat.bitsPerPixel != 24) &&
|
||||
#endif
|
||||
(cl->screen->serverFormat.bitsPerPixel != 32))
|
||||
{
|
||||
rfbErr("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
|
||||
"rfbSetTranslateFunction",
|
||||
cl->screen->serverFormat.bitsPerPixel);
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((cl->format.bitsPerPixel != 8) &&
|
||||
(cl->format.bitsPerPixel != 16) &&
|
||||
#ifdef LIBVNCSERVER_ALLOW24BPP
|
||||
(cl->format.bitsPerPixel != 24) &&
|
||||
#endif
|
||||
(cl->format.bitsPerPixel != 32))
|
||||
{
|
||||
rfbErr("%s: client bits per pixel not 8, 16 or 32\n",
|
||||
"rfbSetTranslateFunction");
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) {
|
||||
rfbErr("rfbSetTranslateFunction: client has colour map "
|
||||
"but %d-bit - can only cope with 8-bit colour maps\n",
|
||||
cl->format.bitsPerPixel);
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* bpp is valid, now work out how to translate
|
||||
*/
|
||||
|
||||
if (!cl->format.trueColour) {
|
||||
/*
|
||||
* truecolour -> colour map
|
||||
*
|
||||
* Set client's colour map to BGR233, then effectively it's
|
||||
* truecolour as well
|
||||
*/
|
||||
|
||||
if (!rfbSetClientColourMapBGR233(cl))
|
||||
return FALSE;
|
||||
|
||||
cl->format = BGR233Format;
|
||||
}
|
||||
|
||||
/* truecolour -> truecolour */
|
||||
|
||||
if (PF_EQ(cl->format,cl->screen->serverFormat)) {
|
||||
|
||||
/* client & server the same */
|
||||
|
||||
rfbLog("no translation needed\n");
|
||||
cl->translateFn = rfbTranslateNone;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((cl->screen->serverFormat.bitsPerPixel < 16) ||
|
||||
((!cl->screen->serverFormat.trueColour || !rfbEconomicTranslate) &&
|
||||
(cl->screen->serverFormat.bitsPerPixel == 16))) {
|
||||
|
||||
/* we can use a single lookup table for <= 16 bpp */
|
||||
|
||||
cl->translateFn = rfbTranslateWithSingleTableFns
|
||||
[BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)]
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)];
|
||||
|
||||
if(cl->screen->serverFormat.trueColour)
|
||||
(*rfbInitTrueColourSingleTableFns
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat), &cl->format);
|
||||
else
|
||||
(*rfbInitColourMapSingleTableFns
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat), &cl->format,&cl->screen->colourMap);
|
||||
|
||||
} else {
|
||||
|
||||
/* otherwise we use three separate tables for red, green and blue */
|
||||
|
||||
cl->translateFn = rfbTranslateWithRGBTablesFns
|
||||
[BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)]
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)];
|
||||
|
||||
(*rfbInitTrueColourRGBTablesFns
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat), &cl->format);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetClientColourMapBGR233 sets the client's colour map so that it's
|
||||
* just like an 8-bit BGR233 true colour client.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
rfbSetClientColourMapBGR233(rfbClientPtr cl)
|
||||
{
|
||||
char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
|
||||
rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
|
||||
uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
|
||||
int i, len;
|
||||
int r, g, b;
|
||||
|
||||
if (cl->format.bitsPerPixel != 8 ) {
|
||||
rfbErr("%s: client not 8 bits per pixel\n",
|
||||
"rfbSetClientColourMapBGR233");
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
scme->type = rfbSetColourMapEntries;
|
||||
|
||||
scme->firstColour = Swap16IfLE(0);
|
||||
scme->nColours = Swap16IfLE(256);
|
||||
|
||||
len = sz_rfbSetColourMapEntriesMsg;
|
||||
|
||||
i = 0;
|
||||
|
||||
for (b = 0; b < 4; b++) {
|
||||
for (g = 0; g < 8; g++) {
|
||||
for (r = 0; r < 8; r++) {
|
||||
rgb[i++] = Swap16IfLE(r * 65535 / 7);
|
||||
rgb[i++] = Swap16IfLE(g * 65535 / 7);
|
||||
rgb[i++] = Swap16IfLE(b * 65535 / 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len += 256 * 3 * 2;
|
||||
|
||||
if (rfbWriteExact(cl, buf, len) < 0) {
|
||||
rfbLogPerror("rfbSetClientColourMapBGR233: write");
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* this function is not called very often, so it needn't be
|
||||
efficient. */
|
||||
|
||||
/*
|
||||
* rfbSetClientColourMap is called to set the client's colour map. If the
|
||||
* client is a true colour client, we simply update our own translation table
|
||||
* and mark the whole screen as having been modified.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours)
|
||||
{
|
||||
if (cl->screen->serverFormat.trueColour || !cl->readyForSetColourMapEntries) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (nColours == 0) {
|
||||
nColours = cl->screen->colourMap.count;
|
||||
}
|
||||
|
||||
if (cl->format.trueColour) {
|
||||
LOCK(cl->updateMutex);
|
||||
(*rfbInitColourMapSingleTableFns
|
||||
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
|
||||
&cl->screen->serverFormat, &cl->format,&cl->screen->colourMap);
|
||||
|
||||
sraRgnDestroy(cl->modifiedRegion);
|
||||
cl->modifiedRegion =
|
||||
sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
|
||||
UNLOCK(cl->updateMutex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return rfbSendSetColourMapEntries(cl, firstColour, nColours);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetClientColourMaps sets the colour map for each RFB client.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours)
|
||||
{
|
||||
rfbClientIteratorPtr i;
|
||||
rfbClientPtr cl;
|
||||
|
||||
i = rfbGetClientIterator(rfbScreen);
|
||||
while((cl = rfbClientIteratorNext(i)))
|
||||
rfbSetClientColourMap(cl, firstColour, nColours);
|
||||
rfbReleaseClientIterator(i);
|
||||
}
|
||||
|
||||
static void
|
||||
PrintPixelFormat(rfbPixelFormat *pf)
|
||||
{
|
||||
if (pf->bitsPerPixel == 1) {
|
||||
rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n",
|
||||
(pf->bigEndian ? "most" : "least"));
|
||||
} else {
|
||||
rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth,
|
||||
((pf->bitsPerPixel == 8) ? ""
|
||||
: (pf->bigEndian ? ", big endian" : ", little endian")));
|
||||
if (pf->trueColour) {
|
||||
rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n",
|
||||
pf->redMax, pf->greenMax, pf->blueMax,
|
||||
pf->redShift, pf->greenShift, pf->blueShift);
|
||||
} else {
|
||||
rfbLog(" uses a colour map (not true colour).\n");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
* ultra.c
|
||||
*
|
||||
* Routines to implement ultra based encoding (minilzo).
|
||||
* ultrazip supports packed rectangles if the rects are tiny...
|
||||
* This improves performance as lzo has more data to work with at once
|
||||
* This is 'UltraZip' and is currently not implemented.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "minilzo.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the lzo (deflated) encoding version.
|
||||
* If the lzo compressed/encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
|
||||
* rectangle encoding.
|
||||
*/
|
||||
|
||||
#define MAX_WRKMEM ((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)
|
||||
|
||||
|
||||
void rfbFreeUltraData(rfbClientPtr cl) {
|
||||
if (cl->compStreamInitedLZO) {
|
||||
free(cl->lzoWrkMem);
|
||||
cl->compStreamInitedLZO=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static rfbBool
|
||||
rfbSendOneRectEncodingUltra(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbZlibHeader hdr;
|
||||
int deflateResult;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize;
|
||||
lzo_uint maxCompSize;
|
||||
|
||||
maxRawSize = (w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* lzo requires output buffer to be slightly larger than the input
|
||||
* buffer, in the worst case.
|
||||
*/
|
||||
maxCompSize = (maxRawSize + maxRawSize / 16 + 64 + 3);
|
||||
|
||||
if (cl->afterEncBufSize < (int)maxCompSize) {
|
||||
cl->afterEncBufSize = maxCompSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert pixel data to client format.
|
||||
*/
|
||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
if ( cl->compStreamInitedLZO == FALSE ) {
|
||||
cl->compStreamInitedLZO = TRUE;
|
||||
/* Work-memory needed for compression. Allocate memory in units
|
||||
* of `lzo_align_t' (instead of `char') to make sure it is properly aligned.
|
||||
*/
|
||||
cl->lzoWrkMem = malloc(sizeof(lzo_align_t) * (((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)));
|
||||
}
|
||||
|
||||
/* Perform the compression here. */
|
||||
deflateResult = lzo1x_1_compress((unsigned char *)cl->beforeEncBuf, (lzo_uint)(w * h * (cl->format.bitsPerPixel / 8)), (unsigned char *)cl->afterEncBuf, &maxCompSize, cl->lzoWrkMem);
|
||||
/* maxCompSize now contains the compressed size */
|
||||
|
||||
/* Find the total size of the resulting compressed data. */
|
||||
cl->afterEncBufLen = maxCompSize;
|
||||
|
||||
if ( deflateResult != LZO_E_OK ) {
|
||||
rfbErr("lzo deflation error: %d\n", deflateResult);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update statics */
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingUltra, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + cl->afterEncBufLen, maxRawSize);
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingUltra);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nBytes = Swap32IfLE(cl->afterEncBufLen);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
|
||||
cl->ublen += sz_rfbZlibHeader;
|
||||
|
||||
/* We might want to try sending the data directly... */
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingUltra - send a given rectangle using one or more
|
||||
* LZO encoding rectangles.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingUltra(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
int maxLines;
|
||||
int linesRemaining;
|
||||
rfbRectangle partialRect;
|
||||
|
||||
partialRect.x = x;
|
||||
partialRect.y = y;
|
||||
partialRect.w = w;
|
||||
partialRect.h = h;
|
||||
|
||||
/* Determine maximum pixel/scan lines allowed per rectangle. */
|
||||
maxLines = ( ULTRA_MAX_SIZE(w) / w );
|
||||
|
||||
/* Initialize number of scan lines left to do. */
|
||||
linesRemaining = h;
|
||||
|
||||
/* Loop until all work is done. */
|
||||
while ( linesRemaining > 0 ) {
|
||||
|
||||
int linesToComp;
|
||||
|
||||
if ( maxLines < linesRemaining )
|
||||
linesToComp = maxLines;
|
||||
else
|
||||
linesToComp = linesRemaining;
|
||||
|
||||
partialRect.h = linesToComp;
|
||||
|
||||
/* Encode (compress) and send the next rectangle. */
|
||||
if ( ! rfbSendOneRectEncodingUltra( cl,
|
||||
partialRect.x,
|
||||
partialRect.y,
|
||||
partialRect.w,
|
||||
partialRect.h )) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Technically, flushing the buffer here is not extrememly
|
||||
* efficient. However, this improves the overall throughput
|
||||
* of the system over very slow networks. By flushing
|
||||
* the buffer with every maximum size lzo rectangle, we
|
||||
* improve the pipelining usage of the server CPU, network,
|
||||
* and viewer CPU components. Insuring that these components
|
||||
* are working in parallel actually improves the performance
|
||||
* seen by the user.
|
||||
* Since, lzo is most useful for slow networks, this flush
|
||||
* is appropriate for the desired behavior of the lzo encoding.
|
||||
*/
|
||||
if (( cl->ublen > 0 ) &&
|
||||
( linesToComp == maxLines )) {
|
||||
if (!rfbSendUpdateBuf(cl)) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update remaining and incremental rectangle location. */
|
||||
linesRemaining -= linesToComp;
|
||||
partialRect.y += linesToComp;
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* vncauth.c - Functions for VNC password management and authentication.
|
||||
*/
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define _BSD_SOURCE
|
||||
#define _POSIX_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "rfb/rfbproto.h"
|
||||
#include "d3des.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef LIBVNCSERVER_HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define srandom srand
|
||||
#define random rand
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* libvncclient does not need this */
|
||||
#ifndef rfbEncryptBytes
|
||||
|
||||
/*
|
||||
* We use a fixed key to store passwords, since we assume that our local
|
||||
* file system is secure but nonetheless don't want to store passwords
|
||||
* as plaintext.
|
||||
*/
|
||||
|
||||
static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
|
||||
|
||||
|
||||
/*
|
||||
* Encrypt a password and store it in a file. Returns 0 if successful,
|
||||
* 1 if the file could not be written.
|
||||
*/
|
||||
|
||||
int
|
||||
rfbEncryptAndStorePasswd(char *passwd, char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int i;
|
||||
unsigned char encryptedPasswd[8];
|
||||
|
||||
if ((fp = fopen(fname,"w")) == NULL) return 1;
|
||||
|
||||
/* windows security sux */
|
||||
#ifndef WIN32
|
||||
fchmod(fileno(fp), S_IRUSR|S_IWUSR);
|
||||
#endif
|
||||
|
||||
/* pad password with nulls */
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < strlen(passwd)) {
|
||||
encryptedPasswd[i] = passwd[i];
|
||||
} else {
|
||||
encryptedPasswd[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do encryption in-place - this way we overwrite our copy of the plaintext
|
||||
password */
|
||||
|
||||
rfbDesKey(fixedkey, EN0);
|
||||
rfbDes(encryptedPasswd, encryptedPasswd);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
putc(encryptedPasswd[i], fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decrypt a password from a file. Returns a pointer to a newly allocated
|
||||
* string containing the password or a null pointer if the password could
|
||||
* not be retrieved for some reason.
|
||||
*/
|
||||
|
||||
char *
|
||||
rfbDecryptPasswdFromFile(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
int i, ch;
|
||||
unsigned char *passwd = (unsigned char *)malloc(9);
|
||||
|
||||
if ((fp = fopen(fname,"r")) == NULL) {
|
||||
free(passwd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
ch = getc(fp);
|
||||
if (ch == EOF) {
|
||||
fclose(fp);
|
||||
free(passwd);
|
||||
return NULL;
|
||||
}
|
||||
passwd[i] = ch;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
rfbDesKey(fixedkey, DE1);
|
||||
rfbDes(passwd, passwd);
|
||||
|
||||
passwd[8] = 0;
|
||||
|
||||
return (char *)passwd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate CHALLENGESIZE random bytes for use in challenge-response
|
||||
* authentication.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbRandomBytes(unsigned char *bytes)
|
||||
{
|
||||
int i;
|
||||
static rfbBool s_srandom_called = FALSE;
|
||||
|
||||
if (!s_srandom_called) {
|
||||
srandom((unsigned int)time(NULL) ^ (unsigned int)getpid());
|
||||
s_srandom_called = TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < CHALLENGESIZE; i++) {
|
||||
bytes[i] = (unsigned char)(random() & 255);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Encrypt CHALLENGESIZE bytes in memory using a password.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbEncryptBytes(unsigned char *bytes, char *passwd)
|
||||
{
|
||||
unsigned char key[8];
|
||||
unsigned int i;
|
||||
|
||||
/* key is simply password padded with nulls */
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < strlen(passwd)) {
|
||||
key[i] = passwd[i];
|
||||
} else {
|
||||
key[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rfbDesKey(key, EN0);
|
||||
|
||||
for (i = 0; i < CHALLENGESIZE; i += 8) {
|
||||
rfbDes(bytes+i, bytes+i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
|
||||
int i, j;
|
||||
rfbDesKey(key, EN0);
|
||||
for (i = 0; i< 8; i++)
|
||||
where[i] ^= key[i];
|
||||
rfbDes(where, where);
|
||||
for (i = 8; i < length; i += 8) {
|
||||
for (j = 0; j < 8; j++)
|
||||
where[i + j] ^= where[i + j - 8];
|
||||
rfbDes(where + i, where + i);
|
||||
}
|
||||
}
|
|
@ -1,331 +0,0 @@
|
|||
/*
|
||||
* zlib.c
|
||||
*
|
||||
* Routines to implement zlib based encoding (deflate).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*
|
||||
* For the latest source code, please check:
|
||||
*
|
||||
* http://www.developVNC.org/
|
||||
*
|
||||
* or send email to feedback@developvnc.org.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* zlibBeforeBuf contains pixel data in the client's format.
|
||||
* zlibAfterBuf contains the zlib (deflated) encoding version.
|
||||
* If the zlib compressed/encoded version is
|
||||
* larger than the raw data or if it exceeds zlibAfterBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Out of lazyiness, we use thread local storage for zlib as we did for
|
||||
* tight. N.B. ZRLE does it the traditional way with per-client storage
|
||||
* (and so at least ZRLE will work threaded on older systems.)
|
||||
*/
|
||||
#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__)
|
||||
#define TLS __thread
|
||||
#endif
|
||||
#ifndef TLS
|
||||
#define TLS
|
||||
#endif
|
||||
|
||||
static TLS int zlibBeforeBufSize = 0;
|
||||
static TLS char *zlibBeforeBuf = NULL;
|
||||
|
||||
static TLS int zlibAfterBufSize = 0;
|
||||
static TLS char *zlibAfterBuf = NULL;
|
||||
static TLS int zlibAfterBufLen = 0;
|
||||
|
||||
void rfbZlibCleanup(rfbScreenInfoPtr screen)
|
||||
{
|
||||
if (zlibBeforeBufSize) {
|
||||
free(zlibBeforeBuf);
|
||||
zlibBeforeBufSize=0;
|
||||
}
|
||||
if (zlibAfterBufSize) {
|
||||
zlibAfterBufSize=0;
|
||||
free(zlibAfterBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
|
||||
* rectangle encoding.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
rfbSendOneRectEncodingZlib(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbZlibHeader hdr;
|
||||
int deflateResult;
|
||||
int previousOut;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize;
|
||||
int maxCompSize;
|
||||
|
||||
maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (zlibBeforeBufSize < maxRawSize) {
|
||||
zlibBeforeBufSize = maxRawSize;
|
||||
if (zlibBeforeBuf == NULL)
|
||||
zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize);
|
||||
else
|
||||
zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize);
|
||||
}
|
||||
|
||||
/* zlib compression is not useful for very small data sets.
|
||||
* So, we just send these raw without any compression.
|
||||
*/
|
||||
if (( w * h * (cl->scaledScreen->bitsPerPixel / 8)) <
|
||||
VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) {
|
||||
|
||||
int result;
|
||||
|
||||
/* The translation function (used also by the in raw encoding)
|
||||
* requires 4/2/1 byte alignment in the output buffer (which is
|
||||
* updateBuf for the raw encoding) based on the bitsPerPixel of
|
||||
* the viewer/client. This prevents SIGBUS errors on some
|
||||
* architectures like SPARC, PARISC...
|
||||
*/
|
||||
if (( cl->format.bitsPerPixel > 8 ) &&
|
||||
( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* zlib requires output buffer to be slightly larger than the input
|
||||
* buffer, in the worst case.
|
||||
*/
|
||||
maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12;
|
||||
|
||||
if (zlibAfterBufSize < maxCompSize) {
|
||||
zlibAfterBufSize = maxCompSize;
|
||||
if (zlibAfterBuf == NULL)
|
||||
zlibAfterBuf = (char *)malloc(zlibAfterBufSize);
|
||||
else
|
||||
zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert pixel data to client format.
|
||||
*/
|
||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,
|
||||
&cl->format, fbptr, zlibBeforeBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
cl->compStream.next_in = ( Bytef * )zlibBeforeBuf;
|
||||
cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8);
|
||||
cl->compStream.next_out = ( Bytef * )zlibAfterBuf;
|
||||
cl->compStream.avail_out = maxCompSize;
|
||||
cl->compStream.data_type = Z_BINARY;
|
||||
|
||||
/* Initialize the deflation state. */
|
||||
if ( cl->compStreamInited == FALSE ) {
|
||||
|
||||
cl->compStream.total_in = 0;
|
||||
cl->compStream.total_out = 0;
|
||||
cl->compStream.zalloc = Z_NULL;
|
||||
cl->compStream.zfree = Z_NULL;
|
||||
cl->compStream.opaque = Z_NULL;
|
||||
|
||||
deflateInit2( &(cl->compStream),
|
||||
cl->zlibCompressLevel,
|
||||
Z_DEFLATED,
|
||||
MAX_WBITS,
|
||||
MAX_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY );
|
||||
/* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */
|
||||
/* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */
|
||||
cl->compStreamInited = TRUE;
|
||||
|
||||
}
|
||||
|
||||
previousOut = cl->compStream.total_out;
|
||||
|
||||
/* Perform the compression here. */
|
||||
deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH );
|
||||
|
||||
/* Find the total size of the resulting compressed data. */
|
||||
zlibAfterBufLen = cl->compStream.total_out - previousOut;
|
||||
|
||||
if ( deflateResult != Z_OK ) {
|
||||
rfbErr("zlib deflation error: %s\n", cl->compStream.msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Note that it is not possible to switch zlib parameters based on
|
||||
* the results of the compression pass. The reason is
|
||||
* that we rely on the compressor and decompressor states being
|
||||
* in sync. Compressing and then discarding the results would
|
||||
* cause lose of synchronization.
|
||||
*/
|
||||
|
||||
/* Update statics */
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingZlib, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + zlibAfterBufLen,
|
||||
+ w * (cl->format.bitsPerPixel / 8) * h);
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingZlib);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nBytes = Swap32IfLE(zlibAfterBufLen);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
|
||||
cl->ublen += sz_rfbZlibHeader;
|
||||
|
||||
for (i = 0; i < zlibAfterBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > zlibAfterBufLen) {
|
||||
bytesToCopy = zlibAfterBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingZlib - send a given rectangle using one or more
|
||||
* Zlib encoding rectangles.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingZlib(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
int maxLines;
|
||||
int linesRemaining;
|
||||
rfbRectangle partialRect;
|
||||
|
||||
partialRect.x = x;
|
||||
partialRect.y = y;
|
||||
partialRect.w = w;
|
||||
partialRect.h = h;
|
||||
|
||||
/* Determine maximum pixel/scan lines allowed per rectangle. */
|
||||
maxLines = ( ZLIB_MAX_SIZE(w) / w );
|
||||
|
||||
/* Initialize number of scan lines left to do. */
|
||||
linesRemaining = h;
|
||||
|
||||
/* Loop until all work is done. */
|
||||
while ( linesRemaining > 0 ) {
|
||||
|
||||
int linesToComp;
|
||||
|
||||
if ( maxLines < linesRemaining )
|
||||
linesToComp = maxLines;
|
||||
else
|
||||
linesToComp = linesRemaining;
|
||||
|
||||
partialRect.h = linesToComp;
|
||||
|
||||
/* Encode (compress) and send the next rectangle. */
|
||||
if ( ! rfbSendOneRectEncodingZlib( cl,
|
||||
partialRect.x,
|
||||
partialRect.y,
|
||||
partialRect.w,
|
||||
partialRect.h )) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Technically, flushing the buffer here is not extrememly
|
||||
* efficient. However, this improves the overall throughput
|
||||
* of the system over very slow networks. By flushing
|
||||
* the buffer with every maximum size zlib rectangle, we
|
||||
* improve the pipelining usage of the server CPU, network,
|
||||
* and viewer CPU components. Insuring that these components
|
||||
* are working in parallel actually improves the performance
|
||||
* seen by the user.
|
||||
* Since, zlib is most useful for slow networks, this flush
|
||||
* is appropriate for the desired behavior of the zlib encoding.
|
||||
*/
|
||||
if (( cl->ublen > 0 ) &&
|
||||
( linesToComp == maxLines )) {
|
||||
if (!rfbSendUpdateBuf(cl)) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update remaining and incremental rectangle location. */
|
||||
linesRemaining -= linesToComp;
|
||||
partialRect.y += linesToComp;
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* zrle.c
|
||||
*
|
||||
* Routines to implement Zlib Run-length Encoding (ZRLE).
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "private.h"
|
||||
#include "zrleoutstream.h"
|
||||
|
||||
|
||||
#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
|
||||
{ char *fbptr = (cl->scaledScreen->frameBuffer \
|
||||
+ (cl->scaledScreen->paddedWidthInBytes * ty) \
|
||||
+ (tx * (cl->scaledScreen->bitsPerPixel / 8))); \
|
||||
\
|
||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\
|
||||
&cl->format, fbptr, (char*)buf, \
|
||||
cl->scaledScreen->paddedWidthInBytes, tw, th); }
|
||||
|
||||
#define EXTRA_ARGS , rfbClientPtr cl
|
||||
|
||||
#define ENDIAN_LITTLE 0
|
||||
#define ENDIAN_BIG 1
|
||||
#define ENDIAN_NO 2
|
||||
#define BPP 8
|
||||
#define ZYWRLE_ENDIAN ENDIAN_NO
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef BPP
|
||||
#define BPP 15
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef BPP
|
||||
#define BPP 16
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef BPP
|
||||
#define BPP 32
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include <zrleencodetemplate.c>
|
||||
#define CPIXEL 24A
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef CPIXEL
|
||||
#define CPIXEL 24B
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include <zrleencodetemplate.c>
|
||||
#undef CPIXEL
|
||||
#undef BPP
|
||||
|
||||
|
||||
/*
|
||||
* zrleBeforeBuf contains pixel data in the client's format. It must be at
|
||||
* least one pixel bigger than the largest tile of pixel data, since the
|
||||
* ZRLE encoding algorithm writes to the position one past the end of the pixel
|
||||
* data.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
|
||||
*/
|
||||
|
||||
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
|
||||
{
|
||||
zrleOutStream* zos;
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbZRLEHeader hdr;
|
||||
int i;
|
||||
char *zrleBeforeBuf;
|
||||
|
||||
if (cl->zrleBeforeBuf == NULL) {
|
||||
cl->zrleBeforeBuf = (char *) malloc(rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4);
|
||||
}
|
||||
zrleBeforeBuf = cl->zrleBeforeBuf;
|
||||
|
||||
if (cl->preferredEncoding == rfbEncodingZYWRLE) {
|
||||
if (cl->tightQualityLevel < 0) {
|
||||
cl->zywrleLevel = 1;
|
||||
} else if (cl->tightQualityLevel < 3) {
|
||||
cl->zywrleLevel = 3;
|
||||
} else if (cl->tightQualityLevel < 6) {
|
||||
cl->zywrleLevel = 2;
|
||||
} else {
|
||||
cl->zywrleLevel = 1;
|
||||
}
|
||||
} else
|
||||
cl->zywrleLevel = 0;
|
||||
|
||||
if (!cl->zrleData)
|
||||
cl->zrleData = zrleOutStreamNew();
|
||||
zos = cl->zrleData;
|
||||
zos->in.ptr = zos->in.start;
|
||||
zos->out.ptr = zos->out.start;
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
|
||||
case 8:
|
||||
zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (cl->format.greenMax > 0x1F) {
|
||||
if (cl->format.bigEndian)
|
||||
zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
else
|
||||
zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
} else {
|
||||
if (cl->format.bigEndian)
|
||||
zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
else
|
||||
zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
break;
|
||||
|
||||
case 32: {
|
||||
rfbBool fitsInLS3Bytes
|
||||
= ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
|
||||
(cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
|
||||
(cl->format.blueMax << cl->format.blueShift) < (1<<24));
|
||||
|
||||
rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 &&
|
||||
cl->format.greenShift > 7 &&
|
||||
cl->format.blueShift > 7);
|
||||
|
||||
if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
|
||||
(fitsInMS3Bytes && cl->format.bigEndian)) {
|
||||
if (cl->format.bigEndian)
|
||||
zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
else
|
||||
zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
|
||||
(fitsInMS3Bytes && !cl->format.bigEndian)) {
|
||||
if (cl->format.bigEndian)
|
||||
zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
else
|
||||
zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
else {
|
||||
if (cl->format.bigEndian)
|
||||
zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
else
|
||||
zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
|
||||
+ w * (cl->format.bitsPerPixel / 8) * h);
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(cl->preferredEncoding);
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
|
||||
cl->ublen += sz_rfbZRLEHeader;
|
||||
|
||||
/* copy into updateBuf and send from there. Maybe should send directly? */
|
||||
|
||||
for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
|
||||
bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
|
||||
}
|
||||
|
||||
memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void rfbFreeZrleData(rfbClientPtr cl)
|
||||
{
|
||||
if (cl->zrleData) {
|
||||
zrleOutStreamFree(cl->zrleData);
|
||||
}
|
||||
cl->zrleData = NULL;
|
||||
|
||||
if (cl->zrleBeforeBuf) {
|
||||
free(cl->zrleBeforeBuf);
|
||||
}
|
||||
cl->zrleBeforeBuf = NULL;
|
||||
|
||||
if (cl->paletteHelper) {
|
||||
free(cl->paletteHelper);
|
||||
}
|
||||
cl->paletteHelper = NULL;
|
||||
}
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Before including this file, you must define a number of CPP macros.
|
||||
*
|
||||
* BPP should be 8, 16 or 32 depending on the bits per pixel.
|
||||
* GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
|
||||
* into the given buffer. EXTRA_ARGS can be defined to pass any other
|
||||
* arguments needed by GET_IMAGE_INTO_BUF.
|
||||
*
|
||||
* Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
|
||||
* bigger than the largest tile of pixel data, since the ZRLE encoding
|
||||
* algorithm writes to the position one past the end of the pixel data.
|
||||
*/
|
||||
|
||||
#include "zrleoutstream.h"
|
||||
#include "zrlepalettehelper.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
|
||||
but also expands its arguments if they are macros */
|
||||
|
||||
#ifndef __RFB_CONCAT2E
|
||||
#define __RFB_CONCAT2(a,b) a##b
|
||||
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef __RFB_CONCAT3E
|
||||
#define __RFB_CONCAT3(a,b,c) a##b##c
|
||||
#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
|
||||
#endif
|
||||
|
||||
#undef END_FIX
|
||||
#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
|
||||
# define END_FIX LE
|
||||
#elif ZYWRLE_ENDIAN == ENDIAN_BIG
|
||||
# define END_FIX BE
|
||||
#else
|
||||
# define END_FIX NE
|
||||
#endif
|
||||
|
||||
#ifdef CPIXEL
|
||||
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
|
||||
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
|
||||
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
|
||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
|
||||
#define BPPOUT 24
|
||||
#elif BPP==15
|
||||
#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
|
||||
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
|
||||
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
|
||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
|
||||
#define BPPOUT 16
|
||||
#else
|
||||
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
|
||||
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
|
||||
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
|
||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
|
||||
#define BPPOUT BPP
|
||||
#endif
|
||||
|
||||
#ifndef ZRLE_ONCE
|
||||
#define ZRLE_ONCE
|
||||
|
||||
static const int bitsPerPackedPixel[] = {
|
||||
0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
|
||||
};
|
||||
|
||||
#endif /* ZRLE_ONCE */
|
||||
|
||||
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os,
|
||||
int zywrle_level, int *zywrleBuf, void *paletteHelper);
|
||||
|
||||
#if BPP!=8
|
||||
#define ZYWRLE_ENCODE
|
||||
#include "zywrletemplate.c"
|
||||
#endif
|
||||
|
||||
static void ZRLE_ENCODE (int x, int y, int w, int h,
|
||||
zrleOutStream* os, void* buf
|
||||
EXTRA_ARGS
|
||||
)
|
||||
{
|
||||
int ty;
|
||||
for (ty = y; ty < y+h; ty += rfbZRLETileHeight) {
|
||||
int tx, th = rfbZRLETileHeight;
|
||||
if (th > y+h-ty) th = y+h-ty;
|
||||
for (tx = x; tx < x+w; tx += rfbZRLETileWidth) {
|
||||
int tw = rfbZRLETileWidth;
|
||||
if (tw > x+w-tx) tw = x+w-tx;
|
||||
|
||||
GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
|
||||
|
||||
if (cl->paletteHelper == NULL) {
|
||||
cl->paletteHelper = (void *) calloc(sizeof(zrlePaletteHelper), 1);
|
||||
}
|
||||
|
||||
ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os,
|
||||
cl->zywrleLevel, cl->zywrleBuf, cl->paletteHelper);
|
||||
}
|
||||
}
|
||||
zrleOutStreamFlush(os);
|
||||
}
|
||||
|
||||
|
||||
void ZRLE_ENCODE_TILE(PIXEL_T* data, int w, int h, zrleOutStream* os,
|
||||
int zywrle_level, int *zywrleBuf, void *paletteHelper)
|
||||
{
|
||||
/* First find the palette and the number of runs */
|
||||
|
||||
zrlePaletteHelper *ph;
|
||||
|
||||
int runs = 0;
|
||||
int singlePixels = 0;
|
||||
|
||||
rfbBool useRle;
|
||||
rfbBool usePalette;
|
||||
|
||||
int estimatedBytes;
|
||||
int plainRleBytes;
|
||||
int i;
|
||||
|
||||
PIXEL_T* ptr = data;
|
||||
PIXEL_T* end = ptr + h * w;
|
||||
*end = ~*(end-1); /* one past the end is different so the while loop ends */
|
||||
|
||||
ph = (zrlePaletteHelper *) paletteHelper;
|
||||
zrlePaletteHelperInit(ph);
|
||||
|
||||
while (ptr < end) {
|
||||
PIXEL_T pix = *ptr;
|
||||
if (*++ptr != pix) {
|
||||
singlePixels++;
|
||||
} else {
|
||||
while (*++ptr == pix) ;
|
||||
runs++;
|
||||
}
|
||||
zrlePaletteHelperInsert(ph, pix);
|
||||
}
|
||||
|
||||
/* Solid tile is a special case */
|
||||
|
||||
if (ph->size == 1) {
|
||||
zrleOutStreamWriteU8(os, 1);
|
||||
zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to work out whether to use RLE and/or a palette. We do this by
|
||||
estimating the number of bytes which will be generated and picking the
|
||||
method which results in the fewest bytes. Of course this may not result
|
||||
in the fewest bytes after compression... */
|
||||
|
||||
useRle = FALSE;
|
||||
usePalette = FALSE;
|
||||
|
||||
estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
|
||||
|
||||
#if BPP!=8
|
||||
if (zywrle_level > 0 && !(zywrle_level & 0x80))
|
||||
estimatedBytes >>= zywrle_level;
|
||||
#endif
|
||||
|
||||
plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
|
||||
|
||||
if (plainRleBytes < estimatedBytes) {
|
||||
useRle = TRUE;
|
||||
estimatedBytes = plainRleBytes;
|
||||
}
|
||||
|
||||
if (ph->size < 128) {
|
||||
int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
|
||||
|
||||
if (paletteRleBytes < estimatedBytes) {
|
||||
useRle = TRUE;
|
||||
usePalette = TRUE;
|
||||
estimatedBytes = paletteRleBytes;
|
||||
}
|
||||
|
||||
if (ph->size < 17) {
|
||||
int packedBytes = ((BPPOUT/8) * ph->size +
|
||||
w * h * bitsPerPackedPixel[ph->size-1] / 8);
|
||||
|
||||
if (packedBytes < estimatedBytes) {
|
||||
useRle = FALSE;
|
||||
usePalette = TRUE;
|
||||
estimatedBytes = packedBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!usePalette) ph->size = 0;
|
||||
|
||||
zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
|
||||
|
||||
for (i = 0; i < ph->size; i++) {
|
||||
zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
|
||||
}
|
||||
|
||||
if (useRle) {
|
||||
|
||||
PIXEL_T* ptr = data;
|
||||
PIXEL_T* end = ptr + w * h;
|
||||
PIXEL_T* runStart;
|
||||
PIXEL_T pix;
|
||||
while (ptr < end) {
|
||||
int len;
|
||||
runStart = ptr;
|
||||
pix = *ptr++;
|
||||
while (*ptr == pix && ptr < end)
|
||||
ptr++;
|
||||
len = ptr - runStart;
|
||||
if (len <= 2 && usePalette) {
|
||||
int index = zrlePaletteHelperLookup(ph, pix);
|
||||
if (len == 2)
|
||||
zrleOutStreamWriteU8(os, index);
|
||||
zrleOutStreamWriteU8(os, index);
|
||||
continue;
|
||||
}
|
||||
if (usePalette) {
|
||||
int index = zrlePaletteHelperLookup(ph, pix);
|
||||
zrleOutStreamWriteU8(os, index | 128);
|
||||
} else {
|
||||
zrleOutStreamWRITE_PIXEL(os, pix);
|
||||
}
|
||||
len -= 1;
|
||||
while (len >= 255) {
|
||||
zrleOutStreamWriteU8(os, 255);
|
||||
len -= 255;
|
||||
}
|
||||
zrleOutStreamWriteU8(os, len);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* no RLE */
|
||||
|
||||
if (usePalette) {
|
||||
int bppp;
|
||||
PIXEL_T* ptr = data;
|
||||
|
||||
/* packed pixels */
|
||||
|
||||
assert (ph->size < 17);
|
||||
|
||||
bppp = bitsPerPackedPixel[ph->size-1];
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
zrle_U8 nbits = 0;
|
||||
zrle_U8 byte = 0;
|
||||
|
||||
PIXEL_T* eol = ptr + w;
|
||||
|
||||
while (ptr < eol) {
|
||||
PIXEL_T pix = *ptr++;
|
||||
zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
|
||||
byte = (byte << bppp) | index;
|
||||
nbits += bppp;
|
||||
if (nbits >= 8) {
|
||||
zrleOutStreamWriteU8(os, byte);
|
||||
nbits = 0;
|
||||
}
|
||||
}
|
||||
if (nbits > 0) {
|
||||
byte <<= 8 - nbits;
|
||||
zrleOutStreamWriteU8(os, byte);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/* raw */
|
||||
|
||||
#if BPP!=8
|
||||
if (zywrle_level > 0 && !(zywrle_level & 0x80)) {
|
||||
ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, zywrleBuf);
|
||||
ZRLE_ENCODE_TILE(data, w, h, os, zywrle_level | 0x80, zywrleBuf, paletteHelper);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef CPIXEL
|
||||
PIXEL_T *ptr;
|
||||
for (ptr = data; ptr < data+w*h; ptr++)
|
||||
zrleOutStreamWRITE_PIXEL(os, *ptr);
|
||||
#else
|
||||
zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef PIXEL_T
|
||||
#undef zrleOutStreamWRITE_PIXEL
|
||||
#undef ZRLE_ENCODE
|
||||
#undef ZRLE_ENCODE_TILE
|
||||
#undef ZYWRLE_ENCODE_TILE
|
||||
#undef BPPOUT
|
|
@ -1,275 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "zrleoutstream.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ZRLE_IN_BUFFER_SIZE 16384
|
||||
#define ZRLE_OUT_BUFFER_SIZE 1024
|
||||
#undef ZRLE_DEBUG
|
||||
|
||||
static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size)
|
||||
{
|
||||
buffer->ptr = buffer->start = malloc(size);
|
||||
if (buffer->start == NULL) {
|
||||
buffer->end = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buffer->end = buffer->start + size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void zrleBufferFree(zrleBuffer *buffer)
|
||||
{
|
||||
if (buffer->start)
|
||||
free(buffer->start);
|
||||
buffer->start = buffer->ptr = buffer->end = NULL;
|
||||
}
|
||||
|
||||
static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size)
|
||||
{
|
||||
int offset;
|
||||
|
||||
size += buffer->end - buffer->start;
|
||||
offset = ZRLE_BUFFER_LENGTH (buffer);
|
||||
|
||||
buffer->start = realloc(buffer->start, size);
|
||||
if (!buffer->start) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buffer->end = buffer->start + size;
|
||||
buffer->ptr = buffer->start + offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
zrleOutStream *zrleOutStreamNew(void)
|
||||
{
|
||||
zrleOutStream *os;
|
||||
|
||||
os = malloc(sizeof(zrleOutStream));
|
||||
if (os == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) {
|
||||
free(os);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) {
|
||||
zrleBufferFree(&os->in);
|
||||
free(os);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os->zs.zalloc = Z_NULL;
|
||||
os->zs.zfree = Z_NULL;
|
||||
os->zs.opaque = Z_NULL;
|
||||
if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
||||
zrleBufferFree(&os->in);
|
||||
free(os);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
void zrleOutStreamFree (zrleOutStream *os)
|
||||
{
|
||||
deflateEnd(&os->zs);
|
||||
zrleBufferFree(&os->in);
|
||||
zrleBufferFree(&os->out);
|
||||
free(os);
|
||||
}
|
||||
|
||||
rfbBool zrleOutStreamFlush(zrleOutStream *os)
|
||||
{
|
||||
os->zs.next_in = os->in.start;
|
||||
os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
|
||||
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in);
|
||||
#endif
|
||||
|
||||
while (os->zs.avail_in != 0) {
|
||||
do {
|
||||
int ret;
|
||||
|
||||
if (os->out.ptr >= os->out.end &&
|
||||
!zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
|
||||
rfbLog("zrleOutStreamFlush: failed to grow output buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
os->zs.next_out = os->out.ptr;
|
||||
os->zs.avail_out = os->out.end - os->out.ptr;
|
||||
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n",
|
||||
os->zs.avail_in, os->zs.avail_out);
|
||||
#endif
|
||||
|
||||
if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
|
||||
rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n",
|
||||
os->zs.next_out - os->out.ptr);
|
||||
#endif
|
||||
|
||||
os->out.ptr = os->zs.next_out;
|
||||
} while (os->zs.avail_out == 0);
|
||||
}
|
||||
|
||||
os->in.ptr = os->in.start;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int zrleOutStreamOverrun(zrleOutStream *os,
|
||||
int size)
|
||||
{
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamOverrun\n");
|
||||
#endif
|
||||
|
||||
while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) {
|
||||
os->zs.next_in = os->in.start;
|
||||
os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
|
||||
|
||||
do {
|
||||
int ret;
|
||||
|
||||
if (os->out.ptr >= os->out.end &&
|
||||
!zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
|
||||
rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
os->zs.next_out = os->out.ptr;
|
||||
os->zs.avail_out = os->out.end - os->out.ptr;
|
||||
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n",
|
||||
os->zs.avail_in, os->zs.avail_out);
|
||||
#endif
|
||||
|
||||
if ((ret = deflate(&os->zs, 0)) != Z_OK) {
|
||||
rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ZRLE_DEBUG
|
||||
rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n",
|
||||
os->zs.next_out - os->out.ptr);
|
||||
#endif
|
||||
|
||||
os->out.ptr = os->zs.next_out;
|
||||
} while (os->zs.avail_out == 0);
|
||||
|
||||
/* output buffer not full */
|
||||
|
||||
if (os->zs.avail_in == 0) {
|
||||
os->in.ptr = os->in.start;
|
||||
} else {
|
||||
/* but didn't consume all the data? try shifting what's left to the
|
||||
* start of the buffer.
|
||||
*/
|
||||
rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n");
|
||||
memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in);
|
||||
os->in.ptr -= os->zs.next_in - os->in.start;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > os->in.end - os->in.ptr)
|
||||
size = os->in.end - os->in.ptr;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int zrleOutStreamCheck(zrleOutStream *os, int size)
|
||||
{
|
||||
if (os->in.ptr + size > os->in.end) {
|
||||
return zrleOutStreamOverrun(os, size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteBytes(zrleOutStream *os,
|
||||
const zrle_U8 *data,
|
||||
int length)
|
||||
{
|
||||
const zrle_U8* dataEnd = data + length;
|
||||
while (data < dataEnd) {
|
||||
int n = zrleOutStreamCheck(os, dataEnd - data);
|
||||
memcpy(os->in.ptr, data, n);
|
||||
os->in.ptr += n;
|
||||
data += n;
|
||||
}
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 1);
|
||||
*os->in.ptr++ = u;
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 1);
|
||||
*os->in.ptr++ = u;
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 2);
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[0];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[1];
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 4);
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[0];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[1];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[2];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[3];
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 3);
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[0];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[1];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[2];
|
||||
}
|
||||
|
||||
void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u)
|
||||
{
|
||||
zrleOutStreamCheck(os, 3);
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[1];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[2];
|
||||
*os->in.ptr++ = ((zrle_U8*)&u)[3];
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef __ZRLE_OUT_STREAM_H__
|
||||
#define __ZRLE_OUT_STREAM_H__
|
||||
|
||||
#include <zlib.h>
|
||||
#include "zrletypes.h"
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
typedef struct {
|
||||
zrle_U8 *start;
|
||||
zrle_U8 *ptr;
|
||||
zrle_U8 *end;
|
||||
} zrleBuffer;
|
||||
|
||||
typedef struct {
|
||||
zrleBuffer in;
|
||||
zrleBuffer out;
|
||||
|
||||
z_stream zs;
|
||||
} zrleOutStream;
|
||||
|
||||
#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start)
|
||||
|
||||
zrleOutStream *zrleOutStreamNew (void);
|
||||
void zrleOutStreamFree (zrleOutStream *os);
|
||||
rfbBool zrleOutStreamFlush (zrleOutStream *os);
|
||||
void zrleOutStreamWriteBytes (zrleOutStream *os,
|
||||
const zrle_U8 *data,
|
||||
int length);
|
||||
void zrleOutStreamWriteU8 (zrleOutStream *os,
|
||||
zrle_U8 u);
|
||||
void zrleOutStreamWriteOpaque8 (zrleOutStream *os,
|
||||
zrle_U8 u);
|
||||
void zrleOutStreamWriteOpaque16 (zrleOutStream *os,
|
||||
zrle_U16 u);
|
||||
void zrleOutStreamWriteOpaque32 (zrleOutStream *os,
|
||||
zrle_U32 u);
|
||||
void zrleOutStreamWriteOpaque24A(zrleOutStream *os,
|
||||
zrle_U32 u);
|
||||
void zrleOutStreamWriteOpaque24B(zrleOutStream *os,
|
||||
zrle_U32 u);
|
||||
|
||||
#endif /* __ZRLE_OUT_STREAM_H__ */
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "zrlepalettehelper.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095)
|
||||
|
||||
void zrlePaletteHelperInit(zrlePaletteHelper *helper)
|
||||
{
|
||||
memset(helper->palette, 0, sizeof(helper->palette));
|
||||
memset(helper->index, 255, sizeof(helper->index));
|
||||
memset(helper->key, 0, sizeof(helper->key));
|
||||
helper->size = 0;
|
||||
}
|
||||
|
||||
void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix)
|
||||
{
|
||||
if (helper->size < ZRLE_PALETTE_MAX_SIZE) {
|
||||
int i = ZRLE_HASH(pix);
|
||||
|
||||
while (helper->index[i] != 255 && helper->key[i] != pix)
|
||||
i++;
|
||||
if (helper->index[i] != 255) return;
|
||||
|
||||
helper->index[i] = helper->size;
|
||||
helper->key[i] = pix;
|
||||
helper->palette[helper->size] = pix;
|
||||
}
|
||||
helper->size++;
|
||||
}
|
||||
|
||||
int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix)
|
||||
{
|
||||
int i = ZRLE_HASH(pix);
|
||||
|
||||
assert(helper->size <= ZRLE_PALETTE_MAX_SIZE);
|
||||
|
||||
while (helper->index[i] != 255 && helper->key[i] != pix)
|
||||
i++;
|
||||
if (helper->index[i] != 255) return helper->index[i];
|
||||
|
||||
return -1;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The PaletteHelper class helps us build up the palette from pixel data by
|
||||
* storing a reverse index using a simple hash-table
|
||||
*/
|
||||
|
||||
#ifndef __ZRLE_PALETTE_HELPER_H__
|
||||
#define __ZRLE_PALETTE_HELPER_H__
|
||||
|
||||
#include "zrletypes.h"
|
||||
|
||||
#define ZRLE_PALETTE_MAX_SIZE 127
|
||||
|
||||
typedef struct {
|
||||
zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE];
|
||||
zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096];
|
||||
zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096];
|
||||
int size;
|
||||
} zrlePaletteHelper;
|
||||
|
||||
void zrlePaletteHelperInit (zrlePaletteHelper *helper);
|
||||
void zrlePaletteHelperInsert(zrlePaletteHelper *helper,
|
||||
zrle_U32 pix);
|
||||
int zrlePaletteHelperLookup(zrlePaletteHelper *helper,
|
||||
zrle_U32 pix);
|
||||
|
||||
#endif /* __ZRLE_PALETTE_HELPER_H__ */
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef __ZRLE_TYPES_H__
|
||||
#define __ZRLE_TYPES_H__
|
||||
|
||||
typedef unsigned char zrle_U8;
|
||||
typedef unsigned short zrle_U16;
|
||||
typedef unsigned int zrle_U32;
|
||||
typedef signed char zrle_S8;
|
||||
typedef signed short zrle_S16;
|
||||
typedef signed int zrle_S32;
|
||||
|
||||
#endif /* __ZRLE_TYPES_H__ */
|
|
@ -1,828 +0,0 @@
|
|||
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. *
|
||||
* *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. *
|
||||
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 *
|
||||
* BY Hitachi Systems & Services, Ltd. *
|
||||
* (Noriaki Yamazaki, Research & Developement Center) * *
|
||||
* *
|
||||
********************************************************************
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Hitachi Systems & Services, Ltd. nor
|
||||
the names of its contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************/
|
||||
|
||||
/* Change Log:
|
||||
V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline
|
||||
(Thanks Johannes Schindelin, author of LibVNC
|
||||
Server/Client)
|
||||
V0.01 : 2007/02/06 : Initial release
|
||||
*/
|
||||
|
||||
/* #define ZYWRLE_ENCODE */
|
||||
/* #define ZYWRLE_DECODE */
|
||||
#define ZYWRLE_QUANTIZE
|
||||
|
||||
/*
|
||||
[References]
|
||||
PLHarr:
|
||||
Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
|
||||
EZW:
|
||||
Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
|
||||
*/
|
||||
|
||||
|
||||
/* Template Macro stuffs. */
|
||||
#undef ZYWRLE_ANALYZE
|
||||
#undef ZYWRLE_SYNTHESIZE
|
||||
#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX)
|
||||
#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX)
|
||||
|
||||
#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX)
|
||||
#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX)
|
||||
#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP)
|
||||
#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP)
|
||||
#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP)
|
||||
#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP)
|
||||
|
||||
/* Packing/Unpacking pixel stuffs.
|
||||
Endian conversion stuffs. */
|
||||
#undef S_0
|
||||
#undef S_1
|
||||
#undef L_0
|
||||
#undef L_1
|
||||
#undef L_2
|
||||
#if ZYWRLE_ENDIAN == ENDIAN_BIG
|
||||
# define S_0 1
|
||||
# define S_1 0
|
||||
# define L_0 3
|
||||
# define L_1 2
|
||||
# define L_2 1
|
||||
#else
|
||||
# define S_0 0
|
||||
# define S_1 1
|
||||
# define L_0 0
|
||||
# define L_1 1
|
||||
# define L_2 2
|
||||
#endif
|
||||
|
||||
/* Load/Save pixel stuffs. */
|
||||
#define ZYWRLE_YMASK15 0xFFFFFFF8
|
||||
#define ZYWRLE_UVMASK15 0xFFFFFFF8
|
||||
#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \
|
||||
R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \
|
||||
G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \
|
||||
B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \
|
||||
}
|
||||
#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \
|
||||
R &= 0xF8; \
|
||||
G &= 0xF8; \
|
||||
B &= 0xF8; \
|
||||
((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \
|
||||
((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \
|
||||
}
|
||||
#define ZYWRLE_YMASK16 0xFFFFFFFC
|
||||
#define ZYWRLE_UVMASK16 0xFFFFFFF8
|
||||
#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \
|
||||
R = ((unsigned char*)pSrc)[S_1] & 0xF8; \
|
||||
G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \
|
||||
B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \
|
||||
}
|
||||
#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \
|
||||
R &= 0xF8; \
|
||||
G &= 0xFC; \
|
||||
B &= 0xF8; \
|
||||
((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \
|
||||
((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \
|
||||
}
|
||||
#define ZYWRLE_YMASK32 0xFFFFFFFF
|
||||
#define ZYWRLE_UVMASK32 0xFFFFFFFF
|
||||
#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \
|
||||
R = ((unsigned char*)pSrc)[L_2]; \
|
||||
G = ((unsigned char*)pSrc)[L_1]; \
|
||||
B = ((unsigned char*)pSrc)[L_0]; \
|
||||
}
|
||||
#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \
|
||||
((unsigned char*)pDst)[L_2] = (unsigned char)R; \
|
||||
((unsigned char*)pDst)[L_1] = (unsigned char)G; \
|
||||
((unsigned char*)pDst)[L_0] = (unsigned char)B; \
|
||||
}
|
||||
|
||||
#ifndef ZYWRLE_ONCE
|
||||
#define ZYWRLE_ONCE
|
||||
|
||||
#ifdef WIN32
|
||||
#define InlineX __inline
|
||||
#else
|
||||
# ifndef __STRICT_ANSI__
|
||||
# define InlineX inline
|
||||
# else
|
||||
# define InlineX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ZYWRLE_ENCODE
|
||||
/* Tables for Coefficients filtering. */
|
||||
# ifndef ZYWRLE_QUANTIZE
|
||||
/* Type A:lower bit omitting of EZW style. */
|
||||
const static unsigned int zywrleParam[3][3]={
|
||||
{0x0000F000,0x00000000,0x00000000},
|
||||
{0x0000C000,0x00F0F0F0,0x00000000},
|
||||
{0x0000C000,0x00C0C0C0,0x00F0F0F0},
|
||||
/* {0x0000FF00,0x00000000,0x00000000},
|
||||
{0x0000FF00,0x00FFFFFF,0x00000000},
|
||||
{0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */
|
||||
};
|
||||
# else
|
||||
/* Type B:Non liner quantization filter. */
|
||||
static const signed char zywrleConv[4][256]={
|
||||
{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 72, 72, 72, 72,
|
||||
72, 72, 72, 72, 80, 80, 80, 80,
|
||||
80, 80, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 96, 96,
|
||||
96, 96, 96, 104, 104, 104, 104, 104,
|
||||
104, 104, 104, 104, 104, 112, 112, 112,
|
||||
112, 112, 112, 112, 112, 112, 120, 120,
|
||||
120, 120, 120, 120, 120, 120, 120, 120,
|
||||
0, -120, -120, -120, -120, -120, -120, -120,
|
||||
-120, -120, -120, -112, -112, -112, -112, -112,
|
||||
-112, -112, -112, -112, -104, -104, -104, -104,
|
||||
-104, -104, -104, -104, -104, -104, -96, -96,
|
||||
-96, -96, -96, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -80,
|
||||
-80, -80, -80, -80, -80, -72, -72, -72,
|
||||
-72, -72, -72, -72, -72, -64, -64, -64,
|
||||
-64, -64, -64, -64, -64, -56, -56, -56,
|
||||
-56, -56, -56, -56, -56, -56, -48, -48,
|
||||
-48, -48, -48, -48, -48, -48, -48, -48,
|
||||
-48, -32, -32, -32, -32, -32, -32, -32,
|
||||
-32, -32, -32, -32, -32, -32, -32, -32,
|
||||
-32, -32, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64,
|
||||
80, 80, 80, 80, 80, 80, 80, 80,
|
||||
80, 80, 80, 80, 80, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
104, 104, 104, 104, 104, 104, 104, 104,
|
||||
104, 104, 104, 112, 112, 112, 112, 112,
|
||||
112, 112, 112, 112, 120, 120, 120, 120,
|
||||
120, 120, 120, 120, 120, 120, 120, 120,
|
||||
0, -120, -120, -120, -120, -120, -120, -120,
|
||||
-120, -120, -120, -120, -120, -112, -112, -112,
|
||||
-112, -112, -112, -112, -112, -112, -104, -104,
|
||||
-104, -104, -104, -104, -104, -104, -104, -104,
|
||||
-104, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -80, -80, -80, -80,
|
||||
-80, -80, -80, -80, -80, -80, -80, -80,
|
||||
-80, -64, -64, -64, -64, -64, -64, -64,
|
||||
-64, -64, -64, -64, -64, -64, -64, -64,
|
||||
-64, -48, -48, -48, -48, -48, -48, -48,
|
||||
-48, -48, -48, -48, -48, -48, -48, -48,
|
||||
-48, -48, -48, -48, -48, -48, -48, -48,
|
||||
-48, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
88, 88, 88, 88, 88, 88, 88, 88,
|
||||
0, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, -88, -88, -88, -88, -88, -88, -88,
|
||||
-88, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
};
|
||||
const static signed char* zywrleParam[3][3][3]={
|
||||
{{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
|
||||
{{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
|
||||
{{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}},
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static InlineX void Harr(signed char* pX0, signed char* pX1)
|
||||
{
|
||||
/* Piecewise-Linear Harr(PLHarr) */
|
||||
int X0 = (int)*pX0, X1 = (int)*pX1;
|
||||
int orgX0 = X0, orgX1 = X1;
|
||||
if ((X0 ^ X1) & 0x80) {
|
||||
/* differ sign */
|
||||
X1 += X0;
|
||||
if (((X1^orgX1)&0x80)==0) {
|
||||
/* |X1| > |X0| */
|
||||
X0 -= X1; /* H = -B */
|
||||
}
|
||||
} else {
|
||||
/* same sign */
|
||||
X0 -= X1;
|
||||
if (((X0 ^ orgX0) & 0x80) == 0) {
|
||||
/* |X0| > |X1| */
|
||||
X1 += X0; /* L = A */
|
||||
}
|
||||
}
|
||||
*pX0 = (signed char)X1;
|
||||
*pX1 = (signed char)X0;
|
||||
}
|
||||
/*
|
||||
1D-Wavelet transform.
|
||||
|
||||
In coefficients array, the famous 'pyramid' decomposition is well used.
|
||||
|
||||
1D Model:
|
||||
|L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
|
||||
|L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
|
||||
|
||||
But this method needs line buffer because H/L is different position from X0/X1.
|
||||
So, I used 'interleave' decomposition instead of it.
|
||||
|
||||
1D Model:
|
||||
|L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
|
||||
|L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
|
||||
|
||||
In this method, H/L and X0/X1 is always same position.
|
||||
This lead us to more speed and less memory.
|
||||
Of cause, the result of both method is quite same
|
||||
because it's only difference that coefficient position.
|
||||
*/
|
||||
static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel)
|
||||
{
|
||||
int s, ofs;
|
||||
signed char* pX0;
|
||||
signed char* end;
|
||||
|
||||
pX0 = (signed char*)data;
|
||||
s = (8<<l)*SkipPixel;
|
||||
end = pX0+(size>>(l+1))*s;
|
||||
s -= 2;
|
||||
ofs = (4<<l)*SkipPixel;
|
||||
while (pX0 < end) {
|
||||
Harr(pX0, pX0+ofs);
|
||||
pX0++;
|
||||
Harr(pX0, pX0+ofs);
|
||||
pX0++;
|
||||
Harr(pX0, pX0+ofs);
|
||||
pX0 += s;
|
||||
}
|
||||
}
|
||||
#define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix)
|
||||
|
||||
#ifdef ZYWRLE_ENCODE
|
||||
# ifndef ZYWRLE_QUANTIZE
|
||||
/* Type A:lower bit omitting of EZW style. */
|
||||
static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
|
||||
{
|
||||
int r, s;
|
||||
int x, y;
|
||||
int* pH;
|
||||
const unsigned int* pM;
|
||||
|
||||
pM = &(zywrleParam[level-1][l]);
|
||||
s = 2<<l;
|
||||
for (r = 1; r < 4; r++) {
|
||||
pH = pBuf;
|
||||
if (r & 0x01)
|
||||
pH += s>>1;
|
||||
if (r & 0x02)
|
||||
pH += (s>>1)*width;
|
||||
for (y = 0; y < height / s; y++) {
|
||||
for (x = 0; x < width / s; x++) {
|
||||
/*
|
||||
these are same following code.
|
||||
pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
|
||||
( round pH[x] with pM[x] bit )
|
||||
'&' operator isn't 'round' but is 'floor'.
|
||||
So, we must offset when pH[x] is negative.
|
||||
*/
|
||||
if (((signed char*)pH)[0] & 0x80)
|
||||
((signed char*)pH)[0] += ~((signed char*)pM)[0];
|
||||
if (((signed char*)pH)[1] & 0x80)
|
||||
((signed char*)pH)[1] += ~((signed char*)pM)[1];
|
||||
if (((signed char*)pH)[2] & 0x80)
|
||||
((signed char*)pH)[2] += ~((signed char*)pM)[2];
|
||||
*pH &= *pM;
|
||||
pH += s;
|
||||
}
|
||||
pH += (s-1)*width;
|
||||
}
|
||||
}
|
||||
}
|
||||
# else
|
||||
/*
|
||||
Type B:Non liner quantization filter.
|
||||
|
||||
Coefficients have Gaussian curve and smaller value which is
|
||||
large part of coefficients isn't more important than larger value.
|
||||
So, I use filter of Non liner quantize/dequantize table.
|
||||
In general, Non liner quantize formula is explained as following.
|
||||
|
||||
y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo)
|
||||
x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
|
||||
( r:power coefficient bi:effective MSB in input bo:effective MSB in output )
|
||||
|
||||
r < 1.0 : Smaller value is more important than larger value.
|
||||
r > 1.0 : Larger value is more important than smaller value.
|
||||
r = 1.0 : Liner quantization which is same with EZW style.
|
||||
|
||||
r = 0.75 is famous non liner quantization used in MP3 audio codec.
|
||||
In contrast to audio data, larger value is important in wavelet coefficients.
|
||||
So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
|
||||
|
||||
As compared with EZW style liner quantization, this filter tended to be
|
||||
more sharp edge and be more compression rate but be more blocking noise and be less quality.
|
||||
Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
|
||||
|
||||
We need only quantized-dequantized(filtered) value rather than quantized value itself
|
||||
because all values are packed or palette-lized in later ZRLE section.
|
||||
This lead us not to need to modify client decoder when we change
|
||||
the filtering procedure in future.
|
||||
Client only decodes coefficients given by encoder.
|
||||
*/
|
||||
static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
|
||||
{
|
||||
int r, s;
|
||||
int x, y;
|
||||
int* pH;
|
||||
const signed char** pM;
|
||||
|
||||
pM = zywrleParam[level-1][l];
|
||||
s = 2<<l;
|
||||
for (r = 1; r < 4; r++) {
|
||||
pH = pBuf;
|
||||
if (r & 0x01)
|
||||
pH += s>>1;
|
||||
if (r & 0x02)
|
||||
pH += (s>>1)*width;
|
||||
for (y = 0; y < height / s; y++) {
|
||||
for (x = 0; x < width / s; x++) {
|
||||
((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]];
|
||||
((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]];
|
||||
((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]];
|
||||
pH += s;
|
||||
}
|
||||
pH += (s-1)*width;
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
static InlineX void Wavelet(int* pBuf, int width, int height, int level)
|
||||
{
|
||||
int l, s;
|
||||
int* pTop;
|
||||
int* pEnd;
|
||||
|
||||
for (l = 0; l < level; l++) {
|
||||
pTop = pBuf;
|
||||
pEnd = pBuf+height*width;
|
||||
s = width<<l;
|
||||
while (pTop < pEnd) {
|
||||
WaveletLevel(pTop, width, l, 1);
|
||||
pTop += s;
|
||||
}
|
||||
pTop = pBuf;
|
||||
pEnd = pBuf+width;
|
||||
s = 1<<l;
|
||||
while (pTop < pEnd) {
|
||||
WaveletLevel(pTop, height,l, width);
|
||||
pTop += s;
|
||||
}
|
||||
FilterWaveletSquare(pBuf, width, height, level, l);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ZYWRLE_DECODE
|
||||
static InlineX void InvWavelet(int* pBuf, int width, int height, int level)
|
||||
{
|
||||
int l, s;
|
||||
int* pTop;
|
||||
int* pEnd;
|
||||
|
||||
for (l = level - 1; l >= 0; l--) {
|
||||
pTop = pBuf;
|
||||
pEnd = pBuf+width;
|
||||
s = 1<<l;
|
||||
while (pTop < pEnd) {
|
||||
InvWaveletLevel(pTop, height,l, width);
|
||||
pTop += s;
|
||||
}
|
||||
pTop = pBuf;
|
||||
pEnd = pBuf+height*width;
|
||||
s = width<<l;
|
||||
while (pTop < pEnd) {
|
||||
InvWaveletLevel(pTop, width, l, 1);
|
||||
pTop += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Load/Save coefficients stuffs.
|
||||
Coefficients manages as 24 bits little-endian pixel. */
|
||||
#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \
|
||||
R = ((signed char*)pSrc)[2]; \
|
||||
G = ((signed char*)pSrc)[1]; \
|
||||
B = ((signed char*)pSrc)[0]; \
|
||||
}
|
||||
#define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \
|
||||
((signed char*)pDst)[2] = (signed char)R; \
|
||||
((signed char*)pDst)[1] = (signed char)G; \
|
||||
((signed char*)pDst)[0] = (signed char)B; \
|
||||
}
|
||||
|
||||
/*
|
||||
RGB <=> YUV conversion stuffs.
|
||||
YUV coversion is explained as following formula in strict meaning:
|
||||
Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255)
|
||||
U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
|
||||
V = 0.500R - 0.419G - 0.081B (-128<=V<=127)
|
||||
|
||||
I use simple conversion RCT(reversible color transform) which is described
|
||||
in JPEG-2000 specification.
|
||||
Y = (R + 2G + B)/4 ( 0<=Y<=255)
|
||||
U = B-G (-256<=U<=255)
|
||||
V = R-G (-256<=V<=255)
|
||||
*/
|
||||
#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x)))
|
||||
/* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
|
||||
For make Same N-bit, UV is lossy.
|
||||
More exact PLHarr, we reduce to odd range(-127<=x<=127). */
|
||||
#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \
|
||||
Y = (R+(G<<1)+B)>>2; \
|
||||
U = B-G; \
|
||||
V = R-G; \
|
||||
Y -= 128; \
|
||||
U >>= 1; \
|
||||
V >>= 1; \
|
||||
Y &= ymask; \
|
||||
U &= uvmask; \
|
||||
V &= uvmask; \
|
||||
if (Y == -128) \
|
||||
Y += (0xFFFFFFFF-ymask+1); \
|
||||
if (U == -128) \
|
||||
U += (0xFFFFFFFF-uvmask+1); \
|
||||
if (V == -128) \
|
||||
V += (0xFFFFFFFF-uvmask+1); \
|
||||
}
|
||||
#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \
|
||||
Y += 128; \
|
||||
U <<= 1; \
|
||||
V <<= 1; \
|
||||
G = Y-((U+V)>>2); \
|
||||
B = U+G; \
|
||||
R = V+G; \
|
||||
G = ROUND(G); \
|
||||
B = ROUND(B); \
|
||||
R = ROUND(R); \
|
||||
}
|
||||
|
||||
/*
|
||||
coefficient packing/unpacking stuffs.
|
||||
Wavelet transform makes 4 sub coefficient image from 1 original image.
|
||||
|
||||
model with pyramid decomposition:
|
||||
+------+------+
|
||||
| | |
|
||||
| L | Hx |
|
||||
| | |
|
||||
+------+------+
|
||||
| | |
|
||||
| H | Hxy |
|
||||
| | |
|
||||
+------+------+
|
||||
|
||||
So, we must transfer each sub images individually in strict meaning.
|
||||
But at least ZRLE meaning, following one decompositon image is same as
|
||||
avobe individual sub image. I use this format.
|
||||
(Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
|
||||
for simplified procedure for any wavelet level.)
|
||||
|
||||
+------+------+
|
||||
| L |
|
||||
+------+------+
|
||||
| Hx |
|
||||
+------+------+
|
||||
| Hy |
|
||||
+------+------+
|
||||
| Hxy |
|
||||
+------+------+
|
||||
*/
|
||||
#define INC_PTR(data) \
|
||||
data++; \
|
||||
if( data-pData >= (w+uw) ){ \
|
||||
data += scanline-(w+uw); \
|
||||
pData = data; \
|
||||
}
|
||||
|
||||
#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \
|
||||
pH = pBuf; \
|
||||
s = 2<<level; \
|
||||
if (r & 0x01) \
|
||||
pH += s>>1; \
|
||||
if (r & 0x02) \
|
||||
pH += (s>>1)*w; \
|
||||
pEnd = pH+h*w; \
|
||||
while (pH < pEnd) { \
|
||||
pLine = pH+w; \
|
||||
while (pH < pLine) { \
|
||||
TRANS \
|
||||
INC_PTR(data) \
|
||||
pH += s; \
|
||||
} \
|
||||
pH += (s-1)*w; \
|
||||
}
|
||||
|
||||
#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \
|
||||
ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
|
||||
|
||||
#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \
|
||||
ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
|
||||
|
||||
#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \
|
||||
pTop = pBuf+w*h; \
|
||||
pEnd = pBuf + (w+uw)*(h+uh); \
|
||||
while (pTop < pEnd) { \
|
||||
TRANS \
|
||||
INC_PTR(data) \
|
||||
pTop++; \
|
||||
}
|
||||
|
||||
#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \
|
||||
pTop = pBuf+w*h; \
|
||||
if (uw) { \
|
||||
pData= data + w; \
|
||||
pEnd = (int*)(pData+ h*scanline); \
|
||||
while (pData < (PIXEL_T*)pEnd) { \
|
||||
pLine = (int*)(pData + uw); \
|
||||
while (pData < (PIXEL_T*)pLine) { \
|
||||
TRANS \
|
||||
pData++; \
|
||||
pTop++; \
|
||||
} \
|
||||
pData += scanline-uw; \
|
||||
} \
|
||||
} \
|
||||
if (uh) { \
|
||||
pData= data + h*scanline; \
|
||||
pEnd = (int*)(pData+ uh*scanline); \
|
||||
while (pData < (PIXEL_T*)pEnd) { \
|
||||
pLine = (int*)(pData + w); \
|
||||
while (pData < (PIXEL_T*)pLine) { \
|
||||
TRANS \
|
||||
pData++; \
|
||||
pTop++; \
|
||||
} \
|
||||
pData += scanline-w; \
|
||||
} \
|
||||
} \
|
||||
if (uw && uh) { \
|
||||
pData= data + w+ h*scanline; \
|
||||
pEnd = (int*)(pData+ uh*scanline); \
|
||||
while (pData < (PIXEL_T*)pEnd) { \
|
||||
pLine = (int*)(pData + uw); \
|
||||
while (pData < (PIXEL_T*)pLine) { \
|
||||
TRANS \
|
||||
pData++; \
|
||||
pTop++; \
|
||||
} \
|
||||
pData += scanline-uw; \
|
||||
} \
|
||||
}
|
||||
|
||||
static InlineX void zywrleCalcSize(int* pW, int* pH, int level)
|
||||
{
|
||||
*pW &= ~((1<<level)-1);
|
||||
*pH &= ~((1<<level)-1);
|
||||
}
|
||||
|
||||
#endif /* ZYWRLE_ONCE */
|
||||
|
||||
#ifndef CPIXEL
|
||||
#ifdef ZYWRLE_ENCODE
|
||||
static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int height, int scanline)
|
||||
{
|
||||
int R, G, B;
|
||||
int Y, U, V;
|
||||
int* pLine;
|
||||
int* pEnd;
|
||||
pEnd = pBuf+height*width;
|
||||
while (pBuf < pEnd) {
|
||||
pLine = pBuf+width;
|
||||
while (pBuf < pLine) {
|
||||
ZYWRLE_LOAD_PIXEL(data,R,G,B);
|
||||
ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK);
|
||||
ZYWRLE_SAVE_COEFF(pBuf,V,Y,U);
|
||||
pBuf++;
|
||||
data++;
|
||||
}
|
||||
data += scanline-width;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ZYWRLE_DECODE
|
||||
static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) {
|
||||
int R, G, B;
|
||||
int Y, U, V;
|
||||
int* pLine;
|
||||
int* pEnd;
|
||||
pEnd = pBuf+height*width;
|
||||
while (pBuf < pEnd) {
|
||||
pLine = pBuf+width;
|
||||
while (pBuf < pLine) {
|
||||
ZYWRLE_LOAD_COEFF(pBuf,V,Y,U);
|
||||
ZYWRLE_YUVRGB1(R,G,B,Y,U,V);
|
||||
ZYWRLE_SAVE_PIXEL(data,R,G,B);
|
||||
pBuf++;
|
||||
data++;
|
||||
}
|
||||
data += scanline-width;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZYWRLE_ENCODE
|
||||
PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) {
|
||||
int l;
|
||||
int uw = w;
|
||||
int uh = h;
|
||||
int* pTop;
|
||||
int* pEnd;
|
||||
int* pLine;
|
||||
PIXEL_T* pData;
|
||||
int R, G, B;
|
||||
int s;
|
||||
int* pH;
|
||||
|
||||
zywrleCalcSize(&w, &h, level);
|
||||
if (w == 0 || h == 0)
|
||||
return NULL;
|
||||
uw -= w;
|
||||
uh -= h;
|
||||
|
||||
pData = dst;
|
||||
ZYWRLE_LOAD_UNALIGN(src,*(PIXEL_T*)pTop=*pData;)
|
||||
ZYWRLE_RGBYUV(pBuf, src, w, h, scanline);
|
||||
Wavelet(pBuf, w, h, level);
|
||||
for (l = 0; l < level; l++) {
|
||||
ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, scanline, l);
|
||||
ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, scanline, l);
|
||||
ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, scanline, l);
|
||||
if (l == level - 1) {
|
||||
ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, scanline, l);
|
||||
}
|
||||
}
|
||||
ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
#ifdef ZYWRLE_DECODE
|
||||
PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf)
|
||||
{
|
||||
int l;
|
||||
int uw = w;
|
||||
int uh = h;
|
||||
int* pTop;
|
||||
int* pEnd;
|
||||
int* pLine;
|
||||
PIXEL_T* pData;
|
||||
int R, G, B;
|
||||
int s;
|
||||
int* pH;
|
||||
|
||||
zywrleCalcSize(&w, &h, level);
|
||||
if (w == 0 || h == 0)
|
||||
return NULL;
|
||||
uw -= w;
|
||||
uh -= h;
|
||||
|
||||
pData = src;
|
||||
for (l = 0; l < level; l++) {
|
||||
ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, scanline, l);
|
||||
ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, scanline, l);
|
||||
ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, scanline, l);
|
||||
if (l == level - 1) {
|
||||
ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, scanline, l);
|
||||
}
|
||||
}
|
||||
ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;)
|
||||
InvWavelet(pBuf, w, h, level);
|
||||
ZYWRLE_YUVRGB(pBuf, dst, w, h, scanline);
|
||||
ZYWRLE_LOAD_UNALIGN(dst,*pData=*(PIXEL_T*)pTop;)
|
||||
return src;
|
||||
}
|
||||
#endif
|
||||
#endif /* CPIXEL */
|
||||
|
||||
#undef ZYWRLE_RGBYUV
|
||||
#undef ZYWRLE_YUVRGB
|
||||
#undef ZYWRLE_LOAD_PIXEL
|
||||
#undef ZYWRLE_SAVE_PIXEL
|
Loading…
Reference in New Issue
Block a user