diff options
-rw-r--r-- | README | 468 | ||||
-rw-r--r--[l---------] | README.md | 477 | ||||
-rw-r--r-- | client_examples/backchannel.c | 4 | ||||
-rw-r--r-- | common/d3des.c | 44 | ||||
-rw-r--r-- | common/d3des.h | 6 | ||||
-rw-r--r-- | libvncclient/rfbproto.c | 31 | ||||
-rw-r--r-- | libvncclient/sasl.c | 3 | ||||
-rw-r--r-- | libvncclient/sockets.c | 3 | ||||
-rw-r--r-- | libvncclient/tls.h | 2 | ||||
-rw-r--r-- | libvncclient/tls_gnutls.c | 2 | ||||
-rw-r--r-- | libvncclient/tls_none.c | 2 | ||||
-rw-r--r-- | libvncclient/tls_openssl.c | 2 | ||||
-rw-r--r-- | libvncclient/vncviewer.c | 6 | ||||
-rw-r--r-- | libvncserver/cargs.c | 4 | ||||
-rw-r--r-- | libvncserver/sockets.c | 6 | ||||
-rw-r--r-- | libvncserver/tight.c | 7 | ||||
-rw-r--r-- | libvncserver/tightvnc-filetransfer/filetransfermsg.c | 14 | ||||
-rw-r--r-- | libvncserver/tightvnc-filetransfer/filetransfermsg.h | 3 | ||||
-rw-r--r-- | libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c | 18 | ||||
-rw-r--r-- | libvncserver/tightvnc-filetransfer/rfbtightproto.h | 1 | ||||
-rw-r--r-- | libvncserver/tightvnc-filetransfer/rfbtightserver.c | 7 | ||||
-rw-r--r-- | libvncserver/zlib.c | 7 | ||||
-rw-r--r-- | rfb/default8x16.h | 5 | ||||
-rw-r--r-- | rfb/rfbclient.h | 3 |
24 files changed, 598 insertions, 527 deletions
@@ -1,468 +0,0 @@ -[![Build Status](https://travis-ci.org/LibVNC/libvncserver.svg?branch=master)](https://travis-ci.org/LibVNC/libvncserver) [![Build status](https://ci.appveyor.com/api/projects/status/fao6m1md3q4g2bwn/branch/master?svg=true)](https://ci.appveyor.com/project/bk138/libvncserver/branch/master) - -LibVNCServer: A library for easy implementation of a VNC server. -Copyright (C) 2001-2003 Johannes E. Schindelin - -If you already used LibVNCServer, you probably want to read NEWS. - -What is it? ------------ - -VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They -are designed to "export" a frame buffer via net (if you don't know VNC, I -suggest you read "Basics" below). It is already in wide use for -administration, but it is not that easy to program a server yourself. - -This has been changed by LibVNCServer. - -There are two examples included: - - example, a shared scribble sheet - - pnmshow, a program to show PNMs (pictures) over the net. - -The examples are not too well documented, but easy straight forward and a -good starting point. - -Try example: it outputs on which port it listens (default: 5900), so it is -display 0. To view, call - vncviewer :0 -You should see a sheet with a gradient and "Hello World!" written on it. Try -to paint something. Note that every time you click, there is some bigger blot, -whereas when you drag the mouse while clicked you draw a line. The size of the -blot depends on the mouse button you click. Open a second vncviewer with -the same parameters and watch it as you paint in the other window. This also -works over internet. You just have to know either the name or the IP of your -machine. Then it is - vncviewer machine.where.example.runs.com:0 -or similar for the remote client. Now you are ready to type something. Be sure -that your mouse sits still, because every time the mouse moves, the cursor is -reset to the position of the pointer! If you are done with that demo, press -the down or up arrows. If your viewer supports it, then the dimensions of the -sheet change. Just press Escape in the viewer. Note that the server still -runs, even if you closed both windows. When you reconnect now, everything you -painted and wrote is still there. You can press "Page Up" for a blank page. - -The demo pnmshow is much simpler: you either provide a filename as argument -or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, -i.e. a truecolour graphics. Only the Escape key is implemented. This may be -the best starting point if you want to learn how to use LibVNCServer. You -are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. - -Projects using it ----------------------------------------- - -VNC for KDE -http://www.tjansen.de/krfb - -GemsVNC -http://www.elilabs.com/~rj/gemsvnc/ - -VNC for Netware -http://forge.novell.com/modules/xfmod/project/?vncnw - -RDesktop -http://rdesktop.sourceforge.net - -VNCpp -https://github.com/ocrespo/VNCpp - - -Mail me, if your application is missing! - -How to build ------------- - -LibVNCServer uses CMake, so you can build via: - - mkdir build - cd build - cmake .. - cmake --build . - -For some more comprehensive examples that include installation of dependencies, see -the [Unix CI](.travis.yml) and [Windows CI](.appveyor.yml) build setups. - -Crosscompiling involves some more advanced command line switches but is easily possible -as well. - -For instance, building for Android (see https://developer.android.com/ndk/guides/cmake.html as a reference): - - mkdir build - cd build - cmake .. -DANDROID_NDK=<path> -DCMAKE_TOOLCHAIN_FILE=<path> -DANDROID_NATIVE_API_LEVEL=<API level you want> -DWITH_PNG=OFF # NDK not shipping png per default - cmake --build . - - -How to use ----------- - -To make a server, you just have to initialise a server structure using the -function rfbDefaultScreenInit, like - rfbScreenInfoPtr rfbScreen = - rfbGetScreen(argc,argv,width,height,8,3,bpp); -where byte per pixel should be 1, 2 or 4. If performance doesn't matter, -you may try bpp=3 (internally one cannot use native data types in this -case; if you want to use this, look at pnmshow24). - - -You then can set hooks and io functions (see below) or other -options (see below). - -And you allocate the frame buffer like this: - rfbScreen->frameBuffer = (char*)malloc(width*height*bpp); - -After that, you initialize the server, like - rfbInitServer(rfbScreen); - -You can use a blocking event loop, a background (pthread based) event loop, -or implement your own using the rfbProcessEvents function. - -Making it interactive ---------------------- - -Input is handled by IO functions (see below). - -Whenever you change something in the frame buffer, call rfbMarkRectAsModified. - -Utility functions ------------------ - -Whenever you draw something, you have to call - rfbMarkRectAsModified(screen,x1,y1,x2,y2). -This tells LibVNCServer to send updates to all connected clients. - -Before you draw something, be sure to call - rfbUndrawCursor(screen). -This tells LibVNCServer to hide the cursor. -Remark: There are vncviewers out there, which know a cursor encoding, so -that network traffic is low, and also the cursor doesn't need to be -drawn the cursor every time an update is sent. LibVNCServer handles -all the details. Just set the cursor and don't bother any more. - -To set the mouse coordinates (or emulate mouse clicks), call - rfbDefaultPtrAddEvent(buttonMask,x,y,cl); -IMPORTANT: do this at the end of your function, because this actually draws -the cursor if no cursor encoding is active. - -What is the difference between rfbScreenInfoPtr and rfbClientPtr? ------------------------------------------------------------------ - -The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which -holds information about the server, like pixel format, io functions, -frame buffer etc. - -The rfbClientPtr is a pointer to an rfbClientRec structure, which holds -information about a client, like pixel format, socket of the -connection, etc. - -A server can have several clients, but needn't have any. So, if you -have a server and three clients are connected, you have one instance -of a rfbScreenInfo and three instances of rfbClientRec's. - -The rfbClientRec structure holds a member - rfbScreenInfoPtr screen -which points to the server and a member - rfbClientPtr next -to the next client. - -The rfbScreenInfo structure holds a member - rfbClientPtr rfbClientHead -which points to the first client. - -So, to access the server from the client structure, you use client->screen. -To access all clients from a server, get screen->rfbClientHead and -iterate using client->next. - -If you change client settings, be sure to use the provided iterator - rfbGetClientIterator(rfbScreen) -with - rfbClientIteratorNext(iterator) -and - rfbReleaseClientIterator -to prevent thread clashes. - -Other options -------------- - -These options have to be set between rfbGetScreen and rfbInitServer. - -If you already have a socket to talk to, just set rfbScreen->inetdSock -(originally this is for inetd handling, but why not use it for your purpose?). - -To also start an HTTP server (running on port 5800+display_number), you have -to set rfbScreen->httpdDir to a directory containing vncviewer.jar and -index.vnc (like the included "webclients" directory). - -Hooks and IO functions ----------------------- - -There exist the following IO functions as members of rfbScreen: -kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText - -kbdAddEvent(rfbBool down,rfbKeySym key,rfbClientPtr cl) - is called when a key is pressed. -kbdReleaseAllKeys(rfbClientPtr cl) - is not called at all (maybe in the future). -ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) - is called when the mouse moves or a button is pressed. - WARNING: if you want to have proper cursor handling, call - rfbDefaultPtrAddEvent(buttonMask,x,y,cl) - in your own function. This sets the coordinates of the cursor. -setXCutText(char* str,int len,rfbClientPtr cl) - is called when the selection changes. - -There are only two hooks: -newClientHook(rfbClientPtr cl) - is called when a new client has connected. -displayHook - is called just before a frame buffer update is sent. - -You can also override the following methods: -getCursorPtr(rfbClientPtr cl) - This could be used to make an animated cursor (if you really want ...) -setTranslateFunction(rfbClientPtr cl) - If you insist on colour maps or something more obscure, you have to - implement this. Default is a trueColour mapping. - -Cursor handling ---------------- - -The screen holds a pointer - rfbCursorPtr cursor -to the current cursor. Whenever you set it, remember that any dynamically -created cursor (like return value from rfbMakeXCursor) is not free'd! - -The rfbCursor structure consists mainly of a mask and a source. The mask -describes, which pixels are drawn for the cursor (a cursor needn't be -rectangular). The source describes, which colour those pixels should have. - -The standard is an XCursor: a cursor with a foreground and a background -colour (stored in backRed,backGreen,backBlue and the same for foreground -in a range from 0-0xffff). Therefore, the arrays "mask" and "source" -contain pixels as single bits stored in bytes in MSB order. The rows are -padded, such that each row begins with a new byte (i.e. a 10x4 -cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). - -It is however very easy to make a cursor like this: - -char* cur=" " - " xx " - " x " - " "; -char* mask="xxxx" - "xxxx" - "xxxx" - "xxx "; -rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); - -You can even set "mask" to NULL in this call and LibVNCServer will calculate -a mask for you (dynamically, so you have to free it yourself). - -There is also an array named "richSource" for colourful cursors. They have -the same format as the frameBuffer (i.e. if the server is 32 bit, -a 10x4 cursor has 4x10x4 bytes). - -History -------- - -LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on -the original code from ORL/AT&T. - -When I began hacking with computers, my first interest was speed. So, when I -got around assembler, I programmed the floppy to do much of the work, because -its clock rate was higher than that of my C64. This was my first experience -with client/server techniques. - -When I came around Xwindows (much later), I was at once intrigued by the -elegance of such connectedness between the different computers. I used it -a lot - not the least priority lay on games. However, when I tried it over -modem from home, it was no longer that much fun. - -When I started working with ASP (Application Service Provider) programs, I -tumbled across Tarantella and Citrix. Being a security fanatic, the idea of -running a server on windows didn't appeal to me, so Citrix went down the -basket. However, Tarantella has its own problems (security as well as the -high price). But at the same time somebody told me about this "great little -administrator's tool" named VNC. Being used to windows programs' sizes, the -surprise was reciprocal inverse to the size of VNC! - -At the same time, the program "rdesktop" (a native Linux client for the -Terminal Services of Windows servers) came to my attention. There where even -works under way to make a protocol converter "rdp2vnc" out of this. However, -my primary goal was a slow connection and rdp2vnc could only speak RRE -encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original -author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is -better. I first tried that, but had no success at all (crunchy pictures). - -Also, I liked the idea of an HTTP server included and possibly other -encodings like the Tight Encodings from Const Kaplinsky. So I started looking -for libraries implementing a VNC server where I could steal what I can't make. -I found some programs based on the demo server from AT&T, which was also the -basis for rdp2vnc (can only speak Raw and RRE encoding). There were some -rumors that GGI has a VNC backend, but I didn't find any code, so probably -there wasn't a working version anyway. - -All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was -released. I looked at the code and it was not much of a problem to work out -a simple server - using every functionality there is in Xvnc. It became clear -to me that I *had* to build a library out of it, so everybody can use it. -Every change, every new feature can propagate to every user of it. - -It also makes everything easier: - You don't care about the cursor, once set (or use the standard cursor). -You don't care about those sockets. You don't care about encodings. -You just change your frame buffer and inform the library about it. Every once -in a while you call rfbProcessEvents and that's it. - -Basics ------- - -VNC (Virtual network computing) works like this: You set up a server and can -connect to it via vncviewers. The communication uses a protocol named RFB -(Remote Frame Buffer). If the server supports HTTP, you can also connect -using a java enabled browser. In this case, the server sends back a -vncviewer applet with the correct settings. - -There exist several encodings for VNC, which are used to compress the regions -which have changed before they are sent to the client. A client need not be -able to understand every encoding, but at least Raw encoding. Which encoding -it understands is negotiated by the RFB protocol. - -The following encodings are known to me: -Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and -Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al. - -If you are using a modem, you want to try the "new" encodings. Especially -with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even -beats Tarantella. - -There is the possibility to set a password, which is also negotiated by the -RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the -password. You really should tunnel through SSH. - -Windows or: why do you do that to me? --------------------------------------------- - -If you love products from Redmod, you better skip this paragraph. -I am always amazed how people react whenever Microsoft(tm) puts in some -features into their products which were around for a long time. Especially -reporters seem to not know dick about what they are reporting about! But -what is every time annoying again, is that they don't do it right. Every -concept has its new name (remember what enumerators used to be until -Mickeysoft(tm) claimed that enumerators are what we thought were iterators. -Yeah right, enumerators are also containers. They are not separated. Muddy.) - -There are three packages you want to get hold of: zlib, jpeg and pthreads. -The latter is not strictly necessary, but when you put something like this -into your source: - -``` -#define MUTEX(s) - struct { - int something; - MUTEX(latex); - } -``` - -Microsoft's C++ compiler doesn't do it. It complains that this is an error. -This, however, is how I implemented mutexes in case you don't need pthreads, -and so don't need the mutex. - -You can find the packages at -http://www.gimp.org/win32/extralibs-dev-20001007.zip - -Thanks go to all the GIMP team! - -What are those other targets in the Makefile? ---------------------------------------------- - -OSXvnc-server is the original OSXvnc adapted to use the library, which was in -turn adapted from OSXvnc. As you easily can see, the OSX dependend part is -minimal. - -storepasswd is the original program to save a vnc style password in a file. -Unfortunately, authentication as every vncviewer speaks it means the server -has to know the plain password. You really should tunnel via ssh or use -your own PasswordCheck to build a PIN/TAN system. - -sratest is a test unit. Run it to assert correct behaviour of sraRegion. I -wrote this to test my iterator implementation. - -blooptest is a test of pthreads. It is just the example, but with a background -loop to hunt down thread lockups. - -pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not -as efficient as 4 bytes/pixel for translation, because there is no native data -type of that size, so you have to memcpy pixels and be real cautious with -endianness. Anyway, it works. - -fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux -console fonts, you can browse them via VNC. Directory browsing not implemented -yet :-( - -Why I don't feel bad about GPL ------------------------------- - -At the beginning of this projects I would have liked to make it a BSD -license. However, it is based on plenty of GPL'ed code, so it has to be -a GPL. I hear BeeGee complaining: "but that's invasive, every derivative -work, even just linking, makes my software GPL!" - -Yeah. That's right. It is because there are nasty jarheads out there who -would take anybody's work and claim it their own, selling it for much too -much money, stealing freedom and innovation from others, saying they were -the maintainers of innovation, lying, making money with that. - -The people at AT&T worked really well to produce something as clean and lean -as VNC. The managers decided that for their fame, they would release the -program for free. But not only that! They realized that by releasing also -the code for free, VNC would become an evolving little child, conquering -new worlds, making its parents very proud. As well they can be! To protect -this innovation, they decided to make it GPL, not BSD. The principal -difference is: You can make closed source programs deriving from BSD, not -from GPL. You have to give proper credit with both. - -Now, why not BSD? Well, imagine your child being some famous actor. Along -comes a manager who exploits your child exclusively, that is: nobody else -can profit from the child, it itself included. Got it? - -What reason do you have now to use this library commercially? - -Several: You don't have to give away your product. Then you have effectively -circumvented the GPL, because you have the benefits of other's work and you -don't give back anything and you will be in hell for that. In fact, this -library, as my other projects, is a payback for all the free software I can -use (and sometimes, make better). For example, just now, I am using XEmacs -on top of XFree86, all running under Linux. - -Better: Use a concept like MySQL. This is free software, however, they make -money with it. If you want something implemented, you have the choice: -Ask them to do it (and pay a fair price), or do it yourself, normally giving -back your enhancements to the free world of computing. - -Learn from it: If you like the style this is written, learn how to imitate -it. If you don't like the style, learn how to avoid those things you don't -like. I learnt so much, just from looking at code like Linux, XEmacs, -LilyPond, STL, etc. - -License -------- - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf - -Contact -------- - -To contact me, mail me: Johannes dot Schindelin at gmx dot de - diff --git a/README.md b/README.md index 100b938..7f12bc0 120000..100644 --- a/README.md +++ b/README.md @@ -1 +1,476 @@ -README
\ No newline at end of file +[![Build Status](https://travis-ci.org/LibVNC/libvncserver.svg?branch=master)](https://travis-ci.org/LibVNC/libvncserver) [![Build status](https://ci.appveyor.com/api/projects/status/fao6m1md3q4g2bwn/branch/master?svg=true)](https://ci.appveyor.com/project/bk138/libvncserver/branch/master) + +LibVNCServer: A library for easy implementation of a VNC server. +Copyright (C) 2001-2003 Johannes E. Schindelin + +If you already used LibVNCServer, you probably want to read NEWS. + +What is it? +=========== + +VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They +are designed to "export" a frame buffer via net (if you don't know VNC, I +suggest you read "Basics" below). It is already in wide use for +administration, but it is not that easy to program a server yourself. + +This has been changed by LibVNCServer. + +There are two examples included: + - example, a shared scribble sheet + - pnmshow, a program to show PNMs (pictures) over the net. + +The examples are not too well documented, but easy straight forward and a +good starting point. + +Try example: it outputs on which port it listens (default: 5900), so it is +display 0. To view, call + `vncviewer :0` +You should see a sheet with a gradient and "Hello World!" written on it. Try +to paint something. Note that every time you click, there is some bigger blot, +whereas when you drag the mouse while clicked you draw a line. The size of the +blot depends on the mouse button you click. Open a second vncviewer with +the same parameters and watch it as you paint in the other window. This also +works over internet. You just have to know either the name or the IP of your +machine. Then it is + `vncviewer machine.where.example.runs.com:0` +or similar for the remote client. Now you are ready to type something. Be sure +that your mouse sits still, because every time the mouse moves, the cursor is +reset to the position of the pointer! If you are done with that demo, press +the down or up arrows. If your viewer supports it, then the dimensions of the +sheet change. Just press Escape in the viewer. Note that the server still +runs, even if you closed both windows. When you reconnect now, everything you +painted and wrote is still there. You can press "Page Up" for a blank page. + +The demo pnmshow is much simpler: you either provide a filename as argument +or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, +i.e. a truecolour graphics. Only the Escape key is implemented. This may be +the best starting point if you want to learn how to use LibVNCServer. You +are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. + +If you want to build a VNC client instead, please have a look at the [various +client examples](./client_examples). + +Projects using it +================= + +VNC for KDE +http://www.tjansen.de/krfb + +GemsVNC +http://www.elilabs.com/~rj/gemsvnc/ + +VNC for Netware +http://forge.novell.com/modules/xfmod/project/?vncnw + +RDesktop +http://rdesktop.sourceforge.net + +VNCpp +https://github.com/ocrespo/VNCpp + +VirtualBox +https://www.virtualbox.org/ + +Veyon +https://veyon.io + +Mail me, if your application is missing! + +How to build +============ + +LibVNCServer uses CMake, so you can build via: + + mkdir build + cd build + cmake .. + cmake --build . + +For some more comprehensive examples that include installation of dependencies, see +the [Unix CI](.travis.yml) and [Windows CI](.appveyor.yml) build setups. + +Crosscompiling involves some more advanced command line switches but is easily possible +as well. + +For instance, building for Android (see https://developer.android.com/ndk/guides/cmake.html as a reference): + + mkdir build + cd build + cmake .. -DANDROID_NDK=<path> -DCMAKE_TOOLCHAIN_FILE=<path> -DANDROID_NATIVE_API_LEVEL=<API level you want> -DWITH_PNG=OFF # NDK not shipping png per default + cmake --build . + + +How to use +========== + +To make a server, you just have to initialise a server structure using the +function rfbDefaultScreenInit, like + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(argc,argv,width,height,8,3,bpp); +where byte per pixel should be 1, 2 or 4. If performance doesn't matter, +you may try bpp=3 (internally one cannot use native data types in this +case; if you want to use this, look at pnmshow24). + + +You then can set hooks and io functions (see below) or other +options (see below). + +And you allocate the frame buffer like this: + rfbScreen->frameBuffer = (char*)malloc(width*height*bpp); + +After that, you initialize the server, like + rfbInitServer(rfbScreen); + +You can use a blocking event loop, a background (pthread based) event loop, +or implement your own using the rfbProcessEvents function. + +Making it interactive +--------------------- + +Input is handled by IO functions (see below). + +Whenever you change something in the frame buffer, call rfbMarkRectAsModified. + +Utility functions +----------------- + +Whenever you draw something, you have to call + rfbMarkRectAsModified(screen,x1,y1,x2,y2). +This tells LibVNCServer to send updates to all connected clients. + +Before you draw something, be sure to call + rfbUndrawCursor(screen). +This tells LibVNCServer to hide the cursor. +Remark: There are vncviewers out there, which know a cursor encoding, so +that network traffic is low, and also the cursor doesn't need to be +drawn the cursor every time an update is sent. LibVNCServer handles +all the details. Just set the cursor and don't bother any more. + +To set the mouse coordinates (or emulate mouse clicks), call + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +IMPORTANT: do this at the end of your function, because this actually draws +the cursor if no cursor encoding is active. + +What is the difference between rfbScreenInfoPtr and rfbClientPtr? +----------------------------------------------------------------- + +The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which +holds information about the server, like pixel format, io functions, +frame buffer etc. + +The rfbClientPtr is a pointer to an rfbClientRec structure, which holds +information about a client, like pixel format, socket of the +connection, etc. + +A server can have several clients, but needn't have any. So, if you +have a server and three clients are connected, you have one instance +of a rfbScreenInfo and three instances of rfbClientRec's. + +The rfbClientRec structure holds a member + rfbScreenInfoPtr screen +which points to the server and a member + rfbClientPtr next +to the next client. + +The rfbScreenInfo structure holds a member + rfbClientPtr rfbClientHead +which points to the first client. + +So, to access the server from the client structure, you use client->screen. +To access all clients from a server, get screen->rfbClientHead and +iterate using client->next. + +If you change client settings, be sure to use the provided iterator + rfbGetClientIterator(rfbScreen) +with + rfbClientIteratorNext(iterator) +and + rfbReleaseClientIterator +to prevent thread clashes. + +Other options +------------- + +These options have to be set between rfbGetScreen and rfbInitServer. + +If you already have a socket to talk to, just set rfbScreen->inetdSock +(originally this is for inetd handling, but why not use it for your purpose?). + +To also start an HTTP server (running on port 5800+display_number), you have +to set rfbScreen->httpdDir to a directory containing vncviewer.jar and +index.vnc (like the included "webclients" directory). + +Hooks and IO functions +---------------------- + +There exist the following IO functions as members of rfbScreen: +kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText + +kbdAddEvent(rfbBool down,rfbKeySym key,rfbClientPtr cl) + is called when a key is pressed. +kbdReleaseAllKeys(rfbClientPtr cl) + is not called at all (maybe in the future). +ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) + is called when the mouse moves or a button is pressed. + WARNING: if you want to have proper cursor handling, call + rfbDefaultPtrAddEvent(buttonMask,x,y,cl) + in your own function. This sets the coordinates of the cursor. +setXCutText(char* str,int len,rfbClientPtr cl) + is called when the selection changes. + +There are only two hooks: +newClientHook(rfbClientPtr cl) + is called when a new client has connected. +displayHook + is called just before a frame buffer update is sent. + +You can also override the following methods: +getCursorPtr(rfbClientPtr cl) + This could be used to make an animated cursor (if you really want ...) +setTranslateFunction(rfbClientPtr cl) + If you insist on colour maps or something more obscure, you have to + implement this. Default is a trueColour mapping. + +Cursor handling +--------------- + +The screen holds a pointer + rfbCursorPtr cursor +to the current cursor. Whenever you set it, remember that any dynamically +created cursor (like return value from rfbMakeXCursor) is not free'd! + +The rfbCursor structure consists mainly of a mask and a source. The mask +describes, which pixels are drawn for the cursor (a cursor needn't be +rectangular). The source describes, which colour those pixels should have. + +The standard is an XCursor: a cursor with a foreground and a background +colour (stored in backRed,backGreen,backBlue and the same for foreground +in a range from 0-0xffff). Therefore, the arrays "mask" and "source" +contain pixels as single bits stored in bytes in MSB order. The rows are +padded, such that each row begins with a new byte (i.e. a 10x4 +cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). + +It is however very easy to make a cursor like this: + +char* cur=" " + " xx " + " x " + " "; +char* mask="xxxx" + "xxxx" + "xxxx" + "xxx "; +rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); + +You can even set "mask" to NULL in this call and LibVNCServer will calculate +a mask for you (dynamically, so you have to free it yourself). + +There is also an array named "richSource" for colourful cursors. They have +the same format as the frameBuffer (i.e. if the server is 32 bit, +a 10x4 cursor has 4x10x4 bytes). + +History +======= + +LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on +the original code from ORL/AT&T. + +When I began hacking with computers, my first interest was speed. So, when I +got around assembler, I programmed the floppy to do much of the work, because +its clock rate was higher than that of my C64. This was my first experience +with client/server techniques. + +When I came around Xwindows (much later), I was at once intrigued by the +elegance of such connectedness between the different computers. I used it +a lot - not the least priority lay on games. However, when I tried it over +modem from home, it was no longer that much fun. + +When I started working with ASP (Application Service Provider) programs, I +tumbled across Tarantella and Citrix. Being a security fanatic, the idea of +running a server on windows didn't appeal to me, so Citrix went down the +basket. However, Tarantella has its own problems (security as well as the +high price). But at the same time somebody told me about this "great little +administrator's tool" named VNC. Being used to windows programs' sizes, the +surprise was reciprocal inverse to the size of VNC! + +At the same time, the program "rdesktop" (a native Linux client for the +Terminal Services of Windows servers) came to my attention. There where even +works under way to make a protocol converter "rdp2vnc" out of this. However, +my primary goal was a slow connection and rdp2vnc could only speak RRE +encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original +author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is +better. I first tried that, but had no success at all (crunchy pictures). + +Also, I liked the idea of an HTTP server included and possibly other +encodings like the Tight Encodings from Const Kaplinsky. So I started looking +for libraries implementing a VNC server where I could steal what I can't make. +I found some programs based on the demo server from AT&T, which was also the +basis for rdp2vnc (can only speak Raw and RRE encoding). There were some +rumors that GGI has a VNC backend, but I didn't find any code, so probably +there wasn't a working version anyway. + +All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was +released. I looked at the code and it was not much of a problem to work out +a simple server - using every functionality there is in Xvnc. It became clear +to me that I *had* to build a library out of it, so everybody can use it. +Every change, every new feature can propagate to every user of it. + +It also makes everything easier: + You don't care about the cursor, once set (or use the standard cursor). +You don't care about those sockets. You don't care about encodings. +You just change your frame buffer and inform the library about it. Every once +in a while you call rfbProcessEvents and that's it. + +Basics +====== + +VNC (Virtual network computing) works like this: You set up a server and can +connect to it via vncviewers. The communication uses a protocol named RFB +(Remote Frame Buffer). If the server supports HTTP, you can also connect +using a java enabled browser. In this case, the server sends back a +vncviewer applet with the correct settings. + +There exist several encodings for VNC, which are used to compress the regions +which have changed before they are sent to the client. A client need not be +able to understand every encoding, but at least Raw encoding. Which encoding +it understands is negotiated by the RFB protocol. + +The following encodings are known to me: +Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and +Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al. + +If you are using a modem, you want to try the "new" encodings. Especially +with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even +beats Tarantella. + +There is the possibility to set a password, which is also negotiated by the +RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the +password. You really should tunnel through SSH. + +Windows or: why do you do that to me? +===================================== + +If you love products from Redmod, you better skip this paragraph. +I am always amazed how people react whenever Microsoft(tm) puts in some +features into their products which were around for a long time. Especially +reporters seem to not know dick about what they are reporting about! But +what is every time annoying again, is that they don't do it right. Every +concept has its new name (remember what enumerators used to be until +Mickeysoft(tm) claimed that enumerators are what we thought were iterators. +Yeah right, enumerators are also containers. They are not separated. Muddy.) + +There are three packages you want to get hold of: zlib, jpeg and pthreads. +The latter is not strictly necessary, but when you put something like this +into your source: + +``` +#define MUTEX(s) + struct { + int something; + MUTEX(latex); + } +``` + +Microsoft's C++ compiler doesn't do it. It complains that this is an error. +This, however, is how I implemented mutexes in case you don't need pthreads, +and so don't need the mutex. + +You can find the packages at +http://www.gimp.org/win32/extralibs-dev-20001007.zip + +Thanks go to all the GIMP team! + +What are those other targets in the Makefile? +============================================= + +OSXvnc-server is the original OSXvnc adapted to use the library, which was in +turn adapted from OSXvnc. As you easily can see, the OSX dependend part is +minimal. + +storepasswd is the original program to save a vnc style password in a file. +Unfortunately, authentication as every vncviewer speaks it means the server +has to know the plain password. You really should tunnel via ssh or use +your own PasswordCheck to build a PIN/TAN system. + +sratest is a test unit. Run it to assert correct behaviour of sraRegion. I +wrote this to test my iterator implementation. + +blooptest is a test of pthreads. It is just the example, but with a background +loop to hunt down thread lockups. + +pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not +as efficient as 4 bytes/pixel for translation, because there is no native data +type of that size, so you have to memcpy pixels and be real cautious with +endianness. Anyway, it works. + +fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux +console fonts, you can browse them via VNC. Directory browsing not implemented +yet :-( + +Why I don't feel bad about GPL +============================== + +At the beginning of this projects I would have liked to make it a BSD +license. However, it is based on plenty of GPL'ed code, so it has to be +a GPL. I hear BeeGee complaining: "but that's invasive, every derivative +work, even just linking, makes my software GPL!" + +Yeah. That's right. It is because there are nasty jarheads out there who +would take anybody's work and claim it their own, selling it for much too +much money, stealing freedom and innovation from others, saying they were +the maintainers of innovation, lying, making money with that. + +The people at AT&T worked really well to produce something as clean and lean +as VNC. The managers decided that for their fame, they would release the +program for free. But not only that! They realized that by releasing also +the code for free, VNC would become an evolving little child, conquering +new worlds, making its parents very proud. As well they can be! To protect +this innovation, they decided to make it GPL, not BSD. The principal +difference is: You can make closed source programs deriving from BSD, not +from GPL. You have to give proper credit with both. + +Now, why not BSD? Well, imagine your child being some famous actor. Along +comes a manager who exploits your child exclusively, that is: nobody else +can profit from the child, it itself included. Got it? + +What reason do you have now to use this library commercially? + +Several: You don't have to give away your product. Then you have effectively +circumvented the GPL, because you have the benefits of other's work and you +don't give back anything and you will be in hell for that. In fact, this +library, as my other projects, is a payback for all the free software I can +use (and sometimes, make better). For example, just now, I am using XEmacs +on top of XFree86, all running under Linux. + +Better: Use a concept like MySQL. This is free software, however, they make +money with it. If you want something implemented, you have the choice: +Ask them to do it (and pay a fair price), or do it yourself, normally giving +back your enhancements to the free world of computing. + +Learn from it: If you like the style this is written, learn how to imitate +it. If you don't like the style, learn how to avoid those things you don't +like. I learnt so much, just from looking at code like Linux, XEmacs, +LilyPond, STL, etc. + +License +------- + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf + +Contact +======= + +To contact me, mail me: Johannes dot Schindelin at gmx dot de + diff --git a/client_examples/backchannel.c b/client_examples/backchannel.c index 04d154e..a7db9a0 100644 --- a/client_examples/backchannel.c +++ b/client_examples/backchannel.c @@ -71,7 +71,9 @@ static rfbClientProtocolExtension backChannel = { backChannelEncodings, /* encodings */ NULL, /* handleEncoding */ handleBackChannelMessage, /* handleMessage */ - NULL /* next extension */ + NULL, /* next extension */ + NULL, /* securityTypes */ + NULL /* handleAuthentication */ }; int diff --git a/common/d3des.c b/common/d3des.c index 2df1aab..12ccf62 100644 --- a/common/d3des.c +++ b/common/d3des.c @@ -28,12 +28,20 @@ #include "d3des.h" +#if defined(__GNUC__) +#define TLS __thread +#elif defined(_MSC_VER) +#define TLS __declspec(thread) +#else +#define TLS +#endif + static void scrunch(unsigned char *, unsigned long *); static void unscrun(unsigned long *, unsigned char *); static void desfunc(unsigned long *, unsigned long *); static void cookey(unsigned long *); -static unsigned long KnL[32] = { 0L }; +static TLS unsigned long KnL[32] = { 0L }; /* static unsigned long KnR[32] = { 0L }; static unsigned long Kn3[32] = { 0L }; @@ -43,10 +51,10 @@ static unsigned char Df_Key[24] = { 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; */ -static unsigned short bytebit[8] = { +static const unsigned short bytebit[8] = { 01, 02, 04, 010, 020, 040, 0100, 0200 }; -static unsigned long bigbyte[24] = { +static const unsigned long bigbyte[24] = { 0x800000L, 0x400000L, 0x200000L, 0x100000L, 0x80000L, 0x40000L, 0x20000L, 0x10000L, 0x8000L, 0x4000L, 0x2000L, 0x1000L, @@ -56,16 +64,16 @@ static unsigned long bigbyte[24] = { /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ -static unsigned char pc1[56] = { +static const unsigned char pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; -static unsigned char totrot[16] = { +static const unsigned char totrot[16] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; -static unsigned char pc2[48] = { +static const unsigned char pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, @@ -129,14 +137,6 @@ static void cookey(register unsigned long *raw1) return; } -void rfbCPKey(register unsigned long *into) -{ - register unsigned long *from, *endp; - - from = KnL, endp = &KnL[32]; - while( from < endp ) *into++ = *from++; - return; - } void rfbUseKey(register unsigned long *from) { @@ -186,7 +186,7 @@ static void unscrun(register unsigned long *outof, return; } -static unsigned long SP1[64] = { +static const unsigned long SP1[64] = { 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, @@ -204,7 +204,7 @@ static unsigned long SP1[64] = { 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; -static unsigned long SP2[64] = { +static const unsigned long SP2[64] = { 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, @@ -222,7 +222,7 @@ static unsigned long SP2[64] = { 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; -static unsigned long SP3[64] = { +static const unsigned long SP3[64] = { 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, @@ -240,7 +240,7 @@ static unsigned long SP3[64] = { 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; -static unsigned long SP4[64] = { +static const unsigned long SP4[64] = { 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, @@ -258,7 +258,7 @@ static unsigned long SP4[64] = { 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; -static unsigned long SP5[64] = { +static const unsigned long SP5[64] = { 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, @@ -276,7 +276,7 @@ static unsigned long SP5[64] = { 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; -static unsigned long SP6[64] = { +static const unsigned long SP6[64] = { 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, @@ -294,7 +294,7 @@ static unsigned long SP6[64] = { 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; -static unsigned long SP7[64] = { +static const unsigned long SP7[64] = { 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, @@ -312,7 +312,7 @@ static unsigned long SP7[64] = { 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; -static unsigned long SP8[64] = { +static const unsigned long SP8[64] = { 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, diff --git a/common/d3des.h b/common/d3des.h index e3761ca..bb7d182 100644 --- a/common/d3des.h +++ b/common/d3des.h @@ -37,12 +37,6 @@ extern void rfbUseKey(unsigned long *); * Loads the internal key register with the data in cookedkey. */ -extern void rfbCPKey(unsigned long *); -/* cookedkey[32] - * Copies the contents of the internal key register into the storage - * located at &cookedkey[0]. - */ - extern void rfbDes(unsigned char *, unsigned char *); /* from[8] to[8] * Encrypts/Decrypts (according to the key currently loaded in the diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index ac2a983..4541e0d 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -474,9 +474,11 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) uint8_t count=0; uint8_t loop=0; uint8_t flag=0; + rfbBool extAuthHandler; uint8_t tAuth[256]; char buf1[500],buf2[10]; uint32_t authScheme; + rfbClientProtocolExtension* e; if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; @@ -495,7 +497,18 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE; rfbClientLog("%d) Received security type %d\n", loop, tAuth[loop]); if (flag) continue; + extAuthHandler=FALSE; + for (e = rfbClientExtensions; e; e = e->next) { + if (!e->handleAuthentication) continue; + uint32_t const* secType; + for (secType = e->securityTypes; secType && *secType; secType++) { + if (tAuth[loop]==*secType) { + extAuthHandler=TRUE; + } + } + } if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth || + extAuthHandler || #if defined(LIBVNCSERVER_HAVE_GNUTLS) || defined(LIBVNCSERVER_HAVE_LIBSSL) tAuth[loop]==rfbVeNCrypt || #endif @@ -1176,6 +1189,22 @@ InitialiseRFBConnection(rfbClient* client) break; default: + { + rfbBool authHandled=FALSE; + rfbClientProtocolExtension* e; + for (e = rfbClientExtensions; e; e = e->next) { + uint32_t const* secType; + if (!e->handleAuthentication) continue; + for (secType = e->securityTypes; secType && *secType; secType++) { + if (authScheme==*secType) { + if (!e->handleAuthentication(client, authScheme)) return FALSE; + if (!rfbHandleAuthResult(client)) return FALSE; + authHandled=TRUE; + } + } + } + if (authHandled) break; + } rfbClientLog("Unknown authentication scheme from VNC server: %d\n", (int)authScheme); return FALSE; @@ -1253,6 +1282,7 @@ SetFormatAndEncodings(rfbClient* client) if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE; se->type = rfbSetEncodings; + se->pad = 0; se->nEncodings = 0; if (client->appData.encodingsString) { @@ -2426,7 +2456,6 @@ PrintPixelFormat(rfbPixelFormat *format) #define rfbDes rfbClientDes #define rfbDesKey rfbClientDesKey #define rfbUseKey rfbClientUseKey -#define rfbCPKey rfbClientCPKey #include "vncauth.c" #include "d3des.c" diff --git a/libvncclient/sasl.c b/libvncclient/sasl.c index 0530307..db240c1 100644 --- a/libvncclient/sasl.c +++ b/libvncclient/sasl.c @@ -41,6 +41,9 @@ #ifdef WIN32 #undef SOCKET #include <winsock2.h> +#ifdef EWOULDBLOCK +#undef EWOULDBLOCK +#endif #define EWOULDBLOCK WSAEWOULDBLOCK #define socklen_t int #define close closesocket diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index ed2deef..f042472 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -40,6 +40,9 @@ #ifdef WIN32 #undef SOCKET #include <winsock2.h> +#ifdef EWOULDBLOCK +#undef EWOULDBLOCK +#endif #define EWOULDBLOCK WSAEWOULDBLOCK #define close closesocket #define read(sock,buf,len) recv(sock,buf,len,0) diff --git a/libvncclient/tls.h b/libvncclient/tls.h index a5a2ac6..ffcfdeb 100644 --- a/libvncclient/tls.h +++ b/libvncclient/tls.h @@ -43,7 +43,7 @@ int ReadFromTLS(rfbClient* client, char *out, unsigned int n); * It's a wrapper function over gnutls_record_send() and it will be * blocking call, until all bytes are written or error returned. */ -int WriteToTLS(rfbClient* client, char *buf, unsigned int n); +int WriteToTLS(rfbClient* client, const char *buf, unsigned int n); /* Free TLS resources */ void FreeTLS(rfbClient* client); diff --git a/libvncclient/tls_gnutls.c b/libvncclient/tls_gnutls.c index f146d2a..ec3c450 100644 --- a/libvncclient/tls_gnutls.c +++ b/libvncclient/tls_gnutls.c @@ -589,7 +589,7 @@ ReadFromTLS(rfbClient* client, char *out, unsigned int n) } int -WriteToTLS(rfbClient* client, char *buf, unsigned int n) +WriteToTLS(rfbClient* client, const char *buf, unsigned int n) { unsigned int offset = 0; ssize_t ret; diff --git a/libvncclient/tls_none.c b/libvncclient/tls_none.c index 4dfcb27..d436ce9 100644 --- a/libvncclient/tls_none.c +++ b/libvncclient/tls_none.c @@ -43,7 +43,7 @@ int ReadFromTLS(rfbClient* client, char *out, unsigned int n) } -int WriteToTLS(rfbClient* client, char *buf, unsigned int n) +int WriteToTLS(rfbClient* client, const char *buf, unsigned int n) { rfbClientLog("TLS is not supported.\n"); errno = EINTR; diff --git a/libvncclient/tls_openssl.c b/libvncclient/tls_openssl.c index fe60147..e2fadb2 100644 --- a/libvncclient/tls_openssl.c +++ b/libvncclient/tls_openssl.c @@ -640,7 +640,7 @@ ReadFromTLS(rfbClient* client, char *out, unsigned int n) } int -WriteToTLS(rfbClient* client, char *buf, unsigned int n) +WriteToTLS(rfbClient* client, const char *buf, unsigned int n) { unsigned int offset = 0; ssize_t ret; diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c index 2a13f0e..ec1b73a 100644 --- a/libvncclient/vncviewer.c +++ b/libvncclient/vncviewer.c @@ -519,6 +519,12 @@ void rfbClientCleanup(rfbClient* client) { #endif #endif + if (client->ultra_buffer) + free(client->ultra_buffer); + + if (client->raw_buffer) + free(client->raw_buffer); + FreeTLS(client); while (client->clientData) { diff --git a/libvncserver/cargs.c b/libvncserver/cargs.c index 4da04b5..85b937d 100644 --- a/libvncserver/cargs.c +++ b/libvncserver/cargs.c @@ -43,6 +43,10 @@ rfbUsage(void) "new non-shared\n" " connection comes in (refuse new connection " "instead)\n"); +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + fprintf(stderr, "-sslkeyfile path set path to private key file for encrypted WebSockets connections\n"); + fprintf(stderr, "-sslcertfile path set path to certificate file for encrypted WebSockets connections\n"); +#endif fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n"); fprintf(stderr, "-httpport portnum use portnum for http connection\n"); #ifdef LIBVNCSERVER_IPv6 diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index bbc3d90..fe54a37 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -109,7 +109,13 @@ int deny_severity=LOG_WARNING; #pragma warning (disable: 4018 4761) #endif #define read(sock,buf,len) recv(sock,buf,len,0) +#ifdef EWOULDBLOCK +#undef EWOULDBLOCK +#endif #define EWOULDBLOCK WSAEWOULDBLOCK +#ifdef ETIMEDOUT +#undef ETIMEDOUT +#endif #define ETIMEDOUT WSAETIMEDOUT #define write(sock,buf,len) send(sock,buf,len,0) #else diff --git a/libvncserver/tight.c b/libvncserver/tight.c index 1081c8f..d6f4749 100644 --- a/libvncserver/tight.c +++ b/libvncserver/tight.c @@ -57,10 +57,11 @@ * that we resort to using thread local storage instead of having * per-client data. */ -#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#if defined(__GNUC__) #define TLS __thread -#endif -#ifndef TLS +#elif defined(_MSC_VER) +#define TLS __declspec(thread) +#else #define TLS #endif diff --git a/libvncserver/tightvnc-filetransfer/filetransfermsg.c b/libvncserver/tightvnc-filetransfer/filetransfermsg.c index 5f84e7f..0003b11 100644 --- a/libvncserver/tightvnc-filetransfer/filetransfermsg.c +++ b/libvncserver/tightvnc-filetransfer/filetransfermsg.c @@ -672,7 +672,7 @@ ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf) char reason[] = "Error writing file data"; int reasonLen = strlen(reason); ftm = CreateFileUploadErrMsg(reason, reasonLen); - CloseUndoneFileTransfer(cl, rtcp); + CloseUndoneFileUpload(cl, rtcp); } return ftm; } @@ -735,7 +735,7 @@ CreateFileUploadErrMsg(char* reason, unsigned int reasonLen) ******************************************************************************/ void -CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp) +CloseUndoneFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp) { /* TODO :: File Upload case is not handled currently */ /* TODO :: In case of concurrency we need to use Critical Section */ @@ -759,9 +759,19 @@ CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp) memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX); } +} + + +void +CloseUndoneFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + if(cl == NULL) + return; if(rtcp->rcft.rcfd.downloadInProgress == TRUE) { rtcp->rcft.rcfd.downloadInProgress = FALSE; + /* the thread will return if downloadInProgress is FALSE */ + pthread_join(rtcp->rcft.rcfd.downloadThread, NULL); if(rtcp->rcft.rcfd.downloadFD != -1) { close(rtcp->rcft.rcfd.downloadFD); diff --git a/libvncserver/tightvnc-filetransfer/filetransfermsg.h b/libvncserver/tightvnc-filetransfer/filetransfermsg.h index 3b27bd0..bbb9148 100644 --- a/libvncserver/tightvnc-filetransfer/filetransfermsg.h +++ b/libvncserver/tightvnc-filetransfer/filetransfermsg.h @@ -51,7 +51,8 @@ FileTransferMsg ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr data, c void CreateDirectory(char* dirName); void FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr data); -void CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr data); +void CloseUndoneFileUpload(rfbClientPtr cl, rfbTightClientPtr data); +void CloseUndoneFileDownload(rfbClientPtr cl, rfbTightClientPtr data); void FreeFileTransferMsg(FileTransferMsg ftm); diff --git a/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c b/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c index 0473783..71fb085 100644 --- a/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c +++ b/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c @@ -489,12 +489,6 @@ RunFileDownloadThread(void* client) if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0) { rfbLog("File [%s]: Method [%s]: Error while writing to socket \n" , __FILE__, __FUNCTION__); - - if(cl != NULL) { - rfbCloseClient(cl); - CloseUndoneFileTransfer(cl, rtcp); - } - FreeFileTransferMsg(fileDownloadMsg); return NULL; } @@ -508,7 +502,6 @@ RunFileDownloadThread(void* client) void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp) { - pthread_t fileDownloadThread; FileTransferMsg fileDownloadMsg; memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); @@ -518,10 +511,9 @@ HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp) FreeFileTransferMsg(fileDownloadMsg); return; } - rtcp->rcft.rcfd.downloadInProgress = FALSE; - rtcp->rcft.rcfd.downloadFD = -1; + CloseUndoneFileDownload(cl, rtcp); - if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*) + if(pthread_create(&rtcp->rcft.rcfd.downloadThread, NULL, RunFileDownloadThread, (void*) cl) != 0) { FileTransferMsg ftm = GetFileDownLoadErrMsg(); @@ -593,7 +585,7 @@ HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) " reason <%s>\n", __FILE__, __FUNCTION__, reason); pthread_mutex_lock(&fileDownloadMutex); - CloseUndoneFileTransfer(cl, rtcp); + CloseUndoneFileDownload(cl, rtcp); pthread_mutex_unlock(&fileDownloadMutex); if(reason != NULL) { @@ -836,7 +828,7 @@ HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) FreeFileTransferMsg(ftm); } - CloseUndoneFileTransfer(cl, rtcp); + CloseUndoneFileUpload(cl, rtcp); if(pBuf != NULL) { free(pBuf); @@ -936,7 +928,7 @@ HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:" " reason <%s>\n", __FILE__, __FUNCTION__, reason); - CloseUndoneFileTransfer(cl, rtcp); + CloseUndoneFileUpload(cl, rtcp); if(reason != NULL) { free(reason); diff --git a/libvncserver/tightvnc-filetransfer/rfbtightproto.h b/libvncserver/tightvnc-filetransfer/rfbtightproto.h index d0fe642..30fc5f5 100644 --- a/libvncserver/tightvnc-filetransfer/rfbtightproto.h +++ b/libvncserver/tightvnc-filetransfer/rfbtightproto.h @@ -148,6 +148,7 @@ typedef struct _rfbClientFileDownload { int downloadInProgress; unsigned long mTime; int downloadFD; + pthread_t downloadThread; } rfbClientFileDownload ; typedef struct _rfbClientFileUpload { diff --git a/libvncserver/tightvnc-filetransfer/rfbtightserver.c b/libvncserver/tightvnc-filetransfer/rfbtightserver.c index 67d4cb5..651d8fb 100644 --- a/libvncserver/tightvnc-filetransfer/rfbtightserver.c +++ b/libvncserver/tightvnc-filetransfer/rfbtightserver.c @@ -26,6 +26,7 @@ #include <rfb/rfb.h> #include "rfbtightproto.h" #include "handlefiletransferrequest.h" +#include "filetransfermsg.h" /* * Get my data! @@ -448,9 +449,11 @@ rfbTightExtensionMsgHandler(struct _rfbClientRec* cl, void* data, void rfbTightExtensionClientClose(rfbClientPtr cl, void* data) { - if(data != NULL) + if(data != NULL) { + CloseUndoneFileUpload(cl, data); + CloseUndoneFileDownload(cl, data); free(data); - + } } void diff --git a/libvncserver/zlib.c b/libvncserver/zlib.c index 45a1314..6fee4df 100644 --- a/libvncserver/zlib.c +++ b/libvncserver/zlib.c @@ -45,10 +45,11 @@ * tight. N.B. ZRLE does it the traditional way with per-client storage * (and so at least ZRLE will work threaded on older systems.) */ -#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#if defined(__GNUC__) #define TLS __thread -#endif -#ifndef TLS +#elif defined(_MSC_VER) +#define TLS __declspec(thread) +#else #define TLS #endif diff --git a/rfb/default8x16.h b/rfb/default8x16.h index 252f411..6096b1c 100644 --- a/rfb/default8x16.h +++ b/rfb/default8x16.h @@ -1,3 +1,6 @@ +#ifndef _DEFAULT_8_X_16_H +#define _DEFAULT_8_X_16_H + static unsigned char default8x16FontData[4096+1]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, @@ -259,3 +262,5 @@ static unsigned char default8x16FontData[4096+1]={ static int default8x16FontMetaData[256*5+1]={ 0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; + +#endif diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index 87f4eaa..1a80f0d 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -620,6 +620,9 @@ typedef struct _rfbClientProtocolExtension { rfbBool (*handleMessage)(rfbClient* cl, rfbServerToClientMsg* message); struct _rfbClientProtocolExtension* next; + uint32_t const* securityTypes; + /** returns TRUE if it handled the authentication */ + rfbBool (*handleAuthentication)(rfbClient* cl, uint32_t authScheme); } rfbClientProtocolExtension; void rfbClientRegisterExtension(rfbClientProtocolExtension* e); |