Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
libvncserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
libvncserver
Commits
ccdbe8f3
Commit
ccdbe8f3
authored
May 15, 2006
by
steven_carr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
The great UltraVNC Compatibility Commit
parent
347c4a98
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1935 additions
and
301 deletions
+1935
-301
ChangeLog
ChangeLog
+20
-0
SDLvncviewer.c
client_examples/SDLvncviewer.c
+21
-1
rfbproto.c
libvncclient/rfbproto.c
+336
-30
ultra.c
libvncclient/ultra.c
+0
-4
zrle.c
libvncclient/zrle.c
+1
-1
auth.c
libvncserver/auth.c
+6
-1
corre.c
libvncserver/corre.c
+4
-4
cursor.c
libvncserver/cursor.c
+3
-8
hextile.c
libvncserver/hextile.c
+10
-7
main.c
libvncserver/main.c
+27
-5
rfbserver.c
libvncserver/rfbserver.c
+910
-103
rre.c
libvncserver/rre.c
+4
-4
scale.c
libvncserver/scale.c
+5
-3
sockets.c
libvncserver/sockets.c
+19
-3
stats.c
libvncserver/stats.c
+410
-66
tight.c
libvncserver/tight.c
+16
-16
rfbtightproto.h
libvncserver/tightvnc-filetransfer/rfbtightproto.h
+6
-0
ultra.c
libvncserver/ultra.c
+1
-3
zlib.c
libvncserver/zlib.c
+3
-3
zrle.c
libvncserver/zrle.c
+2
-3
rfb.h
rfb/rfb.h
+95
-16
rfbclient.h
rfb/rfbclient.h
+21
-0
rfbproto.h
rfb/rfbproto.h
+10
-12
rates.c
x11vnc/rates.c
+4
-7
userinput.c
x11vnc/userinput.c
+1
-1
No files found.
ChangeLog
View file @
ccdbe8f3
2006-05-15 Steven Carr <scarr@jsa-usa.com>
* The great UltraVNC Compatibility Commit!
libvncserver now supports the following messages:
SetSingleWindow - Select a single window to be the source of the
framebuffer.
ServerInput - Disable and blank the servers display
TextChat - TextChat between the remote/local user
(Bandwidth friendly VS the Notepad approach)
FileTransfer - Emulates a Windows Filesystem to the viewer
(Currently does not support Delta Transfers)
(Currently does not support Sending Directories)
UltraZip - Improved UltraZip support
* Improved Statistics SubSystem, now supports all encodings
* RFB 3.8 support! Error Messages are a 'Good Thing' (tm)
* Default to identify as RFB 3.6 to emulate UltraVNC server
(Server now has the ability to set the RFB version reported)
(permits the viewer to identify the server has FileTransfer ability)
* Client Encoding AutoSelection Supported (UltraViewer is speed aware)
* libvncclient has improved server detection/capabilities logic!
2006-05-13 Karl Runge <runge@karlrunge.com>
* minilzo.c,minilzo.h,lzoconf.h: switch to non-CRLF versions.
* libvncclient/Makefile.am: add minilzo.c, minilzo.h, lzoconf.h
...
...
client_examples/SDLvncviewer.c
View file @
ccdbe8f3
...
...
@@ -150,6 +150,26 @@ static void kbd_leds(rfbClient* cl, int value, int pad) {
fflush
(
stderr
);
}
/* trivial support for textchat */
static
void
text_chat
(
rfbClient
*
cl
,
int
value
,
char
*
text
)
{
switch
(
value
)
{
case
rfbTextChatOpen
:
fprintf
(
stderr
,
"TextChat: We should open a textchat window!
\n
"
);
TextChatOpen
(
cl
);
break
;
case
rfbTextChatClose
:
fprintf
(
stderr
,
"TextChat: We should close our window!
\n
"
);
break
;
case
rfbTextChatFinished
:
fprintf
(
stderr
,
"TextChat: We should close our window!
\n
"
);
break
;
default:
fprintf
(
stderr
,
"TextChat: Received
\"
%s
\"\n
"
,
text
);
break
;
}
fflush
(
stderr
);
}
#ifdef __MINGW32__
#define LOG_TO_FILE
#endif
...
...
@@ -212,7 +232,7 @@ int main(int argc,char** argv) {
cl
->
canHandleNewFBSize
=
TRUE
;
cl
->
GotFrameBufferUpdate
=
update
;
cl
->
HandleKeyboardLedState
=
kbd_leds
;
cl
->
HandleTextChat
=
text_chat
;
if
(
!
rfbInitClient
(
cl
,
&
argc
,
argv
))
return
1
;
...
...
libvncclient/rfbproto.c
View file @
ccdbe8f3
...
...
@@ -223,6 +223,99 @@ static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int r
static
rfbBool
HandleZRLE32
(
rfbClient
*
client
,
int
rx
,
int
ry
,
int
rw
,
int
rh
);
#endif
/*
* Server Capability Functions
*/
rfbBool
SupportsClient2Server
(
rfbClient
*
client
,
int
messageType
)
{
return
(
client
->
supportedMessages
.
client2server
[((
messageType
&
0xFF
)
/
8
)]
&
(
1
<<
(
messageType
%
8
))
?
TRUE
:
FALSE
);
}
rfbBool
SupportsServer2Client
(
rfbClient
*
client
,
int
messageType
)
{
return
(
client
->
supportedMessages
.
server2client
[((
messageType
&
0xFF
)
/
8
)]
&
(
1
<<
(
messageType
%
8
))
?
TRUE
:
FALSE
);
}
void
SetClient2Server
(
rfbClient
*
client
,
int
messageType
)
{
client
->
supportedMessages
.
client2server
[((
messageType
&
0xFF
)
/
8
)]
|=
(
1
<<
(
messageType
%
8
));
}
void
SetServer2Client
(
rfbClient
*
client
,
int
messageType
)
{
client
->
supportedMessages
.
server2client
[((
messageType
&
0xFF
)
/
8
)]
|=
(
1
<<
(
messageType
%
8
));
}
void
ClearClient2Server
(
rfbClient
*
client
,
int
messageType
)
{
client
->
supportedMessages
.
client2server
[((
messageType
&
0xFF
)
/
8
)]
&=
(
!
(
1
<<
(
messageType
%
8
)));
}
void
ClearServer2Client
(
rfbClient
*
client
,
int
messageType
)
{
client
->
supportedMessages
.
server2client
[((
messageType
&
0xFF
)
/
8
)]
&=
(
!
(
1
<<
(
messageType
%
8
)));
}
void
DefaultSupportedMessages
(
rfbClient
*
client
)
{
memset
((
char
*
)
&
client
->
supportedMessages
,
0
,
sizeof
(
client
->
supportedMessages
));
/* Default client supported messages (universal RFB 3.3 protocol) */
SetClient2Server
(
client
,
rfbSetPixelFormat
);
/* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */
SetClient2Server
(
client
,
rfbSetEncodings
);
SetClient2Server
(
client
,
rfbFramebufferUpdateRequest
);
SetClient2Server
(
client
,
rfbKeyEvent
);
SetClient2Server
(
client
,
rfbPointerEvent
);
SetClient2Server
(
client
,
rfbClientCutText
);
/* technically, we only care what we can *send* to the server
* but, we set Server2Client Just in case it ever becomes useful
*/
SetServer2Client
(
client
,
rfbFramebufferUpdate
);
SetServer2Client
(
client
,
rfbSetColourMapEntries
);
SetServer2Client
(
client
,
rfbBell
);
SetServer2Client
(
client
,
rfbServerCutText
);
}
void
DefaultSupportedMessagesUltraVNC
(
rfbClient
*
client
)
{
DefaultSupportedMessages
(
client
);
SetClient2Server
(
client
,
rfbFileTransfer
);
SetClient2Server
(
client
,
rfbSetScale
);
SetClient2Server
(
client
,
rfbSetServerInput
);
SetClient2Server
(
client
,
rfbSetSW
);
SetClient2Server
(
client
,
rfbTextChat
);
SetClient2Server
(
client
,
rfbPalmVNCSetScaleFactor
);
/* technically, we only care what we can *send* to the server */
SetServer2Client
(
client
,
rfbResizeFrameBuffer
);
SetServer2Client
(
client
,
rfbPalmVNCReSizeFrameBuffer
);
SetServer2Client
(
client
,
rfbFileTransfer
);
SetServer2Client
(
client
,
rfbTextChat
);
}
void
DefaultSupportedMessagesTightVNC
(
rfbClient
*
client
)
{
DefaultSupportedMessages
(
client
);
SetClient2Server
(
client
,
rfbFileTransfer
);
SetClient2Server
(
client
,
rfbSetServerInput
);
SetClient2Server
(
client
,
rfbSetSW
);
/* SetClient2Server(client, rfbTextChat); */
/* technically, we only care what we can *send* to the server */
SetServer2Client
(
client
,
rfbFileTransfer
);
SetServer2Client
(
client
,
rfbTextChat
);
}
/*
* ConnectToRFBServer.
*/
...
...
@@ -310,25 +403,86 @@ InitialiseRFBConnection(rfbClient* client)
return
FALSE
;
}
#if rfbProtocolMinorVersion == 7
/* work around LibVNCClient not yet speaking RFB 3.7 */
#undef rfbProtocolMinorVersion
#define rfbProtocolMinorVersion 3
#endif
DefaultSupportedMessages
(
client
);
client
->
major
=
major
;
client
->
minor
=
minor
;
/* fall back to viewer supported version */
if
((
major
==
rfbProtocolMajorVersion
)
&&
(
minor
>
rfbProtocolMinorVersion
))
client
->
minor
=
rfbProtocolMinorVersion
;
/* UltraVNC uses minor codes 4 and 6 for the server */
if
(
major
==
3
&&
(
minor
==
4
||
minor
==
6
))
{
rfbClientLog
(
"UltraVNC server detected, enabling UltraVNC specific messages
\n
"
,
pv
);
DefaultSupportedMessagesUltraVNC
(
client
);
}
/* TightVNC uses minor codes 5 for the server */
if
(
major
==
3
&&
minor
==
5
)
{
rfbClientLog
(
"TightVNC server detected, enabling TightVNC specific messages
\n
"
,
pv
);
DefaultSupportedMessagesTightVNC
(
client
);
}
/* we do not support > RFB3.8 */
if
(
major
==
3
&&
minor
>
8
)
client
->
minor
=
8
;
rfbClientLog
(
"VNC server supports protocol version %d.%d (viewer %d.%d)
\n
"
,
major
,
minor
,
rfbProtocolMajorVersion
,
rfbProtocolMinorVersion
);
major
=
rfbProtocolMajorVersion
;
minor
=
rfbProtocolMinorVersion
;
sprintf
(
pv
,
rfbProtocolVersionFormat
,
major
,
minor
);
sprintf
(
pv
,
rfbProtocolVersionFormat
,
client
->
major
,
client
->
minor
);
if
(
!
WriteToRFBServer
(
client
,
pv
,
sz_rfbProtocolVersionMsg
))
return
FALSE
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
authScheme
,
4
))
return
FALSE
;
/* 3.7 and onwards sends a # of security types first */
if
(
client
->
major
==
3
&&
client
->
minor
>
6
)
{
uint8_t
count
=
0
;
uint8_t
loop
=
0
;
uint8_t
flag
=
0
;
uint8_t
tAuth
=
0
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
count
,
1
))
return
FALSE
;
if
(
count
==
0
)
{
rfbClientLog
(
"List of security types is ZERO, expecting an error to follow
\n
"
);
/* we have an error following */
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
reasonLen
,
4
))
return
FALSE
;
reasonLen
=
rfbClientSwap32IfLE
(
reasonLen
);
reason
=
malloc
(
reasonLen
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
FALSE
;
}
rfbClientLog
(
"VNC connection failed: %.*s
\n
"
,(
int
)
reasonLen
,
reason
);
free
(
reason
);
return
FALSE
;
}
rfbClientLog
(
"We have %d security types to read
\n
"
,
count
);
/* now, we have a list of available security types to read ( uint8_t[] ) */
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
tAuth
,
1
))
return
FALSE
;
rfbClientLog
(
"%d) Received security type %d
\n
"
,
loop
,
tAuth
);
if
((
flag
==
0
)
&&
((
tAuth
==
rfbVncAuth
)
||
(
tAuth
==
rfbNoAuth
)))
{
flag
++
;
authScheme
=
tAuth
;
rfbClientLog
(
"Selecting security type %d (%d/%d in the list)
\n
"
,
authScheme
,
loop
,
count
);
/* send back a single byte indicating which security type to use */
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
tAuth
,
1
))
return
FALSE
;
}
}
}
else
{
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
authScheme
,
4
))
return
FALSE
;
authScheme
=
rfbClientSwap32IfLE
(
authScheme
);
}
rfbClientLog
(
"Selected Security Scheme %d
\n
"
,
authScheme
);
switch
(
authScheme
)
{
...
...
@@ -338,9 +492,10 @@ InitialiseRFBConnection(rfbClient* client)
reason
=
malloc
(
reasonLen
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
return
FALSE
;
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
FALSE
;
}
rfbClientLog
(
"VNC connection failed: %.*s
\n
"
,(
int
)
reasonLen
,
reason
);
free
(
reason
);
return
FALSE
;
case
rfbNoAuth
:
...
...
@@ -382,6 +537,17 @@ InitialiseRFBConnection(rfbClient* client)
rfbClientLog
(
"VNC authentication succeeded
\n
"
);
break
;
case
rfbVncAuthFailed
:
if
(
client
->
major
==
3
&&
client
->
minor
>
7
)
{
/* we have an error following */
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
reasonLen
,
4
))
return
FALSE
;
reasonLen
=
rfbClientSwap32IfLE
(
reasonLen
);
reason
=
malloc
(
reasonLen
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
FALSE
;
}
rfbClientLog
(
"VNC connection failed: %.*s
\n
"
,(
int
)
reasonLen
,
reason
);
free
(
reason
);
return
FALSE
;
}
rfbClientLog
(
"VNC authentication failed
\n
"
);
return
FALSE
;
case
rfbVncAuthTooMany
:
...
...
@@ -427,7 +593,7 @@ InitialiseRFBConnection(rfbClient* client)
rfbClientLog
(
"Desktop name
\"
%s
\"\n
"
,
client
->
desktopName
);
rfbClientLog
(
"Connected to VNC server, using protocol version %d.%d
\n
"
,
rfbProtocolMajorVersion
,
rfbProtocolMinorVersion
);
client
->
major
,
client
->
minor
);
rfbClientLog
(
"VNC server default format:
\n
"
);
PrintPixelFormat
(
&
client
->
si
.
format
);
...
...
@@ -445,6 +611,7 @@ SetFormatAndEncodings(rfbClient* client)
{
rfbSetPixelFormatMsg
spf
;
char
buf
[
sz_rfbSetEncodingsMsg
+
MAX_ENCODINGS
*
4
];
rfbSetEncodingsMsg
*
se
=
(
rfbSetEncodingsMsg
*
)
buf
;
uint32_t
*
encs
=
(
uint32_t
*
)(
&
buf
[
sz_rfbSetEncodingsMsg
]);
int
len
=
0
;
...
...
@@ -453,6 +620,8 @@ SetFormatAndEncodings(rfbClient* client)
rfbBool
requestLastRectEncoding
=
FALSE
;
rfbClientProtocolExtension
*
e
;
if
(
!
SupportsClient2Server
(
client
,
rfbSetPixelFormat
))
return
TRUE
;
spf
.
type
=
rfbSetPixelFormat
;
spf
.
format
=
client
->
format
;
spf
.
format
.
redMax
=
rfbClientSwap16IfLE
(
spf
.
format
.
redMax
);
...
...
@@ -462,6 +631,9 @@ SetFormatAndEncodings(rfbClient* client)
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
spf
,
sz_rfbSetPixelFormatMsg
))
return
FALSE
;
if
(
!
SupportsClient2Server
(
client
,
rfbSetEncodings
))
return
TRUE
;
se
->
type
=
rfbSetEncodings
;
se
->
nEncodings
=
0
;
...
...
@@ -655,6 +827,8 @@ SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbB
{
rfbFramebufferUpdateRequestMsg
fur
;
if
(
!
SupportsClient2Server
(
client
,
rfbFramebufferUpdateRequest
))
return
TRUE
;
fur
.
type
=
rfbFramebufferUpdateRequest
;
fur
.
incremental
=
incremental
?
1
:
0
;
fur
.
x
=
rfbClientSwap16IfLE
(
x
);
...
...
@@ -677,19 +851,105 @@ SendScaleSetting(rfbClient* client,int scaleSetting)
{
rfbSetScaleMsg
ssm
;
if
(
client
->
appData
.
palmVNC
)
ssm
.
type
=
rfbPalmVNCSetScaleFactor
;
else
ssm
.
type
=
rfbSetScale
;
ssm
.
scale
=
scaleSetting
;
ssm
.
pad
=
0
;
/* favor UltraVNC SetScale if both are supported */
if
(
SupportsClient2Server
(
client
,
rfbSetScale
))
{
ssm
.
type
=
rfbSetScale
;
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
ssm
,
sz_rfbSetScaleMsg
))
return
FALSE
;
}
if
(
SupportsClient2Server
(
client
,
rfbPalmVNCSetScaleFactor
))
{
ssm
.
type
=
rfbPalmVNCSetScaleFactor
;
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
ssm
,
sz_rfbSetScaleMsg
))
return
FALSE
;
}
return
TRUE
;
}
/*
* TextChatFunctions (UltraVNC)
* Extremely bandwidth friendly method of communicating with a user
* (Think HelpDesk type applications)
*/
rfbBool
TextChatSend
(
rfbClient
*
client
,
char
*
text
)
{
rfbTextChatMsg
chat
;
int
count
=
strlen
(
text
);
if
(
!
SupportsClient2Server
(
client
,
rfbTextChat
))
return
TRUE
;
chat
.
type
=
rfbTextChat
;
chat
.
pad1
=
0
;
chat
.
pad2
=
0
;
chat
.
length
=
(
uint32_t
)
count
;
chat
.
length
=
rfbClientSwap32IfLE
(
chat
.
length
);
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
chat
,
sz_rfbTextChatMsg
))
return
FALSE
;
if
(
count
>
0
)
{
if
(
!
WriteToRFBServer
(
client
,
text
,
count
))
return
FALSE
;
}
return
TRUE
;
}
rfbBool
TextChatOpen
(
rfbClient
*
client
)
{
rfbTextChatMsg
chat
;
if
(
!
SupportsClient2Server
(
client
,
rfbTextChat
))
return
TRUE
;
chat
.
type
=
rfbTextChat
;
chat
.
pad1
=
0
;
chat
.
pad2
=
0
;
chat
.
length
=
rfbClientSwap32IfLE
(
rfbTextChatOpen
);
return
(
WriteToRFBServer
(
client
,
(
char
*
)
&
chat
,
sz_rfbTextChatMsg
)
?
TRUE
:
FALSE
);
}
rfbBool
TextChatClose
(
rfbClient
*
client
)
{
rfbTextChatMsg
chat
;
if
(
!
SupportsClient2Server
(
client
,
rfbTextChat
))
return
TRUE
;
chat
.
type
=
rfbTextChat
;
chat
.
pad1
=
0
;
chat
.
pad2
=
0
;
chat
.
length
=
rfbClientSwap32IfLE
(
rfbTextChatClose
);
return
(
WriteToRFBServer
(
client
,
(
char
*
)
&
chat
,
sz_rfbTextChatMsg
)
?
TRUE
:
FALSE
);
}
rfbBool
TextChatFinish
(
rfbClient
*
client
)
{
rfbTextChatMsg
chat
;
if
(
!
SupportsClient2Server
(
client
,
rfbTextChat
))
return
TRUE
;
chat
.
type
=
rfbTextChat
;
chat
.
pad1
=
0
;
chat
.
pad2
=
0
;
chat
.
length
=
rfbClientSwap32IfLE
(
rfbTextChatFinished
);
return
(
WriteToRFBServer
(
client
,
(
char
*
)
&
chat
,
sz_rfbTextChatMsg
)
?
TRUE
:
FALSE
);
}
/*
* UltraVNC Server Input Disable
* Apparently, the remote client can *prevent* the local user from interacting with the display
* I would think this is extremely helpful when used in a HelpDesk situation
*/
rfbBool
PermitServerInput
(
rfbClient
*
client
,
int
enabled
)
{
rfbSetServerInputMsg
msg
;
if
(
!
SupportsClient2Server
(
client
,
rfbSetServerInput
))
return
TRUE
;
/* enabled==1, then server input from local keyboard is disabled */
msg
.
type
=
rfbSetServerInput
;
msg
.
status
=
(
enabled
?
1
:
0
);
msg
.
pad
=
0
;
return
(
WriteToRFBServer
(
client
,
(
char
*
)
&
msg
,
sz_rfbSetServerInputMsg
)
?
TRUE
:
FALSE
);
}
/*
* SendPointerEvent.
*/
...
...
@@ -699,6 +959,8 @@ SendPointerEvent(rfbClient* client,int x, int y, int buttonMask)
{
rfbPointerEventMsg
pe
;
if
(
!
SupportsClient2Server
(
client
,
rfbPointerEvent
))
return
TRUE
;
pe
.
type
=
rfbPointerEvent
;
pe
.
buttonMask
=
buttonMask
;
if
(
x
<
0
)
x
=
0
;
...
...
@@ -719,6 +981,8 @@ SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down)
{
rfbKeyEventMsg
ke
;
if
(
!
SupportsClient2Server
(
client
,
rfbKeyEvent
))
return
TRUE
;
ke
.
type
=
rfbKeyEvent
;
ke
.
down
=
down
?
1
:
0
;
ke
.
key
=
rfbClientSwap32IfLE
(
key
);
...
...
@@ -739,6 +1003,8 @@ SendClientCutText(rfbClient* client, char *str, int len)
free
(
client
->
serverCutText
);
client
->
serverCutText
=
NULL
;
if
(
!
SupportsClient2Server
(
client
,
rfbClientCutText
))
return
TRUE
;
cct
.
type
=
rfbClientCutText
;
cct
.
length
=
rfbClientSwap32IfLE
(
len
);
return
(
WriteToRFBServer
(
client
,
(
char
*
)
&
cct
,
sz_rfbClientCutTextMsg
)
&&
...
...
@@ -858,9 +1124,8 @@ HandleRFBServerMessage(rfbClient* client)
/* rect.r.w=byte count */
if
(
rect
.
encoding
==
rfbEncodingSupportedMessages
)
{
rfbSupportedMessages
msgs
;
int
loop
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
msg
s
,
sz_rfbSupportedMessages
))
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
client
->
supportedMessage
s
,
sz_rfbSupportedMessages
))
return
FALSE
;
/* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
...
...
@@ -869,18 +1134,18 @@ HandleRFBServerMessage(rfbClient* client)
rfbClientLog
(
"client2server supported messages (bit flags)
\n
"
);
for
(
loop
=
0
;
loop
<
32
;
loop
+=
8
)
rfbClientLog
(
"%02X: %04x %04x %04x %04x - %04x %04x %04x %04x
\n
"
,
loop
,
msgs
.
client2server
[
loop
],
msg
s
.
client2server
[
loop
+
1
],
msgs
.
client2server
[
loop
+
2
],
msg
s
.
client2server
[
loop
+
3
],
msgs
.
client2server
[
loop
+
4
],
msg
s
.
client2server
[
loop
+
5
],
msgs
.
client2server
[
loop
+
6
],
msg
s
.
client2server
[
loop
+
7
]);
client
->
supportedMessages
.
client2server
[
loop
],
client
->
supportedMessage
s
.
client2server
[
loop
+
1
],
client
->
supportedMessages
.
client2server
[
loop
+
2
],
client
->
supportedMessage
s
.
client2server
[
loop
+
3
],
client
->
supportedMessages
.
client2server
[
loop
+
4
],
client
->
supportedMessage
s
.
client2server
[
loop
+
5
],
client
->
supportedMessages
.
client2server
[
loop
+
6
],
client
->
supportedMessage
s
.
client2server
[
loop
+
7
]);
rfbClientLog
(
"server2client supported messages (bit flags)
\n
"
);
for
(
loop
=
0
;
loop
<
32
;
loop
+=
8
)
rfbClientLog
(
"%02X: %04x %04x %04x %04x - %04x %04x %04x %04x
\n
"
,
loop
,
msgs
.
server2client
[
loop
],
msg
s
.
server2client
[
loop
+
1
],
msgs
.
server2client
[
loop
+
2
],
msg
s
.
server2client
[
loop
+
3
],
msgs
.
server2client
[
loop
+
4
],
msg
s
.
server2client
[
loop
+
5
],
msgs
.
server2client
[
loop
+
6
],
msg
s
.
server2client
[
loop
+
7
]);
client
->
supportedMessages
.
server2client
[
loop
],
client
->
supportedMessage
s
.
server2client
[
loop
+
1
],
client
->
supportedMessages
.
server2client
[
loop
+
2
],
client
->
supportedMessage
s
.
server2client
[
loop
+
3
],
client
->
supportedMessages
.
server2client
[
loop
+
4
],
client
->
supportedMessage
s
.
server2client
[
loop
+
5
],
client
->
supportedMessages
.
server2client
[
loop
+
6
],
client
->
supportedMessage
s
.
server2client
[
loop
+
7
]);
continue
;
}
...
...
@@ -1217,6 +1482,47 @@ HandleRFBServerMessage(rfbClient* client)
break
;
}
case
rfbTextChat
:
{
char
*
buffer
=
NULL
;
if
(
!
ReadFromRFBServer
(
client
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbTextChatMsg
-
1
))
return
FALSE
;
msg
.
tc
.
length
=
rfbClientSwap32IfLE
(
msg
.
sct
.
length
);
switch
(
msg
.
tc
.
length
)
{
case
rfbTextChatOpen
:
rfbClientLog
(
"Received TextChat Open
\n
"
);
if
(
client
->
HandleTextChat
!=
NULL
)
client
->
HandleTextChat
(
client
,
(
int
)
rfbTextChatOpen
,
NULL
);
break
;
case
rfbTextChatClose
:
rfbClientLog
(
"Received TextChat Close
\n
"
);
if
(
client
->
HandleTextChat
!=
NULL
)
client
->
HandleTextChat
(
client
,
(
int
)
rfbTextChatClose
,
NULL
);
break
;
case
rfbTextChatFinished
:
rfbClientLog
(
"Received TextChat Finished
\n
"
);
if
(
client
->
HandleTextChat
!=
NULL
)
client
->
HandleTextChat
(
client
,
(
int
)
rfbTextChatFinished
,
NULL
);
break
;
default:
buffer
=
malloc
(
msg
.
tc
.
length
+
1
);
if
(
!
ReadFromRFBServer
(
client
,
buffer
,
msg
.
tc
.
length
))
{
free
(
buffer
);
return
FALSE
;
}
/* Null Terminate <just in case> */
buffer
[
msg
.
tc
.
length
]
=
0
;
rfbClientLog
(
"Received TextChat
\"
%s
\"\n
"
,
buffer
);
if
(
client
->
HandleTextChat
!=
NULL
)
client
->
HandleTextChat
(
client
,
(
int
)
msg
.
tc
.
length
,
buffer
);
free
(
buffer
);
break
;
}
break
;
}
case
rfbResizeFrameBuffer
:
{
if
(
!
ReadFromRFBServer
(
client
,
((
char
*
)
&
msg
)
+
1
,
...
...
libvncclient/ultra.c
View file @
ccdbe8f3
...
...
@@ -18,8 +18,6 @@
* USA.
*/
#ifdef LIBVNCSERVER_HAVE_LIBZ
/*
* ultrazip.c - handle ultrazip encoding.
*
...
...
@@ -210,5 +208,3 @@ HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh)
}
#undef CARDBPP
#endif
libvncclient/zrle.c
View file @
ccdbe8f3
...
...
@@ -377,7 +377,7 @@ static int HandleZRLETile(rfbClient* client,
#undef HandleZRLETile
#undef UncompressCPixel
#undef REALBPP
#undef UNCOMP
#endif
#undef UNCOMP
libvncserver/auth.c
View file @
ccdbe8f3
...
...
@@ -317,6 +317,11 @@ rfbAuthProcessClientMessage(rfbClientPtr cl)
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
)
{
rfbClientConnFailed
(
cl
,
"password check failed!"
);
}
else
rfbCloseClient
(
cl
);
return
;
}
...
...
libvncserver/corre.c
View file @
ccdbe8f3
...
...
@@ -41,7 +41,7 @@ static char *rreBeforeBuf = NULL;
static
int
rreAfterBufSize
=
0
;
static
char
*
rreAfterBuf
=
NULL
;
static
int
rreAfterBufLen
;
static
int
rreAfterBufLen
=
0
;
static
int
subrectEncode8
(
uint8_t
*
data
,
int
w
,
int
h
);
static
int
subrectEncode16
(
uint16_t
*
data
,
int
w
,
int
h
);
...
...
@@ -145,9 +145,9 @@ rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
return
rfbSendRectEncodingRaw
(
cl
,
x
,
y
,
w
,
h
);
}
cl
->
rectanglesSent
[
rfbEncodingCoRRE
]
++
;
cl
->
bytesSent
[
rfbEncodingCoRRE
]
+=
(
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
+
rreAfterBufLen
);
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingCoRRE
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
+
rreAfterBufLen
,
sz_rfbFramebufferUpdateRectHeader
+
w
*
h
*
(
cl
->
format
.
bitsPerPixel
/
8
)
);
if
(
cl
->
ublen
+
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
>
UPDATE_BUF_SIZE
)
...
...
libvncserver/cursor.c
View file @
ccdbe8f3
...
...
@@ -78,9 +78,6 @@ rfbSendCursorShape(rfbClientPtr cl)
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorShapeBytesSent
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorShapeUpdatesSent
++
;
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
@@ -167,9 +164,8 @@ rfbSendCursorShape(rfbClientPtr cl)
}
/* Send everything we have prepared in the cl->updateBuf[]. */
cl
->
cursorShapeBytesSent
+=
(
cl
->
ublen
-
saved_ublen
);
cl
->
cursorShapeUpdatesSent
++
;
rfbStatRecordMessageSent
(
cl
,
(
cl
->
useRichCursorEncoding
?
rfbEncodingRichCursor
:
rfbEncodingXCursor
),
sz_rfbFramebufferUpdateRectHeader
+
(
cl
->
ublen
-
saved_ublen
),
sz_rfbFramebufferUpdateRectHeader
+
(
cl
->
ublen
-
saved_ublen
));
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
@@ -201,8 +197,7 @@ rfbSendCursorPos(rfbClientPtr cl)
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorPosBytesSent
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorPosUpdatesSent
++
;
rfbStatRecordMessageSent
(
cl
,
rfbEncodingPointerPos
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
);
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
libvncserver/hextile.c
View file @
ccdbe8f3
...
...
@@ -60,8 +60,9 @@ rfbSendRectEncodingHextile(rfbClientPtr cl,
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
rectanglesSent
[
rfbEncodingHextile
]
++
;
cl
->
bytesSent
[
rfbEncodingHextile
]
+=
sz_rfbFramebufferUpdateRectHeader
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingHextile
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
+
w
*
(
cl
->
format
.
bitsPerPixel
/
8
)
*
h
);
switch
(
cl
->
format
.
bitsPerPixel
)
{
case
8
:
...
...
@@ -136,6 +137,7 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
startUblen = cl->ublen; \
cl->updateBuf[startUblen] = 0; \
cl->ublen++; \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
testColours##bpp(clientPixelData, w * h, \
&mono, &solid, &newBg, &newFg); \
...
...
@@ -148,7 +150,6 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
} \
\
if (solid) { \
cl->bytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
continue; \
} \
\
...
...
@@ -181,9 +182,9 @@ sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) {
w * h * (bpp/8)); \
\
cl->ublen += w * h * (bpp/8); \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
w * h * (bpp/8)); \
} \
\
cl->bytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
} \
} \
\
...
...
@@ -210,6 +211,7 @@ subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h,
\
nSubrectsUblen = cl->ublen; \
cl->ublen++; \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
for (y=0; y<h; y++) { \
line = data+(y*w); \
...
...
@@ -268,6 +270,7 @@ subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h,
\
cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
\
/* \
* Now mark the subrect as done. \
...
...
libvncserver/main.c
View file @
ccdbe8f3
...
...
@@ -495,22 +495,40 @@ clientInput(void *data)
pthread_create
(
&
output_thread
,
NULL
,
clientOutput
,
(
void
*
)
cl
);
while
(
1
)
{
fd_set
fds
;
fd_set
rfds
,
wfds
,
e
fds
;
struct
timeval
tv
;
int
n
;
FD_ZERO
(
&
fds
);
FD_SET
(
cl
->
sock
,
&
fds
);
FD_ZERO
(
&
rfds
);
FD_SET
(
cl
->
sock
,
&
rfds
);
FD_ZERO
(
&
efds
);
FD_SET
(
cl
->
sock
,
&
efds
);
/* Are we transferring a file in the background? */
FD_ZERO
(
&
wfds
);
if
((
cl
->
fileTransfer
.
fd
!=-
1
)
&&
(
cl
->
fileTransfer
.
sending
==
1
))
FD_SET
(
cl
->
sock
,
&
wfds
);
tv
.
tv_sec
=
60
;
/* 1 minute */
tv
.
tv_usec
=
0
;
n
=
select
(
cl
->
sock
+
1
,
&
fds
,
NULL
,
&
fds
,
&
tv
);
n
=
select
(
cl
->
sock
+
1
,
&
rfds
,
&
wfds
,
&
e
fds
,
&
tv
);
if
(
n
<
0
)
{
rfbLogPerror
(
"ReadExact: select"
);
break
;
}
if
(
n
==
0
)
/* timeout */
{
rfbSendFileTransferChunk
(
cl
);
continue
;
}
/* We have some space on the transmit queue, send some data */
if
(
FD_ISSET
(
cl
->
sock
,
&
wfds
))
rfbSendFileTransferChunk
(
cl
);
if
(
FD_ISSET
(
cl
->
sock
,
&
rfds
)
||
FD_ISSET
(
cl
->
sock
,
&
efds
))
rfbProcessClientMessage
(
cl
);
if
(
cl
->
sock
==
-
1
)
{
/* Client has disconnected. */
break
;
...
...
@@ -818,6 +836,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen
->
handleEventsEagerly
=
FALSE
;
/* Emulate UltraVNC Server by default */
screen
->
protocolMajorVersion
=
3
;
screen
->
protocolMinorVersion
=
6
;
if
(
!
rfbProcessArguments
(
screen
,
argc
,
argv
))
{
free
(
screen
);
return
NULL
;
...
...
libvncserver/rfbserver.c
View file @
ccdbe8f3
...
...
@@ -66,6 +66,14 @@
#endif
#include <stdarg.h>
#include <scale.h>
/* stst() */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* readdir() */
#include <dirent.h>
/* errno */
#include <errno.h>
static
void
rfbProcessClientProtocolVersion
(
rfbClientPtr
cl
);
static
void
rfbProcessClientNormalMessage
(
rfbClientPtr
cl
);
...
...
@@ -229,6 +237,20 @@ rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
}
void
rfbSetProtocolVersion
(
rfbScreenInfoPtr
rfbScreen
,
int
major_
,
int
minor_
)
{
/* Permit the server to set the version to report */
/* TODO: sanity checking */
if
((
major_
==
3
)
&&
(
minor_
>
2
&&
minor_
<
9
))
{
rfbScreen
->
protocolMajorVersion
=
major_
;
rfbScreen
->
protocolMinorVersion
=
minor_
;
}
else
rfbLog
(
"rfbSetProtocolVersion(%d,%d) set to invalid values
\n
"
,
major_
,
minor_
);
}
/*
* rfbNewClient is called when a new connection has been made by whatever
* means.
...
...
@@ -348,6 +370,8 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
#endif
#endif
cl
->
fileTransfer
.
fd
=
-
1
;
cl
->
enableCursorShapeUpdates
=
FALSE
;
cl
->
enableCursorPosUpdates
=
FALSE
;
cl
->
useRichCursorEncoding
=
FALSE
;
...
...
@@ -378,8 +402,8 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
cl
->
lastPtrX
=
-
1
;
sprintf
(
pv
,
rfbProtocolVersionFormat
,
rfb
ProtocolMajorVersion
,
rfbP
rotocolMinorVersion
);
sprintf
(
pv
,
rfbProtocolVersionFormat
,
rfb
Screen
->
protocolMajorVersion
,
rfbScreen
->
p
rotocolMinorVersion
);
if
(
rfbWriteExact
(
cl
,
pv
,
sz_rfbProtocolVersionMsg
)
<
0
)
{
rfbLogPerror
(
"rfbNewClient: write"
);
...
...
@@ -583,7 +607,7 @@ rfbProcessClientProtocolVersion(rfbClientPtr cl)
free
(
cl
->
host
);
cl
->
host
=
strdup
(
name
);
}
rfbLog
(
"
Protocol v
ersion %d.%d
\n
"
,
major_
,
minor_
);
rfbLog
(
"
Client Protocol V
ersion %d.%d
\n
"
,
major_
,
minor_
);
if
(
major_
!=
rfbProtocolMajorVersion
)
{
/* Major version mismatch - send a ConnFailed message */
...
...
@@ -591,23 +615,24 @@ rfbProcessClientProtocolVersion(rfbClientPtr cl)
rfbErr
(
"Major version mismatch
\n
"
);
sprintf
(
failureReason
,
"RFB protocol version mismatch - server %d.%d, client %d.%d"
,
rfbProtocolMajorVersion
,
rfbProtocolMinorVersion
,
major_
,
minor_
);
cl
->
screen
->
protocolMajorVersion
,
cl
->
screen
->
protocolMinorVersion
,
major_
,
minor_
);
rfbClientConnFailed
(
cl
,
failureReason
);
return
;
}
/* Chk for the minor version use either of the two standard version of RFB */
/* Check for the minor version use either of the two standard version of RFB */
/*
* UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
* 3.4, 3.6, 3.14, 3.16
* It's a bad method, but it is what they use to enable features...
* maintaining RFB version compatibility across multiple servers is a pain
* Should use something like ServerIdentity encoding
*/
cl
->
protocolMinorVersion
=
minor_
;
if
(
minor_
>
rfbProtocolMinorVersion
)
{
cl
->
protocolMinorVersion
=
rfbProtocolMinorVersion
;
}
else
if
(
minor_
<
rfbProtocolMinorVersion
)
{
cl
->
protocolMinorVersion
=
rfbProtocolFallbackMinorVersion
;
}
if
(
minor_
!=
rfbProtocolMinorVersion
&&
minor_
!=
rfbProtocolFallbackMinorVersion
)
{
rfbLog
(
"Non-standard protocol version %d.%d, using %d.%d instead
\n
"
,
rfbLog
(
"Protocol version sent %d.%d, using %d.%d
\n
"
,
major_
,
minor_
,
rfbProtocolMajorVersion
,
cl
->
protocolMinorVersion
);
}
rfbAuthNewClient
(
cl
);
}
...
...
@@ -775,8 +800,7 @@ rfbSendKeyboardLedState(rfbClientPtr cl)
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorPosBytesSent
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
cursorPosUpdatesSent
++
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingKeyboardLedState
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
);
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
@@ -806,7 +830,7 @@ rfbSendSupportedMessages(rfbClientPtr cl)
rect
.
encoding
=
Swap32IfLE
(
rfbEncodingSupportedMessages
);
rect
.
r
.
x
=
0
;
rect
.
r
.
y
=
0
;
rect
.
r
.
w
=
Swap16IfLE
(
sz_rfb
FramebufferUpdateRectHeader
);
rect
.
r
.
w
=
Swap16IfLE
(
sz_rfb
SupportedMessages
);
rect
.
r
.
h
=
0
;
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
(
char
*
)
&
rect
,
...
...
@@ -823,10 +847,10 @@ rfbSendSupportedMessages(rfbClientPtr cl)
rfbSetBit
(
msgs
.
client2server
,
rfbClientCutText
);
rfbSetBit
(
msgs
.
client2server
,
rfbFileTransfer
);
rfbSetBit
(
msgs
.
client2server
,
rfbSetScale
);
/
/rfbSetBit(msgs.client2server, rfbSetServerInput);
/
/rfbSetBit(msgs.client2server, rfbSetSW);
/
/rfbSetBit(msgs.client2server, rfbTextChat);
/
/rfbSetBit(msgs.client2server, rfbKeyFrameRequest);
/
*rfbSetBit(msgs.client2server, rfbSetServerInput); */
/
*rfbSetBit(msgs.client2server, rfbSetSW); */
/
*rfbSetBit(msgs.client2server, rfbTextChat); */
/
*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */
rfbSetBit
(
msgs
.
client2server
,
rfbPalmVNCSetScaleFactor
);
rfbSetBit
(
msgs
.
server2client
,
rfbFramebufferUpdate
);
...
...
@@ -834,12 +858,15 @@ rfbSendSupportedMessages(rfbClientPtr cl)
rfbSetBit
(
msgs
.
server2client
,
rfbBell
);
rfbSetBit
(
msgs
.
server2client
,
rfbServerCutText
);
rfbSetBit
(
msgs
.
server2client
,
rfbResizeFrameBuffer
);
/
/rfbSetBit(msgs.server2client, rfbKeyFrameUpdate);
/
*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */
rfbSetBit
(
msgs
.
server2client
,
rfbPalmVNCReSizeFrameBuffer
);
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
(
char
*
)
&
msgs
,
sz_rfbSupportedMessages
);
cl
->
ublen
+=
sz_rfbSupportedMessages
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingSupportedMessages
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbSupportedMessages
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbSupportedMessages
);
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
@@ -918,6 +945,10 @@ rfbSendSupportedEncodings(rfbClientPtr cl)
rfbSendSupporteddEncodings_SendEncoding
(
cl
,
rfbEncodingSupportedEncodings
);
rfbSendSupporteddEncodings_SendEncoding
(
cl
,
rfbEncodingServerIdentity
);
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingSupportedEncodings
,
sz_rfbFramebufferUpdateRectHeader
+
(
nEncodings
*
sizeof
(
uint32_t
)),
sz_rfbFramebufferUpdateRectHeader
+
(
nEncodings
*
sizeof
(
uint32_t
)));
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
...
...
@@ -973,16 +1004,654 @@ rfbSendServerIdentity(rfbClientPtr cl)
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
buffer
,
strlen
(
buffer
)
+
1
);
cl
->
ublen
+=
strlen
(
buffer
)
+
1
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingServerIdentity
,
sz_rfbFramebufferUpdateRectHeader
+
strlen
(
buffer
)
+
1
,
sz_rfbFramebufferUpdateRectHeader
+
strlen
(
buffer
)
+
1
);
if
(
!
rfbSendUpdateBuf
(
cl
))
return
FALSE
;
return
TRUE
;
}
rfbBool
rfbSendFileTransferMessage
(
rfbClientPtr
cl
,
uint8_t
contentType
,
uint8_t
contentParam
,
uint32_t
size
,
uint32_t
length
,
char
*
buffer
)
{
rfbFileTransferMsg
ft
;
ft
.
type
=
rfbFileTransfer
;
ft
.
contentType
=
contentType
;
ft
.
contentParam
=
contentParam
;
ft
.
pad
=
0
;
/* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */
ft
.
size
=
Swap32IfLE
(
size
);
ft
.
length
=
Swap32IfLE
(
length
);
/*
rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer);
*/
if
(
rfbWriteExact
(
cl
,
(
char
*
)
&
ft
,
sz_rfbFileTransferMsg
)
<
0
)
{
rfbLogPerror
(
"rfbSendFileTransferMessage: write"
);
rfbCloseClient
(
cl
);
return
FALSE
;
}
if
(
length
>
0
)
{
if
(
rfbWriteExact
(
cl
,
buffer
,
length
)
<
0
)
{
rfbLogPerror
(
"rfbSendFileTransferMessage: write"
);
rfbCloseClient
(
cl
);
return
FALSE
;
}
}
rfbStatRecordMessageSent
(
cl
,
rfbFileTransfer
,
sz_rfbFileTransferMsg
+
length
,
sz_rfbFileTransferMsg
+
length
);
return
TRUE
;
}
/*
* UltraVNC uses Windows Structures
*/
#define MAX_PATH 260
typedef
struct
_FILETIME
{
uint32_t
dwLowDateTime
;
uint32_t
dwHighDateTime
;
}
FILETIME
;
typedef
struct
_WIN32_FIND_DATA
{
uint32_t
dwFileAttributes
;
FILETIME
ftCreationTime
;
FILETIME
ftLastAccessTime
;
FILETIME
ftLastWriteTime
;
uint32_t
nFileSizeHigh
;
uint32_t
nFileSizeLow
;
uint32_t
dwReserved0
;
uint32_t
dwReserved1
;
uint8_t
cFileName
[
MAX_PATH
];
uint8_t
cAlternateFileName
[
14
];
}
WIN32_FIND_DATA
;
#define FILE_ATTRIBUTE_READONLY 0x1
#define FILE_ATTRIBUTE_HIDDEN 0x2
#define FILE_ATTRIBUTE_SYSTEM 0x4
#define FILE_ATTRIBUTE_DIRECTORY 0x10
#define FILE_ATTRIBUTE_ARCHIVE 0x20
#define FILE_ATTRIBUTE_NORMAL 0x80
#define FILE_ATTRIBUTE_TEMPORARY 0x100
#define FILE_ATTRIBUTE_COMPRESSED 0x800
rfbBool
rfbFilenameTranslate2UNIX
(
rfbClientPtr
cl
,
char
*
path
,
char
*
unixPath
)
{
int
x
;
char
*
home
=
NULL
;
/* C: */
if
(
path
[
0
]
==
'C'
&&
path
[
1
]
==
':'
)
strcpy
(
unixPath
,
&
path
[
2
]);
else
{
home
=
getenv
(
"HOME"
);
if
(
home
!=
NULL
)
{
strcpy
(
unixPath
,
home
);
strcat
(
unixPath
,
"/"
);
strcat
(
unixPath
,
path
);
}
else
strcpy
(
unixPath
,
path
);
}
for
(
x
=
0
;
x
<
strlen
(
unixPath
);
x
++
)
if
(
unixPath
[
x
]
==
'\\'
)
unixPath
[
x
]
=
'/'
;
return
TRUE
;
}
rfbBool
rfbFilenameTranslate2DOS
(
rfbClientPtr
cl
,
char
*
unixPath
,
char
*
path
)
{
int
x
;
sprintf
(
path
,
"C:%s"
,
unixPath
);
for
(
x
=
2
;
x
<
strlen
(
path
);
x
++
)
if
(
path
[
x
]
==
'/'
)
path
[
x
]
=
'\\'
;
return
TRUE
;
}
rfbBool
rfbSendDirContent
(
rfbClientPtr
cl
,
int
length
,
char
*
buffer
)
{
char
retfilename
[
MAX_PATH
];
char
path
[
MAX_PATH
];
struct
stat
statbuf
;
WIN32_FIND_DATA
win32filename
;
int
nOptLen
=
0
,
retval
=
0
;
DIR
*
dirp
=
NULL
;
struct
dirent
*
direntp
=
NULL
;
/* Client thinks we are Winblows */
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
path
);
// /*
rfbLog
(
"rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent:
\"
%s
\"
->
\"
%s
\"\n
"
,
buffer
,
path
);
// */
dirp
=
opendir
(
path
);
if
(
dirp
==
NULL
)
return
rfbSendFileTransferMessage
(
cl
,
rfbDirPacket
,
rfbADirectory
,
0
,
0
,
NULL
);
/* send back the path name (necessary for links) */
if
(
rfbSendFileTransferMessage
(
cl
,
rfbDirPacket
,
rfbADirectory
,
0
,
length
,
buffer
)
==
FALSE
)
return
FALSE
;
for
(
direntp
=
readdir
(
dirp
);
direntp
!=
NULL
;
direntp
=
readdir
(
dirp
))
{
/* get stats */
snprintf
(
retfilename
,
sizeof
(
retfilename
),
"%s/%s"
,
path
,
direntp
->
d_name
);
retval
=
stat
(
retfilename
,
&
statbuf
);
if
(
retval
==
0
)
{
memset
((
char
*
)
&
win32filename
,
0
,
sizeof
(
win32filename
));
win32filename
.
dwFileAttributes
=
Swap32IfBE
(
FILE_ATTRIBUTE_NORMAL
);
if
(
S_ISDIR
(
statbuf
.
st_mode
))
win32filename
.
dwFileAttributes
=
Swap32IfBE
(
FILE_ATTRIBUTE_DIRECTORY
);
win32filename
.
ftCreationTime
.
dwLowDateTime
=
Swap32IfBE
(
statbuf
.
st_ctime
);
/* Intel Order */
win32filename
.
ftCreationTime
.
dwHighDateTime
=
0
;
win32filename
.
ftLastAccessTime
.
dwLowDateTime
=
Swap32IfBE
(
statbuf
.
st_atime
);
/* Intel Order */
win32filename
.
ftLastAccessTime
.
dwHighDateTime
=
0
;
win32filename
.
ftLastWriteTime
.
dwLowDateTime
=
Swap32IfBE
(
statbuf
.
st_mtime
);
/* Intel Order */
win32filename
.
ftLastWriteTime
.
dwHighDateTime
=
0
;
win32filename
.
nFileSizeLow
=
Swap32IfBE
(
statbuf
.
st_size
);
/* Intel Order */
win32filename
.
nFileSizeHigh
=
0
;
win32filename
.
dwReserved0
=
0
;
win32filename
.
dwReserved1
=
0
;
/* If this had the full path, we would need to translate to DOS format ("C:\") */
/* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
strcpy
((
char
*
)
win32filename
.
cFileName
,
direntp
->
d_name
);
/* Do not show hidden files (but show how to move up the tree) */
if
((
strcmp
(
direntp
->
d_name
,
".."
)
==
0
)
||
(
direntp
->
d_name
[
0
]
!=
'.'
))
{
nOptLen
=
sizeof
(
WIN32_FIND_DATA
)
-
MAX_PATH
-
14
+
strlen
((
char
*
)
win32filename
.
cFileName
);
/*
rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
*/
if
(
rfbSendFileTransferMessage
(
cl
,
rfbDirPacket
,
rfbADirectory
,
0
,
nOptLen
,
(
char
*
)
&
win32filename
)
==
FALSE
)
return
FALSE
;
}
}
}
closedir
(
dirp
);
/* End of the transfer */
return
rfbSendFileTransferMessage
(
cl
,
rfbDirPacket
,
0
,
0
,
0
,
NULL
);
}
char
*
rfbProcessFileTransferReadBuffer
(
rfbClientPtr
cl
,
uint32_t
length
)
{
char
*
buffer
=
NULL
;
int
n
=
0
;
/*
rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
*/
if
(
length
>
0
)
{
buffer
=
malloc
(
length
+
1
);
if
(
buffer
!=
NULL
)
{
if
((
n
=
rfbReadExact
(
cl
,
(
char
*
)
buffer
,
length
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessFileTransferReadBuffer: read"
);
rfbCloseClient
(
cl
);
/* NOTE: don't forget to free(buffer) if you return early! */
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
NULL
;
}
/* Null Terminate */
buffer
[
length
]
=
0
;
}
}
return
buffer
;
}
rfbBool
rfbSendFileTransferChunk
(
rfbClientPtr
cl
)
{
/* Allocate buffer for compression */
unsigned
char
readBuf
[
sz_rfbBlockSize
];
int
bytesRead
=
0
;
int
retval
=
0
;
fd_set
wfds
;
struct
timeval
tv
;
int
n
;
#ifdef LIBVNCSERVER_HAVE_LIBZ
unsigned
char
compBuf
[
sz_rfbBlockSize
+
1024
];
unsigned
long
nMaxCompSize
=
sizeof
(
compBuf
);
int
nRetC
=
0
;
#endif
/* If not sending, or no file open... Return as if we sent something! */
if
((
cl
->
fileTransfer
.
fd
!=-
1
)
&&
(
cl
->
fileTransfer
.
sending
==
1
))
{
FD_ZERO
(
&
wfds
);
FD_SET
(
cl
->
sock
,
&
wfds
);
/* return immediately */
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
0
;
n
=
select
(
cl
->
sock
+
1
,
NULL
,
&
wfds
,
NULL
,
&
tv
);
if
(
n
<
1
)
rfbLog
(
"rfbSendFileTransferChunk() select failed: %s
\n
"
,
strerror
(
errno
));
/* We have space on the transmit queue */
if
(
n
>
0
)
{
bytesRead
=
read
(
cl
->
fileTransfer
.
fd
,
readBuf
,
sz_rfbBlockSize
);
switch
(
bytesRead
)
{
case
0
:
/*
rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
*/
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbEndOfFile
,
0
,
0
,
0
,
NULL
);
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=
-
1
;
cl
->
fileTransfer
.
sending
=
0
;
cl
->
fileTransfer
.
receiving
=
0
;
return
retval
;
case
-
1
:
/* TODO : send an error msg to the client... */
rfbLog
(
"rfbSendFileTransferChunk(): %s
\n
"
,
strerror
(
errno
));
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbAbortFileTransfer
,
0
,
0
,
0
,
NULL
);
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=
-
1
;
cl
->
fileTransfer
.
sending
=
0
;
cl
->
fileTransfer
.
receiving
=
0
;
return
retval
;
default:
/*
rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
*/
if
(
!
cl
->
fileTransfer
.
compressionEnabled
)
return
rfbSendFileTransferMessage
(
cl
,
rfbFilePacket
,
0
,
0
,
bytesRead
,
(
char
*
)
readBuf
);
else
{
#ifdef LIBVNCSERVER_HAVE_LIBZ
nRetC
=
compress
(
compBuf
,
&
nMaxCompSize
,
readBuf
,
bytesRead
);
/*
rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
*/
if
((
nRetC
==
0
)
&&
(
nMaxCompSize
<
bytesRead
))
return
rfbSendFileTransferMessage
(
cl
,
rfbFilePacket
,
0
,
1
,
nMaxCompSize
,
(
char
*
)
compBuf
);
else
return
rfbSendFileTransferMessage
(
cl
,
rfbFilePacket
,
0
,
0
,
bytesRead
,
(
char
*
)
readBuf
);
#else
/* We do not support compression of the data stream */
return
rfbSendFileTransferMessage
(
cl
,
rfbFilePacket
,
0
,
0
,
bytesRead
,
(
char
*
)
readBuf
);
#endif
}
}
}
}
return
TRUE
;
}
rfbBool
rfbProcessFileTransfer
(
rfbClientPtr
cl
,
uint8_t
contentType
,
uint8_t
contentParam
,
uint32_t
size
,
uint32_t
length
)
{
char
*
buffer
=
NULL
,
*
p
=
NULL
;
int
retval
=
0
;
char
filename1
[
MAX_PATH
];
char
filename2
[
MAX_PATH
];
char
szFileTime
[
MAX_PATH
];
struct
stat
statbuf
;
uint32_t
sizeHtmp
=
0
;
int
n
=
0
;
char
timespec
[
64
];
#ifdef LIBVNCSERVER_HAVE_LIBZ
unsigned
char
compBuff
[
sz_rfbBlockSize
];
unsigned
long
nRawBytes
=
sz_rfbBlockSize
;
int
nRet
=
0
;
#endif
/*
rfbLog("rfbProcessFileTransfer(%dtype, %dparam, %dsize, %dlen)\n", contentType, contentParam, size, length);
*/
switch
(
contentType
)
{
case
rfbDirContentRequest
:
switch
(
contentParam
)
{
case
rfbRDrivesList
:
/* Client requests the List of Local Drives */
/*
rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDrivesList:\n");
*/
/* Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>
*
* We replace the "\" char following the drive letter and ":"
* with a char corresponding to the type of drive
* We obtain something like "C:l<NULL>D:c<NULL>....Z:n\<NULL><NULL>"
* Isn't it ugly ?
* DRIVE_FIXED = 'l' (local?)
* DRIVE_REMOVABLE = 'f' (floppy?)
* DRIVE_CDROM = 'c'
* DRIVE_REMOTE = 'n'
*/
/* in unix, there are no 'drives' (We could list mount points though)
* We fake the root as a "C:" for the Winblows users
*/
filename2
[
0
]
=
'C'
;
filename2
[
1
]
=
':'
;
filename2
[
2
]
=
'l'
;
filename2
[
3
]
=
0
;
filename2
[
4
]
=
0
;
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbDirPacket
,
rfbADrivesList
,
0
,
5
,
filename2
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
break
;
case
rfbRDirContent
:
/* Client requests the content of a directory */
/*
rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n");
*/
if
((
buffer
=
rfbProcessFileTransferReadBuffer
(
cl
,
length
))
==
NULL
)
return
FALSE
;
retval
=
rfbSendDirContent
(
cl
,
length
,
buffer
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
}
break
;
case
rfbDirPacket
:
rfbLog
(
"rfbProcessFileTransfer() rfbDirPacket
\n
"
);
break
;
case
rfbFileAcceptHeader
:
rfbLog
(
"rfbProcessFileTransfer() rfbFileAcceptHeader
\n
"
);
break
;
case
rfbCommandReturn
:
rfbLog
(
"rfbProcessFileTransfer() rfbCommandReturn
\n
"
);
break
;
case
rfbFileChecksums
:
/* Destination file already exists - the viewer sends the checksums */
rfbLog
(
"rfbProcessFileTransfer() rfbFileChecksums
\n
"
);
break
;
case
rfbFileTransferAccess
:
rfbLog
(
"rfbProcessFileTransfer() rfbFileTransferAccess
\n
"
);
break
;
/*
* sending from the server to the viewer
*/
case
rfbFileTransferRequest
:
/*
rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n");
*/
/* add some space to the end of the buffer as we will be adding a timespec to it */
if
((
buffer
=
rfbProcessFileTransferReadBuffer
(
cl
,
length
))
==
NULL
)
return
FALSE
;
/* The client requests a File */
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
filename1
);
cl
->
fileTransfer
.
fd
=
open
(
filename1
,
O_RDONLY
,
0744
);
/*
rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"));
*/
if
(
cl
->
fileTransfer
.
fd
!=-
1
)
{
if
(
fstat
(
cl
->
fileTransfer
.
fd
,
&
statbuf
)
!=
0
)
{
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=-
1
;
}
else
{
/* Add the File Time Stamp to the filename */
strftime
(
timespec
,
sizeof
(
timespec
),
"%m/%d/%Y %H:%M"
,
gmtime
(
&
statbuf
.
st_ctime
));
buffer
=
realloc
(
buffer
,
length
+
strlen
(
timespec
)
+
2
);
/* comma, and Null term */
if
(
buffer
==
NULL
)
{
rfbLog
(
"rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes
\n
"
,
length
+
strlen
(
timespec
)
+
2
);
return
FALSE
;
}
strcat
(
buffer
,
","
);
strcat
(
buffer
,
timespec
);
length
=
strlen
(
buffer
);
}
}
/* The viewer supports compression if size==1 */
cl
->
fileTransfer
.
compressionEnabled
=
(
size
==
1
);
/*
rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" <Compression Enabled>":""));
*/
/* File Size in bytes, 0xFFFFFFFF (-1) means error */
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbFileHeader
,
0
,
(
cl
->
fileTransfer
.
fd
==-
1
?
-
1
:
statbuf
.
st_size
),
length
,
buffer
);
if
(
cl
->
fileTransfer
.
fd
==-
1
)
{
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
}
/* setup filetransfer stuff */
cl
->
fileTransfer
.
fileSize
=
statbuf
.
st_size
;
cl
->
fileTransfer
.
numPackets
=
statbuf
.
st_size
/
sz_rfbBlockSize
;
cl
->
fileTransfer
.
receiving
=
0
;
cl
->
fileTransfer
.
sending
=
0
;
/* set when we receive a rfbFileHeader: */
/* TODO: finish 64-bit file size support */
sizeHtmp
=
0
;
if
(
rfbWriteExact
(
cl
,
(
char
*
)
&
sizeHtmp
,
4
)
<
0
)
{
rfbLogPerror
(
"rfbProcessFileTransfer: write"
);
rfbCloseClient
(
cl
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
FALSE
;
}
break
;
case
rfbFileHeader
:
/* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */
if
(
size
==-
1
)
{
rfbLog
(
"rfbProcessFileTransfer() rfbFileHeader (error, aborting)
\n
"
);
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=-
1
;
return
TRUE
;
}
/*
rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size);
*/
/* Starts the transfer! */
cl
->
fileTransfer
.
sending
=
1
;
return
rfbSendFileTransferChunk
(
cl
);
break
;
/*
* sending from the viewer to the server
*/
case
rfbFileTransferOffer
:
/* client is sending a file to us */
/* buffer contains full path name (plus FileTime) */
/* size contains size of the file */
/*
rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n");
*/
if
((
buffer
=
rfbProcessFileTransferReadBuffer
(
cl
,
length
))
==
NULL
)
return
FALSE
;
/* Parse the FileTime */
p
=
strrchr
(
buffer
,
','
);
if
(
p
!=
NULL
)
{
*
p
=
'\0'
;
strcpy
(
szFileTime
,
p
+
1
);
}
else
szFileTime
[
0
]
=
0
;
/* Need to read in sizeHtmp */
if
((
n
=
rfbReadExact
(
cl
,
(
char
*
)
&
sizeHtmp
,
4
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessFileTransfer: read sizeHtmp"
);
rfbCloseClient
(
cl
);
/* NOTE: don't forget to free(buffer) if you return early! */
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
FALSE
;
}
sizeHtmp
=
Swap32IfLE
(
sizeHtmp
);
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
filename1
);
/* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
/* TODO: Delta Transfer */
cl
->
fileTransfer
.
fd
=
open
(
filename1
,
O_CREAT
|
O_WRONLY
|
O_TRUNC
,
0744
);
/*
rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer(\"%s\"->\"%s\") %s %s\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), (cl->fileTransfer.fd==-1?strerror(errno):""));
*/
/* File Size in bytes, 0xFFFFFFFF (-1) means error */
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbFileAcceptHeader
,
0
,
(
cl
->
fileTransfer
.
fd
==-
1
?
-
1
:
0
),
length
,
buffer
);
if
(
cl
->
fileTransfer
.
fd
==-
1
)
{
free
(
buffer
);
return
retval
;
}
/* setup filetransfer stuff */
cl
->
fileTransfer
.
fileSize
=
size
;
cl
->
fileTransfer
.
numPackets
=
size
/
sz_rfbBlockSize
;
cl
->
fileTransfer
.
receiving
=
1
;
cl
->
fileTransfer
.
sending
=
0
;
break
;
case
rfbFilePacket
:
/*
rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n");
*/
if
((
buffer
=
rfbProcessFileTransferReadBuffer
(
cl
,
length
))
==
NULL
)
return
FALSE
;
if
(
cl
->
fileTransfer
.
fd
!=-
1
)
{
/* buffer contains the contents of the file */
if
(
size
==
0
)
retval
=
write
(
cl
->
fileTransfer
.
fd
,
buffer
,
length
);
else
{
#ifdef LIBVNCSERVER_HAVE_LIBZ
/* compressed packet */
nRet
=
uncompress
(
compBuff
,
&
nRawBytes
,(
const
unsigned
char
*
)
buffer
,
length
);
retval
=
write
(
cl
->
fileTransfer
.
fd
,
compBuff
,
nRawBytes
);
#else
/* Write the file out as received... */
retval
=
write
(
cl
->
fileTransfer
.
fd
,
buffer
,
length
);
#endif
}
if
(
retval
==-
1
)
{
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=-
1
;
cl
->
fileTransfer
.
sending
=
0
;
cl
->
fileTransfer
.
receiving
=
0
;
}
}
break
;
case
rfbEndOfFile
:
/*
rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n");
*/
if
(
cl
->
fileTransfer
.
fd
!=-
1
)
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=-
1
;
cl
->
fileTransfer
.
sending
=
0
;
cl
->
fileTransfer
.
receiving
=
0
;
break
;
case
rfbAbortFileTransfer
:
/*
rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n");
*/
if
(
cl
->
fileTransfer
.
fd
!=-
1
)
{
close
(
cl
->
fileTransfer
.
fd
);
cl
->
fileTransfer
.
fd
=-
1
;
cl
->
fileTransfer
.
sending
=
0
;
cl
->
fileTransfer
.
receiving
=
0
;
}
else
{
/* We use this message for FileTransfer rights (<=RC18 versions)
* The client asks for FileTransfer permission
*/
if
(
contentParam
==
0
)
{
rfbLog
(
"rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)
\n
"
);
/* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/
return
rfbSendFileTransferMessage
(
cl
,
rfbAbortFileTransfer
,
0
,
-
1
,
0
,
""
);
}
/* New method is allowed */
if
(
cl
->
screen
->
getFileTransferPermission
!=
NULL
)
{
if
(
cl
->
screen
->
getFileTransferPermission
(
cl
)
==
TRUE
)
{
rfbLog
(
"rfbProcessFileTransfer() File Transfer Permission Granted!
\n
"
);
return
rfbSendFileTransferMessage
(
cl
,
rfbFileTransferAccess
,
0
,
1
,
0
,
""
);
/* Permit */
}
else
{
rfbLog
(
"rfbProcessFileTransfer() File Transfer Permission DENIED!
\n
"
);
return
rfbSendFileTransferMessage
(
cl
,
rfbFileTransferAccess
,
0
,
-
1
,
0
,
""
);
/* Deny */
}
}
rfbLog
(
"rfbProcessFileTransfer() File Transfer Permission DENIED by default!
\n
"
);
return
rfbSendFileTransferMessage
(
cl
,
rfbFileTransferAccess
,
0
,
-
1
,
0
,
""
);
/* DEFAULT: DENY (for security) */
}
break
;
case
rfbCommand
:
/*
rfbLog("rfbProcessFileTransfer() rfbCommand:\n");
*/
if
((
buffer
=
rfbProcessFileTransferReadBuffer
(
cl
,
length
))
==
NULL
)
return
FALSE
;
switch
(
contentParam
)
{
case
rfbCDirCreate
:
/* Client requests the creation of a directory */
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
filename1
);
retval
=
mkdir
(
filename1
,
0755
);
/*
rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
*/
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbCommandReturn
,
rfbADirCreate
,
retval
,
length
,
buffer
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
case
rfbCFileDelete
:
/* Client requests the deletion of a file */
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
filename1
);
if
(
stat
(
filename1
,
&
statbuf
)
==
0
)
{
if
(
S_ISDIR
(
statbuf
.
st_mode
))
retval
=
rmdir
(
filename1
);
else
retval
=
unlink
(
filename1
);
}
else
retval
=-
1
;
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbCommandReturn
,
rfbAFileDelete
,
retval
,
length
,
buffer
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
case
rfbCFileRename
:
/* Client requests the Renaming of a file/directory */
p
=
strrchr
(
buffer
,
'*'
);
if
(
p
!=
NULL
)
{
/* Split into 2 filenames ('*' is a seperator) */
*
p
=
'\0'
;
rfbFilenameTranslate2UNIX
(
cl
,
buffer
,
filename1
);
rfbFilenameTranslate2UNIX
(
cl
,
p
+
1
,
filename2
);
retval
=
rename
(
filename1
,
filename2
);
/*
rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
*/
/* Restore the buffer so the reply is good */
*
p
=
'*'
;
retval
=
rfbSendFileTransferMessage
(
cl
,
rfbCommandReturn
,
rfbAFileRename
,
retval
,
length
,
buffer
);
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
retval
;
}
break
;
}
break
;
}
/* NOTE: don't forget to free(buffer) if you return early! */
if
(
buffer
!=
NULL
)
free
(
buffer
);
return
TRUE
;
}
/*
* rfbProcessClientNormalMessage is called when the client has sent a normal
* protocol message.
...
...
@@ -994,6 +1663,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
int
n
=
0
;
rfbClientToServerMsg
msg
;
char
*
str
;
int
i
;
uint32_t
enc
=
0
;
uint32_t
lastPreferredEncoding
=
-
1
;
char
encBuf
[
64
];
char
encBuf2
[
64
];
if
((
n
=
rfbReadExact
(
cl
,
(
char
*
)
&
msg
,
1
))
<=
0
)
{
if
(
n
!=
0
)
...
...
@@ -1028,6 +1702,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl
->
readyForSetColourMapEntries
=
TRUE
;
cl
->
screen
->
setTranslateFunction
(
cl
);
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetPixelFormatMsg
,
sz_rfbSetPixelFormatMsg
);
return
;
...
...
@@ -1039,16 +1715,23 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetPixelFormatMsg
,
sz_rfbSetPixelFormatMsg
);
rfbLog
(
"rfbProcessClientNormalMessage: %s"
,
"FixColourMapEntries unsupported
\n
"
);
rfbCloseClient
(
cl
);
return
;
/* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
* We may want to look into this...
* Example:
* case rfbEncodingXCursor:
* cl->enableCursorShapeUpdates = TRUE;
*
* Currently: cl->enableCursorShapeUpdates can *never* be turned off...
*/
case
rfbSetEncodings
:
{
int
i
;
uint32_t
enc
;
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbSetEncodingsMsg
-
1
))
<=
0
)
{
...
...
@@ -1060,6 +1743,31 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
msg
.
se
.
nEncodings
=
Swap16IfLE
(
msg
.
se
.
nEncodings
);
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetEncodingsMsg
+
(
msg
.
se
.
nEncodings
*
4
),
sz_rfbSetEncodingsMsg
+
(
msg
.
se
.
nEncodings
*
4
));
/*
* UltraVNC Client has the ability to adapt to changing network environments
* So, let's give it a change to tell us what it wants now!
*/
if
(
cl
->
preferredEncoding
!=-
1
)
lastPreferredEncoding
=
cl
->
preferredEncoding
;
/* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
cl
->
preferredEncoding
=-
1
;
cl
->
useCopyRect
=
FALSE
;
cl
->
useNewFBSize
=
FALSE
;
cl
->
cursorWasChanged
=
FALSE
;
cl
->
useRichCursorEncoding
=
FALSE
;
cl
->
enableCursorPosUpdates
=
FALSE
;
cl
->
enableCursorShapeUpdates
=
FALSE
;
cl
->
enableCursorShapeUpdates
=
FALSE
;
cl
->
enableLastRectEncoding
=
FALSE
;
cl
->
enableKeyboardLedState
=
FALSE
;
cl
->
enableSupportedMessages
=
FALSE
;
cl
->
enableSupportedEncodings
=
FALSE
;
cl
->
enableServerIdentity
=
FALSE
;
for
(
i
=
0
;
i
<
msg
.
se
.
nEncodings
;
i
++
)
{
if
((
n
=
rfbReadExact
(
cl
,
(
char
*
)
&
enc
,
4
))
<=
0
)
{
if
(
n
!=
0
)
...
...
@@ -1075,58 +1783,23 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl
->
useCopyRect
=
TRUE
;
break
;
case
rfbEncodingRaw
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using raw encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
case
rfbEncodingRRE
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using rre encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
case
rfbEncodingCoRRE
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using CoRRE encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
case
rfbEncodingHextile
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using hextile encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
case
rfbEncodingUltra
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using Ultra encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
#ifdef LIBVNCSERVER_HAVE_LIBZ
case
rfbEncodingZlib
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using zlib encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
case
rfbEncodingZRLE
:
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
case
rfbEncodingTight
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using tight encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
#endif
#endif
/* The first supported encoding is the 'preferred' encoding */
if
(
cl
->
preferredEncoding
==
-
1
)
cl
->
preferredEncoding
=
enc
;
break
;
case
rfbEncodingXCursor
:
if
(
!
cl
->
screen
->
dontConvertRichCursorToXCursor
)
{
rfbLog
(
"Enabling X-style cursor updates for client %s
\n
"
,
...
...
@@ -1200,15 +1873,6 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl
->
enableServerIdentity
=
TRUE
;
}
break
;
#ifdef LIBVNCSERVER_HAVE_LIBZ
case
rfbEncodingZRLE
:
if
(
cl
->
preferredEncoding
==
-
1
)
{
cl
->
preferredEncoding
=
enc
;
rfbLog
(
"Using ZRLE encoding for client %s
\n
"
,
cl
->
host
);
}
break
;
#endif
default:
#ifdef LIBVNCSERVER_HAVE_LIBZ
if
(
enc
>=
(
uint32_t
)
rfbEncodingCompressLevel0
&&
...
...
@@ -1268,15 +1932,34 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
if
(
!
handled
)
rfbLog
(
"rfbProcessClientNormalMessage: "
"ignoring un
known encoding type %d
\n
"
,
(
int
)
enc
);
"ignoring un
supported encoding type %s
\n
"
,
encodingName
(
enc
,
encBuf
,
sizeof
(
encBuf
))
);
}
}
}
}
if
(
cl
->
preferredEncoding
==
-
1
)
{
if
(
lastPreferredEncoding
==-
1
)
{
cl
->
preferredEncoding
=
rfbEncodingRaw
;
rfbLog
(
"Defaulting to %s encoding for client %s
\n
"
,
encodingName
(
cl
->
preferredEncoding
,
encBuf
,
sizeof
(
encBuf
)),
cl
->
host
);
}
else
{
cl
->
preferredEncoding
=
lastPreferredEncoding
;
rfbLog
(
"Sticking with %s encoding for client %s
\n
"
,
encodingName
(
cl
->
preferredEncoding
,
encBuf
,
sizeof
(
encBuf
)),
cl
->
host
);
}
}
else
{
if
(
lastPreferredEncoding
==-
1
)
{
rfbLog
(
"Using %s encoding for client %s
\n
"
,
encodingName
(
cl
->
preferredEncoding
,
encBuf
,
sizeof
(
encBuf
)),
cl
->
host
);
}
else
{
rfbLog
(
"Switching from %s to %s Encoding for client %s
\n
"
,
encodingName
(
lastPreferredEncoding
,
encBuf2
,
sizeof
(
encBuf2
)),
encodingName
(
cl
->
preferredEncoding
,
encBuf
,
sizeof
(
encBuf
)),
cl
->
host
);
}
}
if
(
cl
->
enableCursorPosUpdates
&&
!
cl
->
enableCursorShapeUpdates
)
{
...
...
@@ -1301,6 +1984,7 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbFramebufferUpdateRequestMsg
,
sz_rfbFramebufferUpdateRequestMsg
);
/* The values come in based on the scaled screen, we need to convert them to
* values based on the main screen's coordinate system
...
...
@@ -1347,8 +2031,6 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
case
rfbKeyEvent
:
cl
->
keyEventsRcvd
++
;
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbKeyEventMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
...
...
@@ -1357,6 +2039,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbKeyEventMsg
,
sz_rfbKeyEventMsg
);
if
(
!
cl
->
viewOnly
)
{
cl
->
screen
->
kbdAddEvent
(
msg
.
ke
.
down
,
(
rfbKeySym
)
Swap32IfLE
(
msg
.
ke
.
key
),
cl
);
}
...
...
@@ -1366,8 +2050,6 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
case
rfbPointerEvent
:
cl
->
pointerEventsRcvd
++
;
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbPointerEventMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
...
...
@@ -1376,6 +2058,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbPointerEventMsg
,
sz_rfbPointerEventMsg
);
if
(
cl
->
screen
->
pointerClient
&&
cl
->
screen
->
pointerClient
!=
cl
)
return
;
...
...
@@ -1401,6 +2085,115 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
return
;
case
rfbFileTransfer
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbFileTransferMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
rfbCloseClient
(
cl
);
return
;
}
msg
.
ft
.
size
=
Swap32IfLE
(
msg
.
ft
.
size
);
msg
.
ft
.
length
=
Swap32IfLE
(
msg
.
ft
.
length
);
/* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */
rfbProcessFileTransfer
(
cl
,
msg
.
ft
.
contentType
,
msg
.
ft
.
contentParam
,
msg
.
ft
.
size
,
msg
.
ft
.
length
);
return
;
case
rfbSetSW
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbSetSWMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
rfbCloseClient
(
cl
);
return
;
}
msg
.
sw
.
x
=
Swap16IfLE
(
msg
.
sw
.
x
);
msg
.
sw
.
y
=
Swap16IfLE
(
msg
.
sw
.
y
);
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetSWMsg
,
sz_rfbSetSWMsg
);
/* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */
rfbLog
(
"Received a rfbSetSingleWindow(%d x, %d y)
\n
"
,
msg
.
sw
.
x
,
msg
.
sw
.
y
);
if
(
cl
->
screen
->
setSingleWindow
!=
NULL
)
cl
->
screen
->
setSingleWindow
(
cl
,
msg
.
sw
.
x
,
msg
.
sw
.
y
);
return
;
case
rfbSetServerInput
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbSetServerInputMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetServerInputMsg
,
sz_rfbSetServerInputMsg
);
/* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */
/* msg.sim.pad = Swap16IfLE(msg.sim.pad); */
rfbLog
(
"Received a rfbSetServerInput(%d status)
\n
"
,
msg
.
sim
.
status
);
if
(
cl
->
screen
->
setServerInput
!=
NULL
)
cl
->
screen
->
setServerInput
(
cl
,
msg
.
sim
.
status
);
return
;
case
rfbTextChat
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbTextChatMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
rfbCloseClient
(
cl
);
return
;
}
msg
.
tc
.
pad2
=
Swap16IfLE
(
msg
.
tc
.
pad2
);
msg
.
tc
.
length
=
Swap32IfLE
(
msg
.
tc
.
length
);
switch
(
msg
.
tc
.
length
)
{
case
rfbTextChatOpen
:
case
rfbTextChatClose
:
case
rfbTextChatFinished
:
/* commands do not have text following */
/* Why couldn't they have used the pad byte??? */
str
=
NULL
;
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbTextChatMsg
,
sz_rfbTextChatMsg
);
break
;
default:
if
((
msg
.
tc
.
length
>
0
)
&&
(
msg
.
tc
.
length
<
rfbTextMaxSize
))
{
str
=
(
char
*
)
malloc
(
msg
.
tc
.
length
);
if
(
str
==
NULL
)
{
rfbLog
(
"Unable to malloc %d bytes for a TextChat Message
\n
"
,
msg
.
tc
.
length
);
rfbCloseClient
(
cl
);
return
;
}
if
((
n
=
rfbReadExact
(
cl
,
str
,
msg
.
tc
.
length
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
free
(
str
);
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbTextChatMsg
+
msg
.
tc
.
length
,
sz_rfbTextChatMsg
+
msg
.
tc
.
length
);
}
else
{
/* This should never happen */
rfbLog
(
"client sent us a Text Message that is too big %d>%d
\n
"
,
msg
.
tc
.
length
,
rfbTextMaxSize
);
rfbCloseClient
(
cl
);
return
;
}
}
/* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished
* at which point, the str is NULL (as it is not sent)
*/
if
(
cl
->
screen
->
setTextChat
!=
NULL
)
cl
->
screen
->
setTextChat
(
cl
,
msg
.
tc
.
length
,
str
);
free
(
str
);
return
;
case
rfbClientCutText
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
...
...
@@ -1422,7 +2215,7 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbClientCutTextMsg
+
msg
.
cct
.
length
,
sz_rfbClientCutTextMsg
+
msg
.
cct
.
length
);
if
(
!
cl
->
viewOnly
)
{
cl
->
screen
->
setXCutText
(
str
,
msg
.
cct
.
length
,
cl
);
}
...
...
@@ -1432,6 +2225,20 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
case
rfbPalmVNCSetScaleFactor
:
cl
->
PalmVNC
=
TRUE
;
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
sz_rfbSetScaleMsg
-
1
))
<=
0
)
{
if
(
n
!=
0
)
rfbLogPerror
(
"rfbProcessClientNormalMessage: read"
);
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetScaleMsg
,
sz_rfbSetScaleMsg
);
rfbLog
(
"rfbSetScale(%d)
\n
"
,
msg
.
ssc
.
scale
);
rfbScalingSetup
(
cl
,
cl
->
screen
->
width
/
msg
.
ssc
.
scale
,
cl
->
screen
->
height
/
msg
.
ssc
.
scale
);
rfbSendNewScaleSize
(
cl
);
return
;
case
rfbSetScale
:
if
((
n
=
rfbReadExact
(
cl
,
((
char
*
)
&
msg
)
+
1
,
...
...
@@ -1441,11 +2248,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
rfbCloseClient
(
cl
);
return
;
}
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
sz_rfbSetScaleMsg
,
sz_rfbSetScaleMsg
);
rfbLog
(
"rfbSetScale(%d)
\n
"
,
msg
.
ssc
.
scale
);
rfbScalingSetup
(
cl
,
cl
->
screen
->
width
/
msg
.
ssc
.
scale
,
cl
->
screen
->
height
/
msg
.
ssc
.
scale
);
rfbSendNewScaleSize
(
cl
);
return
;
default:
...
...
@@ -1456,7 +2263,10 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
next
=
e
->
next
;
if
(
e
->
extension
->
handleMessage
&&
e
->
extension
->
handleMessage
(
cl
,
e
->
data
,
&
msg
))
{
rfbStatRecordMessageRcvd
(
cl
,
msg
.
type
,
0
,
0
);
/* Extension should handle this */
return
;
}
e
=
next
;
}
...
...
@@ -1508,7 +2318,6 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
LOCK
(
cl
->
updateMutex
);
cl
->
newFBSizePending
=
FALSE
;
UNLOCK
(
cl
->
updateMutex
);
cl
->
framebufferUpdateMessagesSent
++
;
fu
->
type
=
rfbFramebufferUpdate
;
fu
->
nRects
=
Swap16IfLE
(
1
);
cl
->
ublen
=
sz_rfbFramebufferUpdateMsg
;
...
...
@@ -1693,8 +2502,8 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
/*
* Now send the update.
*/
cl
->
framebufferUpdateMessagesSent
++
;
rfbStatRecordMessageSent
(
cl
,
rfbFramebufferUpdate
,
0
,
0
);
if
(
cl
->
preferredEncoding
==
rfbEncodingCoRRE
)
{
nUpdateRegionRects
=
0
;
...
...
@@ -1843,9 +2652,6 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
if
(
cl
->
screen
!=
cl
->
scaledScreen
)
rfbScaledCorrection
(
cl
->
screen
,
cl
->
scaledScreen
,
&
x
,
&
y
,
&
w
,
&
h
,
"rfbSendFramebufferUpdate"
);
cl
->
rawBytesEquivalent
+=
(
sz_rfbFramebufferUpdateRectHeader
+
w
*
(
cl
->
format
.
bitsPerPixel
/
8
)
*
h
);
switch
(
cl
->
preferredEncoding
)
{
case
-
1
:
case
rfbEncodingRaw
:
...
...
@@ -1961,10 +2767,8 @@ rfbSendCopyRegion(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
(
char
*
)
&
cr
,
sz_rfbCopyRect
);
cl
->
ublen
+=
sz_rfbCopyRect
;
cl
->
rectanglesSent
[
rfbEncodingCopyRect
]
++
;
cl
->
bytesSent
[
rfbEncodingCopyRect
]
+=
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbCopyRect
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingCopyRect
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbCopyRect
,
w
*
h
*
(
cl
->
scaledScreen
->
bitsPerPixel
/
8
));
}
sraRgnReleaseIterator
(
i
);
...
...
@@ -2003,9 +2807,9 @@ rfbSendRectEncodingRaw(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
(
char
*
)
&
rect
,
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
rectanglesSent
[
rfbEncodingRaw
]
++
;
cl
->
bytesSent
[
rfbEncodingRaw
]
+=
sz_rfbFramebufferUpdateRectHeader
+
bytesPerLine
*
h
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingRaw
,
sz_rfbFramebufferUpdateRectHeader
+
bytesPerLine
*
h
,
sz_rfbFramebufferUpdateRectHeader
+
bytesPerLine
*
h
)
;
nlines
=
(
UPDATE_BUF_SIZE
-
cl
->
ublen
)
/
bytesPerLine
;
...
...
@@ -2069,8 +2873,8 @@ rfbSendLastRectMarker(rfbClientPtr cl)
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
(
char
*
)
&
rect
,
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
lastRectMarkersSent
++
;
cl
->
lastRectBytesSent
+=
sz_rfbFramebufferUpdateRectHeader
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingLastRect
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
)
;
return
TRUE
;
}
...
...
@@ -2108,8 +2912,7 @@ rfbSendNewFBSize(rfbClientPtr cl,
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
lastRectMarkersSent
++
;
cl
->
lastRectBytesSent
+=
sz_rfbFramebufferUpdateRectHeader
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingNewFBSize
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
);
return
TRUE
;
}
...
...
@@ -2181,6 +2984,8 @@ rfbSendSetColourMapEntries(rfbClientPtr cl,
rfbCloseClient
(
cl
);
return
FALSE
;
}
rfbStatRecordMessageSent
(
cl
,
rfbSetColourMapEntries
,
len
,
len
);
return
TRUE
;
}
...
...
@@ -2203,6 +3008,7 @@ rfbSendBell(rfbScreenInfoPtr rfbScreen)
rfbCloseClient
(
cl
);
}
}
rfbStatRecordMessageSent
(
cl
,
rfbBell
,
sz_rfbBellMsg
,
sz_rfbBellMsg
);
rfbReleaseClientIterator
(
i
);
}
...
...
@@ -2232,6 +3038,7 @@ rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
rfbLogPerror
(
"rfbSendServerCutText: write"
);
rfbCloseClient
(
cl
);
}
rfbStatRecordMessageSent
(
cl
,
rfbServerCutText
,
sz_rfbServerCutTextMsg
+
len
,
sz_rfbServerCutTextMsg
+
len
);
}
rfbReleaseClientIterator
(
iterator
);
}
...
...
libvncserver/rre.c
View file @
ccdbe8f3
...
...
@@ -40,7 +40,7 @@ static char *rreBeforeBuf = NULL;
static
int
rreAfterBufSize
=
0
;
static
char
*
rreAfterBuf
=
NULL
;
static
int
rreAfterBufLen
;
static
int
rreAfterBufLen
=
0
;
static
int
subrectEncode8
(
uint8_t
*
data
,
int
w
,
int
h
);
static
int
subrectEncode16
(
uint16_t
*
data
,
int
w
,
int
h
);
...
...
@@ -112,9 +112,9 @@ rfbSendRectEncodingRRE(rfbClientPtr cl,
return
rfbSendRectEncodingRaw
(
cl
,
x
,
y
,
w
,
h
);
}
cl
->
rectanglesSent
[
rfbEncodingRRE
]
++
;
cl
->
bytesSent
[
rfbEncodingRRE
]
+=
(
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
+
rreAfterBufLen
);
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingRRE
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
+
rreAfterBufLen
,
sz_rfbFramebufferUpdateRectHeader
+
w
*
h
*
(
cl
->
format
.
bitsPerPixel
/
8
)
);
if
(
cl
->
ublen
+
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbRREHeader
>
UPDATE_BUF_SIZE
)
...
...
libvncserver/scale.c
View file @
ccdbe8f3
...
...
@@ -128,8 +128,8 @@ void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int
*
h
=
(
int
)
h2
;
/* Small changes for a thumbnail may be scaled to zero */
if
(
*
w
==
0
)
*
w
++
;
if
(
*
h
==
0
)
*
h
++
;
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
;
...
...
@@ -212,7 +212,9 @@ void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, in
pixel_value
+=
(
srcptr2
[
z
]
<<
(
8
*
z
));
break
;
}
//srcptr2 += bytesPerPixel;
/*
srcptr2 += bytesPerPixel;
*/
red
+=
((
pixel_value
>>
redShift
)
&
redMax
);
green
+=
((
pixel_value
>>
greenShift
)
&
greenMax
);
...
...
libvncserver/sockets.c
View file @
ccdbe8f3
...
...
@@ -239,8 +239,18 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
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
();
...
...
@@ -332,11 +342,17 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
i
=
rfbGetClientIterator
(
rfbScreen
);
while
((
cl
=
rfbClientIteratorNext
(
i
)))
{
if
(
cl
->
onHold
)
continue
;
if
(
FD_ISSET
(
cl
->
sock
,
&
fds
)
&&
FD_ISSET
(
cl
->
sock
,
&
(
rfbScreen
->
allFds
)))
if
(
FD_ISSET
(
cl
->
sock
,
&
(
rfbScreen
->
allFds
)))
{
if
(
FD_ISSET
(
cl
->
sock
,
&
fds
))
rfbProcessClientMessage
(
cl
);
else
rfbSendFileTransferChunk
(
cl
);
}
}
rfbReleaseClientIterator
(
i
);
}
while
(
rfbScreen
->
handleEventsEagerly
);
...
...
libvncserver/stats.c
View file @
ccdbe8f3
...
...
@@ -26,90 +26,434 @@
#include <rfb/rfb.h>
static
const
char
*
encNames
[]
=
{
"raw"
,
"copyRect"
,
"RRE"
,
"[encoding 3]"
,
"CoRRE"
,
"hextile"
,
"zlib"
,
"tight"
,
"[encoding 8]"
,
"ultra"
,
"[encoding 10]"
,
"[encoding 11]"
,
"[encoding 12]"
,
"[encoding 13]"
,
"[encoding 14]"
,
"[encoding 15]"
,
"ZRLE"
,
"[encoding 17]"
,
"[encoding 18]"
,
"[encoding 19]"
,
"[encoding 20]"
};
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
rfbResetStats
(
rfbClientPtr
cl
)
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
rfbKeyFrameUpdate
:
snprintf
(
buf
,
len
,
"KeyFrameUpdate"
);
break
;
case
rfbFileTransfer
:
snprintf
(
buf
,
len
,
"FileTransfer"
);
break
;
case
rfbTextChat
:
snprintf
(
buf
,
len
,
"TextChat"
);
break
;
case
rfbPalmVNCReSizeFrameBuffer
:
snprintf
(
buf
,
len
,
"PalmVNCReSize"
);
break
;
default:
snprintf
(
buf
,
len
,
"server2client(0x%04X)"
,
type
);
}
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
rfbKeyFrameRequest
:
snprintf
(
buf
,
len
,
"KeyFrameRequest"
);
break
;
case
rfbPalmVNCSetScaleFactor
:
snprintf
(
buf
,
len
,
"PalmVNCSetScale"
);
break
;
default:
snprintf
(
buf
,
len
,
"client2server(0x%04X)"
,
type
);
}
return
buf
;
}
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
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
,
"SupportedMessages"
);
break
;
case
rfbEncodingSupportedEncodings
:
snprintf
(
buf
,
len
,
"SupportedEncodings"
);
break
;
case
rfbEncodingServerIdentity
:
snprintf
(
buf
,
len
,
"ServerIdentity"
);
break
;
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
,
"encoding(0x%04X)"
,
type
);
}
return
buf
;
}
rfbStatList
*
rfbStatLookupEncoding
(
rfbClientPtr
cl
,
uint32_t
type
)
{
int
i
;
for
(
i
=
0
;
i
<
MAX_ENCODINGS
;
i
++
)
{
cl
->
bytesSent
[
i
]
=
0
;
cl
->
rectanglesSent
[
i
]
=
0
;
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
;
}
cl
->
lastRectMarkersSent
=
0
;
cl
->
lastRectBytesSent
=
0
;
cl
->
cursorShapeBytesSent
=
0
;
cl
->
cursorShapeUpdatesSent
=
0
;
cl
->
cursorPosBytesSent
=
0
;
cl
->
cursorPosUpdatesSent
=
0
;
cl
->
framebufferUpdateMessagesSent
=
0
;
cl
->
rawBytesEquivalent
=
0
;
cl
->
keyEventsRcvd
=
0
;
cl
->
pointerEventsRcvd
=
0
;
return
ptr
;
}
void
rfbPrintStats
(
rfbClientPtr
cl
)
void
rfbStatRecordEncodingSentAdd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
)
/* Specifically for tight encoding */
{
int
i
;
int
totalRectanglesSent
=
0
;
int
totalBytesSent
=
0
;
rfbStatList
*
ptr
;
ptr
=
rfbStatLookupEncoding
(
cl
,
type
);
if
(
ptr
!=
NULL
)
ptr
->
bytesSent
+=
byteCount
;
}
rfbLog
(
"Statistics:
\n
"
);
if
((
cl
->
keyEventsRcvd
!=
0
)
||
(
cl
->
pointerEventsRcvd
!=
0
)
)
rfbLog
(
" key events received %d, pointer events %d
\n
"
,
cl
->
keyEventsRcvd
,
cl
->
pointerEventsRcvd
)
;
void
rfbStatRecordEncodingSent
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
)
{
rfbStatList
*
ptr
;
for
(
i
=
0
;
i
<
MAX_ENCODINGS
;
i
++
)
{
totalRectanglesSent
+=
cl
->
rectanglesSent
[
i
];
totalBytesSent
+=
cl
->
bytesSent
[
i
];
ptr
=
rfbStatLookupEncoding
(
cl
,
type
);
if
(
ptr
!=
NULL
)
{
ptr
->
sentCount
++
;
ptr
->
bytesSent
+=
byteCount
;
ptr
->
bytesSentIfRaw
+=
byteIfRaw
;
}
}
totalRectanglesSent
+=
(
cl
->
cursorShapeUpdatesSent
+
cl
->
cursorPosUpdatesSent
+
cl
->
lastRectMarkersSent
);
totalBytesSent
+=
(
cl
->
cursorShapeBytesSent
+
cl
->
cursorPosBytesSent
+
cl
->
lastRectBytesSent
);
void
rfbStatRecordEncodingRcvd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
)
{
rfbStatList
*
ptr
;
rfbLog
(
" framebuffer updates %d, rectangles %d, bytes %d
\n
"
,
cl
->
framebufferUpdateMessagesSent
,
totalRectanglesSent
,
totalBytesSent
);
ptr
=
rfbStatLookupEncoding
(
cl
,
type
);
if
(
ptr
!=
NULL
)
{
ptr
->
rcvdCount
++
;
ptr
->
bytesRcvd
+=
byteCount
;
ptr
->
bytesRcvdIfRaw
+=
byteIfRaw
;
}
}
if
(
cl
->
lastRectMarkersSent
!=
0
)
rfbLog
(
" LastRect and NewFBSize markers %d, bytes %d
\n
"
,
cl
->
lastRectMarkersSent
,
cl
->
lastRectBytesSent
)
;
void
rfbStatRecordMessageSent
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
)
{
rfbStatList
*
ptr
;
if
(
cl
->
cursorShapeUpdatesSent
!=
0
)
rfbLog
(
" cursor shape updates %d, bytes %d
\n
"
,
cl
->
cursorShapeUpdatesSent
,
cl
->
cursorShapeBytesSent
);
ptr
=
rfbStatLookupMessage
(
cl
,
type
);
if
(
ptr
!=
NULL
)
{
ptr
->
sentCount
++
;
ptr
->
bytesSent
+=
byteCount
;
ptr
->
bytesSentIfRaw
+=
byteIfRaw
;
}
}
if
(
cl
->
cursorPosUpdatesSent
!=
0
)
rfbLog
(
" cursor position updates %d, bytes %d
\n
"
,
cl
->
cursorPosUpdatesSent
,
cl
->
cursorPosBytesSent
)
;
void
rfbStatRecordMessageRcvd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
)
{
rfbStatList
*
ptr
;
for
(
i
=
0
;
i
<
MAX_ENCODINGS
;
i
++
)
{
if
(
cl
->
rectanglesSent
[
i
]
!=
0
)
rfbLog
(
" %s rectangles %d, bytes %d
\n
"
,
encNames
[
i
],
cl
->
rectanglesSent
[
i
],
cl
->
bytesSent
[
i
]);
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
);
}
}
if
((
totalBytesSent
-
cl
->
bytesSent
[
rfbEncodingCopyRect
])
!=
0
)
{
rfbLog
(
" raw bytes equivalent %d, compression ratio %f
\n
"
,
cl
->
rawBytesEquivalent
,
(
double
)
cl
->
rawBytesEquivalent
/
(
double
)(
totalBytesSent
-
cl
->
bytesSent
[
rfbEncodingCopyRect
]
-
cl
->
cursorShapeBytesSent
-
cl
->
cursorPosBytesSent
-
cl
->
lastRectBytesSent
));
void
rfbPrintStats
(
rfbClientPtr
cl
)
{
rfbStatList
*
ptr
=
NULL
;
char
encBuf
[
64
];
double
savings
=
0
.
0
;
int
totalRectsSent
=
0
;
double
totalBytesSent
=
0
.
0
;
double
totalBytesIfRawSent
=
0
.
0
;
int
totalRectsRcvd
=
0
;
double
totalBytesRcvd
=
0
.
0
;
double
totalBytesIfRawRcvd
=
0
.
0
;
char
*
name
=
NULL
;
int
bytes
=
0
;
int
count
=
0
;
if
(
cl
==
NULL
)
return
;
rfbLog
(
"Statistics: Transmit
\n
"
);
for
(
ptr
=
cl
->
statMsgList
;
ptr
!=
NULL
;
ptr
=
ptr
->
Next
)
{
name
=
messageNameServer2Client
(
ptr
->
type
,
encBuf
,
sizeof
(
encBuf
));
count
=
ptr
->
sentCount
;
bytes
=
ptr
->
bytesSent
;
savings
=
0
.
0
;
if
(
ptr
->
bytesSentIfRaw
>
0
.
0
)
savings
=
100
.
0
-
(((
double
)
ptr
->
bytesSent
/
(
double
)
ptr
->
bytesSentIfRaw
)
*
100
.
0
);
if
((
bytes
>
0
)
||
(
count
>
0
))
rfbLog
(
" %-24.24s: %6d events %9d/%9d bytes (%5.2f%% saved)
\n
"
,
name
,
count
,
bytes
,
ptr
->
bytesSentIfRaw
,
savings
);
totalRectsSent
+=
count
;
totalBytesSent
+=
bytes
;
totalBytesIfRawSent
+=
ptr
->
bytesSentIfRaw
;
}
for
(
ptr
=
cl
->
statEncList
;
ptr
!=
NULL
;
ptr
=
ptr
->
Next
)
{
name
=
encodingName
(
ptr
->
type
,
encBuf
,
sizeof
(
encBuf
));
count
=
ptr
->
sentCount
;
bytes
=
ptr
->
bytesSent
;
savings
=
0
.
0
;
if
(
ptr
->
bytesSentIfRaw
>
0
.
0
)
savings
=
100
.
0
-
(((
double
)
ptr
->
bytesSent
/
(
double
)
ptr
->
bytesSentIfRaw
)
*
100
.
0
);
if
((
bytes
>
0
)
||
(
count
>
0
))
rfbLog
(
" %-24.24s: %6d events %9d/%9d bytes (%5.2f%% saved)
\n
"
,
name
,
count
,
bytes
,
ptr
->
bytesSentIfRaw
,
savings
);
totalRectsSent
+=
count
;
totalBytesSent
+=
bytes
;
totalBytesIfRawSent
+=
ptr
->
bytesSentIfRaw
;
}
savings
=
100
.
0
-
((
totalBytesSent
/
totalBytesIfRawSent
)
*
100
.
0
);
rfbLog
(
" %-24.24s: %6d events %9.0f/%9.0f bytes (%5.2f%% savings)
\n
"
,
"TOTALS"
,
totalRectsSent
,
totalBytesSent
,
totalBytesIfRawSent
,
savings
);
rfbLog
(
"Statistics: Receive
\n
"
);
for
(
ptr
=
cl
->
statMsgList
;
ptr
!=
NULL
;
ptr
=
ptr
->
Next
)
{
name
=
messageNameClient2Server
(
ptr
->
type
,
encBuf
,
sizeof
(
encBuf
));
count
=
ptr
->
rcvdCount
;
bytes
=
ptr
->
bytesRcvd
;
savings
=
0
.
0
;
if
(
ptr
->
bytesSentIfRaw
>
0
.
0
)
savings
=
100
.
0
-
(((
double
)
ptr
->
bytesRcvd
/
(
double
)
ptr
->
bytesRcvdIfRaw
)
*
100
.
0
);
if
((
bytes
>
0
)
||
(
count
>
0
))
rfbLog
(
" %-24.24s: %6d events %9d/%9d bytes (%5.2f%% saved)
\n
"
,
name
,
count
,
bytes
,
ptr
->
bytesRcvdIfRaw
,
savings
);
totalRectsRcvd
+=
count
;
totalBytesRcvd
+=
bytes
;
totalBytesIfRawRcvd
+=
ptr
->
bytesRcvdIfRaw
;
}
for
(
ptr
=
cl
->
statEncList
;
ptr
!=
NULL
;
ptr
=
ptr
->
Next
)
{
name
=
encodingName
(
ptr
->
type
,
encBuf
,
sizeof
(
encBuf
));
count
=
ptr
->
rcvdCount
;
bytes
=
ptr
->
bytesRcvd
;
savings
=
0
.
0
;
if
(
ptr
->
bytesSentIfRaw
>
0
.
0
)
savings
=
100
.
0
-
(((
double
)
ptr
->
bytesRcvd
/
(
double
)
ptr
->
bytesRcvdIfRaw
)
*
100
.
0
);
if
((
bytes
>
0
)
||
(
count
>
0
))
rfbLog
(
" %-24.24s: %6d events %9d/%9d bytes (%5.2f%% saved)
\n
"
,
name
,
count
,
bytes
,
ptr
->
bytesRcvdIfRaw
,
savings
);
totalRectsRcvd
+=
count
;
totalBytesRcvd
+=
bytes
;
totalBytesIfRawRcvd
+=
ptr
->
bytesRcvdIfRaw
;
}
savings
=
100
.
0
-
((
totalBytesRcvd
/
totalBytesIfRawRcvd
)
*
100
.
0
);
rfbLog
(
" %-24.24s: %6d events %9.0f/%9.0f bytes (%5.2f%% savings)
\n
"
,
"TOTALS"
,
totalRectsRcvd
,
totalBytesRcvd
,
totalBytesIfRawRcvd
,
savings
);
}
libvncserver/tight.c
View file @
ccdbe8f3
...
...
@@ -663,8 +663,8 @@ SendTightHeader(rfbClientPtr cl,
sz_rfbFramebufferUpdateRectHeader
);
cl
->
ublen
+=
sz_rfbFramebufferUpdateRectHeader
;
cl
->
rectanglesSent
[
rfbEncodingTight
]
++
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
sz_rfbFramebufferUpdateRectHeader
;
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingTight
,
sz_rfbFramebufferUpdateRectHeader
,
sz_rfbFramebufferUpdateRectHeader
+
w
*
(
cl
->
format
.
bitsPerPixel
/
8
)
*
h
)
;
return
TRUE
;
}
...
...
@@ -693,7 +693,7 @@ SendSolidRect(rfbClientPtr cl)
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightBeforeBuf
,
len
);
cl
->
ublen
+=
len
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
len
+
1
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
len
+
1
)
;
return
TRUE
;
}
...
...
@@ -736,7 +736,7 @@ SendMonoRect(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightAfterBuf
,
paletteLen
);
cl
->
ublen
+=
paletteLen
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
3
+
paletteLen
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
3
+
paletteLen
)
;
break
;
case
16
:
...
...
@@ -747,7 +747,7 @@ SendMonoRect(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightAfterBuf
,
4
);
cl
->
ublen
+=
4
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
7
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
7
)
;
break
;
default
:
...
...
@@ -755,7 +755,7 @@ SendMonoRect(rfbClientPtr cl,
cl
->
updateBuf
[
cl
->
ublen
++
]
=
(
char
)
monoBackground
;
cl
->
updateBuf
[
cl
->
ublen
++
]
=
(
char
)
monoForeground
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
5
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
5
)
;
}
return
CompressData
(
cl
,
streamId
,
dataLen
,
...
...
@@ -801,7 +801,7 @@ SendIndexedRect(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightAfterBuf
,
paletteNumColors
*
entryLen
);
cl
->
ublen
+=
paletteNumColors
*
entryLen
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
3
+
paletteNumColors
*
entryLen
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
3
+
paletteNumColors
*
entryLen
)
;
break
;
case
16
:
...
...
@@ -814,7 +814,7 @@ SendIndexedRect(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightAfterBuf
,
paletteNumColors
*
2
);
cl
->
ublen
+=
paletteNumColors
*
2
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
3
+
paletteNumColors
*
2
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
3
+
paletteNumColors
*
2
)
;
break
;
default
:
...
...
@@ -840,7 +840,7 @@ SendFullColorRect(rfbClientPtr cl,
}
cl
->
updateBuf
[
cl
->
ublen
++
]
=
0x00
;
/* stream id = 0, no flushing, no filter */
cl
->
bytesSent
[
rfbEncodingTight
]
++
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
1
)
;
if
(
usePixelFormat24
)
{
Pack24
(
cl
,
tightBeforeBuf
,
&
cl
->
format
,
w
*
h
);
...
...
@@ -874,7 +874,7 @@ SendGradientRect(rfbClientPtr cl,
cl
->
updateBuf
[
cl
->
ublen
++
]
=
(
streamId
|
rfbTightExplicitFilter
)
<<
4
;
cl
->
updateBuf
[
cl
->
ublen
++
]
=
rfbTightFilterGradient
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
2
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
2
)
;
if
(
usePixelFormat24
)
{
FilterGradient24
(
cl
,
tightBeforeBuf
,
&
cl
->
format
,
w
,
h
);
...
...
@@ -905,7 +905,7 @@ CompressData(rfbClientPtr cl,
if
(
dataLen
<
TIGHT_MIN_TO_COMPRESS
)
{
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
tightBeforeBuf
,
dataLen
);
cl
->
ublen
+=
dataLen
;
cl
->
bytesSent
[
rfbEncodingTight
]
+=
dataLen
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
dataLen
)
;
return
TRUE
;
}
...
...
@@ -955,15 +955,15 @@ static rfbBool SendCompressedData(rfbClientPtr cl,
int
i
,
portionLen
;
cl
->
updateBuf
[
cl
->
ublen
++
]
=
compressedLen
&
0x7F
;
cl
->
bytesSent
[
rfbEncodingTight
]
++
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
1
)
;
if
(
compressedLen
>
0x7F
)
{
cl
->
updateBuf
[
cl
->
ublen
-
1
]
|=
0x80
;
cl
->
updateBuf
[
cl
->
ublen
++
]
=
compressedLen
>>
7
&
0x7F
;
cl
->
bytesSent
[
rfbEncodingTight
]
++
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
1
)
;
if
(
compressedLen
>
0x3FFF
)
{
cl
->
updateBuf
[
cl
->
ublen
-
1
]
|=
0x80
;
cl
->
updateBuf
[
cl
->
ublen
++
]
=
compressedLen
>>
14
&
0xFF
;
cl
->
bytesSent
[
rfbEncodingTight
]
++
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
1
)
;
}
}
...
...
@@ -979,7 +979,7 @@ static rfbBool SendCompressedData(rfbClientPtr cl,
memcpy
(
&
cl
->
updateBuf
[
cl
->
ublen
],
&
tightAfterBuf
[
i
],
portionLen
);
cl
->
ublen
+=
portionLen
;
}
cl
->
bytesSent
[
rfbEncodingTight
]
+=
compressedLen
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
compressedLen
)
;
return
TRUE
;
}
...
...
@@ -1686,7 +1686,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality)
}
cl
->
updateBuf
[
cl
->
ublen
++
]
=
(
char
)(
rfbTightJpeg
<<
4
);
cl
->
bytesSent
[
rfbEncodingTight
]
++
;
rfbStatRecordEncodingSentAdd
(
cl
,
rfbEncodingTight
,
1
)
;
return
SendCompressedData
(
cl
,
jpegDstDataLen
);
}
...
...
libvncserver/tightvnc-filetransfer/rfbtightproto.h
View file @
ccdbe8f3
...
...
@@ -28,6 +28,12 @@
#include <rfb/rfb.h>
#include <limits.h>
/* PATH_MAX is not defined in limits.h on some platforms */
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define rfbSecTypeTight 16
void
rfbTightUsage
(
void
);
...
...
libvncserver/ultra.c
View file @
ccdbe8f3
...
...
@@ -101,9 +101,7 @@ rfbSendOneRectEncodingUltra(rfbClientPtr cl,
}
/* Update statics */
cl
->
rectanglesSent
[
rfbEncodingUltra
]
++
;
cl
->
bytesSent
[
rfbEncodingUltra
]
+=
(
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
+
lzoAfterBufLen
);
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingUltra
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
+
lzoAfterBufLen
,
maxRawSize
);
if
(
cl
->
ublen
+
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
>
UPDATE_BUF_SIZE
)
...
...
libvncserver/zlib.c
View file @
ccdbe8f3
...
...
@@ -121,6 +121,7 @@ rfbSendOneRectEncodingZlib(rfbClientPtr cl,
zlibAfterBuf
=
(
char
*
)
realloc
(
zlibAfterBuf
,
zlibAfterBufSize
);
}
/*
* Convert pixel data to client format.
*/
...
...
@@ -176,9 +177,8 @@ rfbSendOneRectEncodingZlib(rfbClientPtr cl,
*/
/* Update statics */
cl
->
rectanglesSent
[
rfbEncodingZlib
]
++
;
cl
->
bytesSent
[
rfbEncodingZlib
]
+=
(
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
+
zlibAfterBufLen
);
rfbStatRecordEncodingSent
(
cl
,
rfbEncodingZlib
,
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
+
zlibAfterBufLen
,
+
w
*
(
cl
->
format
.
bitsPerPixel
/
8
)
*
h
);
if
(
cl
->
ublen
+
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZlibHeader
>
UPDATE_BUF_SIZE
)
...
...
libvncserver/zrle.c
View file @
ccdbe8f3
...
...
@@ -124,9 +124,8 @@ rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
break
;
}
cl
->
rectanglesSent
[
rfbEncodingZRLE
]
++
;
cl
->
bytesSent
[
rfbEncodingZRLE
]
+=
(
sz_rfbFramebufferUpdateRectHeader
+
sz_rfbZRLEHeader
+
ZRLE_BUFFER_LENGTH
(
&
zos
->
out
));
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
)
...
...
rfb/rfb.h
View file @
ccdbe8f3
...
...
@@ -137,7 +137,21 @@ typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl)
typedef
void
(
*
rfbDisplayHookPtr
)(
struct
_rfbClientRec
*
cl
);
/* support the capability to view the caps/num/scroll states of the X server */
typedef
int
(
*
rfbGetKeyboardLedStateHookPtr
)(
struct
_rfbScreenInfo
*
screen
);
/* If x==1 and y==1 then set the whole display
* else find the window underneath x and y and set the framebuffer to the dimensions
* of that window
*/
typedef
void
(
*
rfbSetSingleWindowProcPtr
)
(
struct
_rfbClientRec
*
cl
,
int
x
,
int
y
);
/* Status determines if the X11 server permits input from the local user
* status==0 or 1
*/
typedef
void
(
*
rfbSetServerInputProcPtr
)
(
struct
_rfbClientRec
*
cl
,
int
status
);
/* Permit the server to allow or deny filetransfers. This is defaulted to deny
* It is called when a client initiates a connection to determine if it is permitted.
*/
typedef
int
(
*
rfbFileTransferPermitted
)
(
struct
_rfbClientRec
*
cl
);
/* Handle the textchat messages */
typedef
void
(
*
rfbSetTextChat
)
(
struct
_rfbClientRec
*
cl
,
int
length
,
char
*
string
);
typedef
struct
{
uint32_t
count
;
...
...
@@ -296,6 +310,10 @@ typedef struct _rfbScreenInfo
rfbSetXCutTextProcPtr
setXCutText
;
rfbGetCursorProcPtr
getCursorPtr
;
rfbSetTranslateFunctionProcPtr
setTranslateFunction
;
rfbSetSingleWindowProcPtr
setSingleWindow
;
rfbSetServerInputProcPtr
setServerInput
;
rfbFileTransferPermitted
getFileTransferPermission
;
rfbSetTextChat
setTextChat
;
/* newClientHook is called just after a new client is created */
rfbNewClientHookPtr
newClientHook
;
...
...
@@ -326,6 +344,10 @@ typedef struct _rfbScreenInfo
/* rfbEncodingServerIdentity */
char
*
versionString
;
/* What does the server tell the new clients which version it supports */
int
protocolMajorVersion
;
int
protocolMinorVersion
;
}
rfbScreenInfo
,
*
rfbScreenInfoPtr
;
...
...
@@ -351,6 +373,27 @@ typedef struct sraRegion* sraRegionPtr;
typedef
void
(
*
ClientGoneHookPtr
)(
struct
_rfbClientRec
*
cl
);
typedef
struct
_rfbFileTransferData
{
int
fd
;
int
compressionEnabled
;
int
fileSize
;
int
numPackets
;
int
receiving
;
int
sending
;
}
rfbFileTransferData
;
typedef
struct
_rfbStatList
{
uint32_t
type
;
uint32_t
sentCount
;
uint32_t
bytesSent
;
uint32_t
bytesSentIfRaw
;
uint32_t
rcvdCount
;
uint32_t
bytesRcvd
;
uint32_t
bytesRcvdIfRaw
;
struct
_rfbStatList
*
Next
;
}
rfbStatList
;
typedef
struct
_rfbClientRec
{
/* back pointer to the screen */
...
...
@@ -467,19 +510,10 @@ typedef struct _rfbClientRec {
int
ublen
;
/* statistics */
int
bytesSent
[
MAX_ENCODINGS
];
int
rectanglesSent
[
MAX_ENCODINGS
];
int
lastRectMarkersSent
;
int
lastRectBytesSent
;
int
cursorShapeBytesSent
;
int
cursorShapeUpdatesSent
;
int
cursorPosBytesSent
;
int
cursorPosUpdatesSent
;
int
framebufferUpdateMessagesSent
;
struct
_rfbStatList
*
statEncList
;
struct
_rfbStatList
*
statMsgList
;
int
rawBytesEquivalent
;
int
keyEventsRcvd
;
int
pointerEventsRcvd
;
int
bytesSent
;
#ifdef LIBVNCSERVER_HAVE_LIBZ
/* zlib encoding -- necessary compression state info per client */
...
...
@@ -502,6 +536,7 @@ typedef struct _rfbClientRec {
rfbBool
compStreamInitedLZO
;
char
*
lzoWrkMem
;
rfbFileTransferData
fileTransfer
;
int
lastKeyboardLedState
;
/* keep track of last value so we can send *change* events */
rfbBool
enableSupportedMessages
;
/* client supports SupportedMessages encoding */
...
...
@@ -584,6 +619,11 @@ extern char rfbEndianTest;
#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l))
#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l))
/* UltraVNC uses some windows structures unmodified, so the viewer expects LittleEndian Data */
#define Swap16IfBE(s) (rfbEndianTest ? (s) : Swap16(s))
#define Swap24IfBE(l) (rfbEndianTest ? (l) : Swap24(l))
#define Swap32IfBE(l) (rfbEndianTest ? (l) : Swap32(l))
/* sockets.c */
extern
int
rfbMaxClientWait
;
...
...
@@ -634,6 +674,13 @@ extern rfbBool rfbSendNewFBSize(rfbClientPtr cl, int w, int h);
extern
rfbBool
rfbSendSetColourMapEntries
(
rfbClientPtr
cl
,
int
firstColour
,
int
nColours
);
extern
void
rfbSendBell
(
rfbScreenInfoPtr
rfbScreen
);
extern
char
*
rfbProcessFileTransferReadBuffer
(
rfbClientPtr
cl
,
uint32_t
length
);
extern
rfbBool
rfbSendFileTransferChunk
(
rfbClientPtr
cl
);
extern
rfbBool
rfbSendDirContent
(
rfbClientPtr
cl
,
int
length
,
char
*
buffer
);
extern
rfbBool
rfbSendFileTransferMessage
(
rfbClientPtr
cl
,
uint8_t
contentType
,
uint8_t
contentParam
,
uint32_t
size
,
uint32_t
length
,
char
*
buffer
);
extern
char
*
rfbProcessFileTransferReadBuffer
(
rfbClientPtr
cl
,
uint32_t
length
);
extern
rfbBool
rfbProcessFileTransfer
(
rfbClientPtr
cl
,
uint8_t
contentType
,
uint8_t
contentParam
,
uint32_t
size
,
uint32_t
length
);
void
rfbGotXCutText
(
rfbScreenInfoPtr
rfbScreen
,
char
*
str
,
int
len
);
/* translate.c */
...
...
@@ -880,6 +927,38 @@ extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo);
void
rfbRegisterTightVNCFileTransferExtension
();
void
rfbUnregisterTightVNCFileTransferExtension
();
/* Statistics */
extern
char
*
messageNameServer2Client
(
uint32_t
type
,
char
*
buf
,
int
len
);
extern
char
*
messageNameClient2Server
(
uint32_t
type
,
char
*
buf
,
int
len
);
extern
char
*
encodingName
(
uint32_t
enc
,
char
*
buf
,
int
len
);
extern
rfbStatList
*
rfbStatLookupEncoding
(
rfbClientPtr
cl
,
uint32_t
type
);
extern
rfbStatList
*
rfbStatLookupMessage
(
rfbClientPtr
cl
,
uint32_t
type
);
/* Each call to rfbStatRecord* adds one to the rect count for that type */
extern
void
rfbStatRecordEncodingSent
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
);
extern
void
rfbStatRecordEncodingSentAdd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
);
/* Specifically for tight encoding */
extern
void
rfbStatRecordEncodingRcvd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
);
extern
void
rfbStatRecordMessageSent
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
);
extern
void
rfbStatRecordMessageRcvd
(
rfbClientPtr
cl
,
uint32_t
type
,
int
byteCount
,
int
byteIfRaw
);
extern
void
rfbResetStats
(
rfbClientPtr
cl
);
extern
void
rfbPrintStats
(
rfbClientPtr
cl
);
extern
int
rfbStatGetSentBytes
(
rfbClientPtr
cl
);
extern
int
rfbStatGetSentBytesIfRaw
(
rfbClientPtr
cl
);
extern
int
rfbStatGetRcvdBytes
(
rfbClientPtr
cl
);
extern
int
rfbStatGetRcvdBytesIfRaw
(
rfbClientPtr
cl
);
extern
int
rfbStatGetMessageCountSent
(
rfbClientPtr
cl
,
uint32_t
type
);
extern
int
rfbStatGetMessageCountRcvd
(
rfbClientPtr
cl
,
uint32_t
type
);
extern
int
rfbStatGetEncodingCountSent
(
rfbClientPtr
cl
,
uint32_t
type
);
extern
int
rfbStatGetEncodingCountRcvd
(
rfbClientPtr
cl
,
uint32_t
type
);
/* Set which version you want to advertise 3.3, 3.6, 3.7 and 3.8 are currently supported*/
extern
void
rfbSetProtocolVersion
(
rfbScreenInfoPtr
rfbScreen
,
int
major_
,
int
minor_
);
#endif
#if(defined __cplusplus)
...
...
rfb/rfbclient.h
View file @
ccdbe8f3
...
...
@@ -96,6 +96,7 @@ typedef struct {
struct
_rfbClient
;
typedef
void
(
*
HandleTextChatProc
)(
struct
_rfbClient
*
client
,
int
value
,
char
*
text
);
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
);
...
...
@@ -210,6 +211,7 @@ typedef struct _rfbClient {
int
canHandleNewFBSize
;
/* hooks */
HandleTextChatProc
HandleTextChat
;
HandleKeyboardLedStateProc
HandleKeyboardLedState
;
HandleCursorPosProc
HandleCursorPos
;
SoftCursorLockAreaProc
SoftCursorLockArea
;
...
...
@@ -219,6 +221,19 @@ typedef struct _rfbClient {
GetPasswordProc
GetPassword
;
MallocFrameBufferProc
MallocFrameBuffer
;
BellProc
Bell
;
/* 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
;
}
rfbClient
;
/* cursor.c */
...
...
@@ -247,6 +262,12 @@ 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
void
PrintPixelFormat
(
rfbPixelFormat
*
format
);
/* client data */
...
...
rfb/rfbproto.h
View file @
ccdbe8f3
...
...
@@ -218,8 +218,10 @@ typedef struct {
#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
#define rfbProtocolMajorVersion 3
#define rfbProtocolMinorVersion 7
#define rfbProtocolFallbackMinorVersion 3
#define rfbProtocolMinorVersion 6
/* UltraVNC Viewer examines rfbProtocolMinorVersion number (4, and 6)
* to identify if the server supports File Transfer
*/
typedef
char
rfbProtocolVersionMsg
[
13
];
/* allow extra byte for null */
...
...
@@ -397,24 +399,18 @@ typedef struct {
#define rfbEncodingRRE 2
#define rfbEncodingCoRRE 4
#define rfbEncodingHextile 5
#ifdef LIBVNCSERVER_HAVE_LIBZ
#define rfbEncodingZlib 6
#define rfbEncodingTight 7
#define rfbEncodingZlibHex 8
#endif
#define rfbEncodingUltra 9
#ifdef LIBVNCSERVER_HAVE_LIBZ
#define rfbEncodingZRLE 16
#endif
/* Cache & XOR-Zlib - rdv@2002 */
#define rfbEncodingCache 0xFFFF0000
#define rfbEncodingCacheEnable 0xFFFF0001
#ifdef LIBVNCSERVER_HAVE_LIBZ
#define rfbEncodingXOR_Zlib 0xFFFF0002
#define rfbEncodingXORMonoColor_Zlib 0xFFFF0003
#define rfbEncodingXORMultiColor_Zlib 0xFFFF0004
#endif
#define rfbEncodingSolidColor 0xFFFF0005
#define rfbEncodingXOREnable 0xFFFF0006
#define rfbEncodingCacheZip 0xFFFF0007
...
...
@@ -649,11 +645,11 @@ typedef struct {
#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
#ifdef LIBVNCSERVER_HAVE_LIBZ
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* zlib - zlib compressed Encoding. We have an rfbZlibHeader structure
* giving the number of bytes following. Finally the data follows is
* zlib compressed version of the raw pixel data as negotiated.
* (NOTE: also used by Ultra Encoding)
*/
typedef
struct
{
...
...
@@ -662,6 +658,7 @@ typedef struct {
#define sz_rfbZlibHeader 4
#ifdef LIBVNCSERVER_HAVE_LIBZ
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Tight Encoding.
...
...
@@ -935,9 +932,10 @@ typedef struct {
typedef
struct
_rfbFileTransferMsg
{
uint8_t
type
;
/* always rfbFileTransfer */
uint8_t
contentType
;
/* See defines below */
uint16_t
contentParam
;
/* Other possible content classification (Dir or File name, etc..) */
uint8_t
contentParam
;
/* Other possible content classification (Dir or File name, etc..) */
uint8_t
pad
;
/* It appears that UltraVNC *forgot* to Swap16IfLE(contentParam) */
uint32_t
size
;
/* FileSize or packet index or error or other */
/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */
/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */
uint32_t
length
;
/* followed by data char text[length] */
}
rfbFileTransferMsg
;
...
...
x11vnc/rates.c
View file @
ccdbe8f3
...
...
@@ -350,11 +350,8 @@ db = 0;
}
nclients
++
;
cbs
=
0
;
for
(
i
=
0
;
i
<
MAX_ENCODINGS
;
i
++
)
{
cbs
+=
cl
->
bytesSent
[
i
];
}
rbs
=
cl
->
rawBytesEquivalent
;
cbs
=
rfbStatGetSentBytes
(
cl
);
rbs
=
rfbStatGetSentBytesIfRaw
(
cl
);
if
(
init
)
{
...
...
@@ -435,7 +432,7 @@ if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d "
if
(
db
)
fprintf
(
stderr
,
"dt2 calc: num rects req: %d/%d mod: %d/%d "
"fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f
\n
"
,
req0
,
req1
,
mod0
,
mod1
,
cl
->
framebufferUpdateMessagesSent
,
dt
,
dt2
,
tm
);
req0
,
req1
,
mod0
,
mod1
,
rfbStatGetMessageCountSent
(
cl
,
rfbFramebufferUpdate
)
,
dt
,
dt2
,
tm
);
if
(
req1
!=
0
&&
mod1
==
0
)
{
got_t2
=
1
;
break
;
...
...
@@ -502,7 +499,7 @@ if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d "
if
(
db
)
fprintf
(
stderr
,
"dt3 calc: num rects req: %d/%d mod: %d/%d "
"fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f
\n
"
,
req0
,
req1
,
mod0
,
mod1
,
cl
->
framebufferUpdateMessagesSent
,
dt
,
dt3
,
tm
);
req0
,
req1
,
mod0
,
mod1
,
rfbStatGetMessageCountSent
(
cl
,
rfbFramebufferUpdate
)
,
dt
,
dt3
,
tm
);
if
(
req1
!=
0
&&
mod1
==
0
)
{
dts
[
got_t3
++
]
=
dt3
;
...
...
x11vnc/userinput.c
View file @
ccdbe8f3
...
...
@@ -4082,7 +4082,7 @@ int fb_update_sent(int *count) {
i
=
rfbGetClientIterator
(
screen
);
while
(
(
cl
=
rfbClientIteratorNext
(
i
))
)
{
sent
+=
cl
->
framebufferUpdateMessagesSent
;
sent
+=
rfbStatGetMessageCountSent
(
cl
,
rfbFramebufferUpdate
)
;
}
rfbReleaseClientIterator
(
i
);
if
(
sent
!=
last_count
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment