San Mehat | a430b2b | 2014-09-23 08:30:51 -0700 | [diff] [blame] | 1 | LibVNCServer: A library for easy implementation of a VNC server. |
| 2 | Copyright (C) 2001-2003 Johannes E. Schindelin |
| 3 | |
| 4 | If you already used LibVNCServer, you probably want to read NEWS. |
| 5 | |
| 6 | What is it? |
| 7 | ----------- |
| 8 | |
| 9 | VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They |
| 10 | are designed to "export" a frame buffer via net (if you don't know VNC, I |
| 11 | suggest you read "Basics" below). It is already in wide use for |
| 12 | administration, but it is not that easy to program a server yourself. |
| 13 | |
| 14 | This has been changed by LibVNCServer. |
| 15 | |
| 16 | There are two examples included: |
| 17 | - example, a shared scribble sheet |
| 18 | - pnmshow, a program to show PNMs (pictures) over the net. |
| 19 | |
| 20 | The examples are not too well documented, but easy straight forward and a |
| 21 | good starting point. |
| 22 | |
| 23 | Try example: it outputs on which port it listens (default: 5900), so it is |
| 24 | display 0. To view, call |
| 25 | vncviewer :0 |
| 26 | You should see a sheet with a gradient and "Hello World!" written on it. Try |
| 27 | to paint something. Note that everytime you click, there is some bigger blot, |
| 28 | whereas when you drag the mouse while clicked you draw a line. The size of the |
| 29 | blot depends on the mouse button you click. Open a second vncviewer with |
| 30 | the same parameters and watch it as you paint in the other window. This also |
| 31 | works over internet. You just have to know either the name or the IP of your |
| 32 | machine. Then it is |
| 33 | vncviewer machine.where.example.runs.com:0 |
| 34 | or similar for the remote client. Now you are ready to type something. Be sure |
| 35 | that your mouse sits still, because everytime the mouse moves, the cursor is |
| 36 | reset to the position of the pointer! If you are done with that demo, press |
| 37 | the down or up arrows. If your viewer supports it, then the dimensions of the |
| 38 | sheet change. Just press Escape in the viewer. Note that the server still |
| 39 | runs, even if you closed both windows. When you reconnect now, everything you |
| 40 | painted and wrote is still there. You can press "Page Up" for a blank page. |
| 41 | |
| 42 | The demo pnmshow is much simpler: you either provide a filename as argument |
| 43 | or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, |
| 44 | i.e. a truecolour graphics. Only the Escape key is implemented. This may be |
| 45 | the best starting point if you want to learn how to use LibVNCServer. You |
| 46 | are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. |
| 47 | |
| 48 | Projects using it |
| 49 | ---------------------------------------- |
| 50 | |
| 51 | VNC for KDE |
| 52 | http://www.tjansen.de/krfb |
| 53 | |
| 54 | GemsVNC |
| 55 | http://www.elilabs.com/~rj/gemsvnc/ |
| 56 | |
| 57 | VNC for Netware |
| 58 | http://forge.novell.com/modules/xfmod/project/?vncnw |
| 59 | |
| 60 | RDesktop |
| 61 | http://rdesktop.sourceforge.net |
| 62 | |
| 63 | Mail me, if your application is missing! |
| 64 | |
| 65 | How to use |
| 66 | ---------- |
| 67 | |
| 68 | To make a server, you just have to initialise a server structure using the |
| 69 | function rfbDefaultScreenInit, like |
| 70 | rfbScreenInfoPtr rfbScreen = |
| 71 | rfbGetScreen(argc,argv,width,height,8,3,bpp); |
| 72 | where byte per pixel should be 1, 2 or 4. If performance doesn't matter, |
| 73 | you may try bpp=3 (internally one cannot use native data types in this |
| 74 | case; if you want to use this, look at pnmshow24). |
| 75 | |
| 76 | |
| 77 | You then can set hooks and io functions (see below) or other |
| 78 | options (see below). |
| 79 | |
| 80 | And you allocate the frame buffer like this: |
| 81 | rfbScreen->frameBuffer = (char*)malloc(width*height*bpp); |
| 82 | |
| 83 | After that, you initialize the server, like |
| 84 | rfbInitServer(rfbScreen); |
| 85 | |
| 86 | You can use a blocking event loop, a background (pthread based) event loop, |
| 87 | or implement your own using the rfbProcessEvents function. |
| 88 | |
| 89 | Making it interactive |
| 90 | --------------------- |
| 91 | |
| 92 | Input is handled by IO functions (see below). |
| 93 | |
| 94 | Whenever you change something in the frame buffer, call rfbMarkRectAsModified. |
| 95 | You should make sure that the cursor is not drawn before drawing yourself |
| 96 | by calling rfbUndrawCursor. You can also draw the cursor using rfbDrawCursor, |
| 97 | but it hardly seems necessary. For cursor details, see below. |
| 98 | |
| 99 | Utility functions |
| 100 | ----------------- |
| 101 | |
| 102 | Whenever you draw something, you have to call |
| 103 | rfbMarkRectAsModified(screen,x1,y1,x2,y2). |
| 104 | This tells LibVNCServer to send updates to all connected clients. |
| 105 | |
| 106 | Before you draw something, be sure to call |
| 107 | rfbUndrawCursor(screen). |
| 108 | This tells LibVNCServer to hide the cursor. |
| 109 | Remark: There are vncviewers out there, which know a cursor encoding, so |
| 110 | that network traffic is low, and also the cursor doesn't need to be |
| 111 | drawn the cursor everytime an update is sent. LibVNCServer handles |
| 112 | all the details. Just set the cursor and don't bother any more. |
| 113 | |
| 114 | To set the mouse coordinates (or emulate mouse clicks), call |
| 115 | defaultPtrAddEvent(buttonMask,x,y,cl); |
| 116 | IMPORTANT: do this at the end of your function, because this actually draws |
| 117 | the cursor if no cursor encoding is active. |
| 118 | |
| 119 | What is the difference between rfbScreenInfoPtr and rfbClientPtr? |
| 120 | ----------------------------------------------------------------- |
| 121 | |
| 122 | The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which |
| 123 | holds information about the server, like pixel format, io functions, |
| 124 | frame buffer etc. |
| 125 | |
| 126 | The rfbClientPtr is a pointer to an rfbClientRec structure, which holds |
| 127 | information about a client, like pixel format, socket of the |
| 128 | connection, etc. |
| 129 | |
| 130 | A server can have several clients, but needn't have any. So, if you |
| 131 | have a server and three clients are connected, you have one instance |
| 132 | of a rfbScreenInfo and three instances of rfbClientRec's. |
| 133 | |
| 134 | The rfbClientRec structure holds a member |
| 135 | rfbScreenInfoPtr screen |
| 136 | which points to the server and a member |
| 137 | rfbClientPtr next |
| 138 | to the next client. |
| 139 | |
| 140 | The rfbScreenInfo structure holds a member |
| 141 | rfbClientPtr rfbClientHead |
| 142 | which points to the first client. |
| 143 | |
| 144 | So, to access the server from the client structure, you use client->screen. |
| 145 | To access all clients from a server, get screen->rfbClientHead and |
| 146 | iterate using client->next. |
| 147 | |
| 148 | If you change client settings, be sure to use the provided iterator |
| 149 | rfbGetClientIterator(rfbScreen) |
| 150 | with |
| 151 | rfbClientIteratorNext(iterator) |
| 152 | and |
| 153 | rfbReleaseClientIterator |
| 154 | to prevent thread clashes. |
| 155 | |
| 156 | Other options |
| 157 | ------------- |
| 158 | |
| 159 | These options have to be set between rfbGetScreen and rfbInitServer. |
| 160 | |
| 161 | If you already have a socket to talk to, just set rfbScreen->inetdSock |
| 162 | (originally this is for inetd handling, but why not use it for your purpose?). |
| 163 | |
| 164 | To also start an HTTP server (running on port 5800+display_number), you have |
| 165 | to set rfbScreen->httpdDir to a directory containing vncviewer.jar and |
| 166 | index.vnc (like the included "webclients" directory). |
| 167 | |
| 168 | Hooks and IO functions |
| 169 | ---------------------- |
| 170 | |
| 171 | There exist the following IO functions as members of rfbScreen: |
| 172 | kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText |
| 173 | |
| 174 | kbdAddEvent(rfbBool down,rfbKeySym key,rfbClientPtr cl) |
| 175 | is called when a key is pressed. |
| 176 | kbdReleaseAllKeys(rfbClientPtr cl) |
| 177 | is not called at all (maybe in the future). |
| 178 | ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) |
| 179 | is called when the mouse moves or a button is pressed. |
| 180 | WARNING: if you want to have proper cursor handling, call |
| 181 | defaultPtrAddEvent(buttonMask,x,y,cl) |
| 182 | in your own function. This sets the coordinates of the cursor. |
| 183 | setXCutText(char* str,int len,rfbClientPtr cl) |
| 184 | is called when the selection changes. |
| 185 | |
| 186 | There are only two hooks: |
| 187 | newClientHook(rfbClientPtr cl) |
| 188 | is called when a new client has connected. |
| 189 | displayHook |
| 190 | is called just before a frame buffer update is sent. |
| 191 | |
| 192 | You can also override the following methods: |
| 193 | getCursorPtr(rfbClientPtr cl) |
| 194 | This could be used to make an animated cursor (if you really want ...) |
| 195 | setTranslateFunction(rfbClientPtr cl) |
| 196 | If you insist on colour maps or something more obscure, you have to |
| 197 | implement this. Default is a trueColour mapping. |
| 198 | |
| 199 | Cursor handling |
| 200 | --------------- |
| 201 | |
| 202 | The screen holds a pointer |
| 203 | rfbCursorPtr cursor |
| 204 | to the current cursor. Whenever you set it, remember that any dynamically |
| 205 | created cursor (like return value from rfbMakeXCursor) is not free'd! |
| 206 | |
| 207 | The rfbCursor structure consists mainly of a mask and a source. The mask |
| 208 | describes, which pixels are drawn for the cursor (a cursor needn't be |
| 209 | rectangular). The source describes, which colour those pixels should have. |
| 210 | |
| 211 | The standard is an XCursor: a cursor with a foreground and a background |
| 212 | colour (stored in backRed,backGreen,backBlue and the same for foreground |
| 213 | in a range from 0-0xffff). Therefore, the arrays "mask" and "source" |
| 214 | contain pixels as single bits stored in bytes in MSB order. The rows are |
| 215 | padded, such that each row begins with a new byte (i.e. a 10x4 |
| 216 | cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). |
| 217 | |
| 218 | It is however very easy to make a cursor like this: |
| 219 | |
| 220 | char* cur=" " |
| 221 | " xx " |
| 222 | " x " |
| 223 | " "; |
| 224 | char* mask="xxxx" |
| 225 | "xxxx" |
| 226 | "xxxx" |
| 227 | "xxx "; |
| 228 | rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); |
| 229 | |
| 230 | You can even set "mask" to NULL in this call and LibVNCServer will calculate |
| 231 | a mask for you (dynamically, so you have to free it yourself). |
| 232 | |
| 233 | There is also an array named "richSource" for colourful cursors. They have |
| 234 | the same format as the frameBuffer (i.e. if the server is 32 bit, |
| 235 | a 10x4 cursor has 4x10x4 bytes). |
| 236 | |
| 237 | History |
| 238 | ------- |
| 239 | |
| 240 | LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on |
| 241 | the original code from ORL/AT&T. |
| 242 | |
| 243 | When I began hacking with computers, my first interest was speed. So, when I |
| 244 | got around assembler, I programmed the floppy to do much of the work, because |
| 245 | it's clock rate was higher than that of my C64. This was my first experience |
| 246 | with client/server techniques. |
| 247 | |
| 248 | When I came around Xwindows (much later), I was at once intrigued by the |
| 249 | elegance of such connectedness between the different computers. I used it |
| 250 | a lot - not the least priority lay on games. However, when I tried it over |
| 251 | modem from home, it was no longer that much fun. |
| 252 | |
| 253 | When I started working with ASP (Application Service Provider) programs, I |
| 254 | tumbled across Tarantella and Citrix. Being a security fanatic, the idea of |
| 255 | running a server on windows didn't appeal to me, so Citrix went down the |
| 256 | basket. However, Tarantella has it's own problems (security as well as the |
| 257 | high price). But at the same time somebody told me about this "great little |
| 258 | administrator's tool" named VNC. Being used to windows programs' sizes, the |
| 259 | surprise was reciprocal inverse to the size of VNC! |
| 260 | |
| 261 | At the same time, the program "rdesktop" (a native Linux client for the |
| 262 | Terminal Services of Windows servers) came to my attention. There where even |
| 263 | works under way to make a protocol converter "rdp2vnc" out of this. However, |
| 264 | my primary goal was a slow connection and rdp2vnc could only speak RRE |
| 265 | encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original |
| 266 | author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is |
| 267 | better. I first tried that, but had no success at all (crunchy pictures). |
| 268 | |
| 269 | Also, I liked the idea of an HTTP server included and possibly other |
| 270 | encodings like the Tight Encodings from Const Kaplinsky. So I started looking |
| 271 | for libraries implementing a VNC server where I could steal what I can't make. |
| 272 | I found some programs based on the demo server from AT&T, which was also the |
| 273 | basis for rdp2vnc (can only speak Raw and RRE encoding). There were some |
| 274 | rumors that GGI has a VNC backend, but I didn't find any code, so probably |
| 275 | there wasn't a working version anyway. |
| 276 | |
| 277 | All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was |
| 278 | released. I looked at the code and it was not much of a problem to work out |
| 279 | a simple server - using every functionality there is in Xvnc. It became clear |
| 280 | to me that I *had* to build a library out of it, so everybody can use it. |
| 281 | Every change, every new feature can propagate to every user of it. |
| 282 | |
| 283 | It also makes everything easier: |
| 284 | You don't care about the cursor, once set (or use the standard cursor). |
| 285 | You don't care about those sockets. You don't care about encodings. |
| 286 | You just change your frame buffer and inform the library about it. Every once |
| 287 | in a while you call rfbProcessEvents and that's it. |
| 288 | |
| 289 | Basics |
| 290 | ------ |
| 291 | |
| 292 | VNC (Virtual network computing) works like this: You set up a server and can |
| 293 | connect to it via vncviewers. The communication uses a protocol named RFB |
| 294 | (Remote Frame Buffer). If the server supports HTTP, you can also connect |
| 295 | using a java enabled browser. In this case, the server sends back a |
| 296 | vncviewer applet with the correct settings. |
| 297 | |
| 298 | There exist several encodings for VNC, which are used to compress the regions |
| 299 | which have changed before they are sent to the client. A client need not be |
| 300 | able to understand every encoding, but at least Raw encoding. Which encoding |
| 301 | it understands is negotiated by the RFB protocol. |
| 302 | |
| 303 | The following encodings are known to me: |
| 304 | Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and |
| 305 | Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al. |
| 306 | |
| 307 | If you are using a modem, you want to try the "new" encodings. Especially |
| 308 | with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even |
| 309 | beats Tarantella. |
| 310 | |
| 311 | There is the possibility to set a password, which is also negotiated by the |
| 312 | RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the |
| 313 | password. You really should tunnel through SSH. |
| 314 | |
| 315 | Windows or: why do you do that to me? |
| 316 | -------------------------------------------- |
| 317 | |
| 318 | If you love products from Redmod, you better skip this paragraph. |
| 319 | I am always amazed how people react whenever Microsoft(tm) puts in some |
| 320 | features into their products which were around for a long time. Especially |
| 321 | reporters seem to not know dick about what they are reporting about! But |
| 322 | what is everytime annoying again, is that they don't do it right. Every |
| 323 | concept has it's new name (remember what enumerators used to be until |
| 324 | Mickeysoft(tm) claimed that enumerators are what we thought were iterators. |
| 325 | Yeah right, enumerators are also containers. They are not separated. Muddy.) |
| 326 | |
| 327 | There are three packages you want to get hold of: zlib, jpeg and pthreads. |
| 328 | The latter is not strictly necessary, but when you put something like this |
| 329 | into your source: |
| 330 | |
| 331 | #define MUTEX(s) |
| 332 | struct { |
| 333 | int something; |
| 334 | MUTEX(latex); |
| 335 | } |
| 336 | |
| 337 | Microsoft's C++ compiler doesn't do it. It complains that this is an error. |
| 338 | This, however, is how I implemented mutexes in case you don't need pthreads, |
| 339 | and so don't need the mutex. |
| 340 | |
| 341 | You can find the packages at |
| 342 | http://www.gimp.org/win32/extralibs-dev-20001007.zip |
| 343 | |
| 344 | Thanks go to all the GIMP team! |
| 345 | |
| 346 | What are those other targets in the Makefile? |
| 347 | --------------------------------------------- |
| 348 | |
| 349 | OSXvnc-server is the original OSXvnc adapted to use the library, which was in |
| 350 | turn adapted from OSXvnc. As you easily can see, the OSX dependend part is |
| 351 | minimal. |
| 352 | |
| 353 | storepasswd is the original program to save a vnc style password in a file. |
| 354 | Unfortunately, authentication as every vncviewer speaks it means the server |
| 355 | has to know the plain password. You really should tunnel via ssh or use |
| 356 | your own PasswordCheck to build a PIN/TAN system. |
| 357 | |
| 358 | sratest is a test unit. Run it to assert correct behaviour of sraRegion. I |
| 359 | wrote this to test my iterator implementation. |
| 360 | |
| 361 | blooptest is a test of pthreads. It is just the example, but with a background |
| 362 | loop to hunt down thread lockups. |
| 363 | |
| 364 | pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not |
| 365 | as efficient as 4 bytes/pixel for translation, because there is no native data |
| 366 | type of that size, so you have to memcpy pixels and be real cautious with |
| 367 | endianness. Anyway, it works. |
| 368 | |
| 369 | fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux |
| 370 | console fonts, you can browse them via VNC. Directory browsing not implemented |
| 371 | yet :-( |
| 372 | |
| 373 | Why I don't feel bad about GPL |
| 374 | ------------------------------ |
| 375 | |
| 376 | At the beginning of this projects I would have liked to make it a BSD |
| 377 | license. However, it is based on plenty of GPL'ed code, so it has to be |
| 378 | a GPL. I hear BeeGee complaining: "but that's invasive, every derivative |
| 379 | work, even just linking, makes my software GPL!" |
| 380 | |
| 381 | Yeah. That's right. It is because there are nasty jarheads out there who |
| 382 | would take anybody's work and claim it their own, selling it for much too |
| 383 | much money, stealing freedom and innovation from others, saying they were |
| 384 | the maintainers of innovation, lying, making money with that. |
| 385 | |
| 386 | The people at AT&T worked really well to produce something as clean and lean |
| 387 | as VNC. The managers decided that for their fame, they would release the |
| 388 | program for free. But not only that! They realized that by releasing also |
| 389 | the code for free, VNC would become an evolving little child, conquering |
| 390 | new worlds, making it's parents very proud. As well they can be! To protect |
| 391 | this innovation, they decided to make it GPL, not BSD. The principal |
| 392 | difference is: You can make closed source programs deriving from BSD, not |
| 393 | from GPL. You have to give proper credit with both. |
| 394 | |
| 395 | Now, why not BSD? Well, imagine your child being some famous actor. Along |
| 396 | comes a manager who exploits your child exclusively, that is: nobody else |
| 397 | can profit from the child, it itself included. Got it? |
| 398 | |
| 399 | What reason do you have now to use this library commercially? |
| 400 | |
| 401 | Several: You don't have to give away your product. Then you have effectively |
| 402 | circumvented the GPL, because you have the benefits of other's work and you |
| 403 | don't give back anything and you will be in hell for that. In fact, this |
| 404 | library, as my other projects, is a payback for all the free software I can |
| 405 | use (and sometimes, make better). For example, just now, I am using XEmacs |
| 406 | on top of XFree86, all running under Linux. |
| 407 | |
| 408 | Better: Use a concept like MySQL. This is free software, however, they make |
| 409 | money with it. If you want something implemented, you have the choice: |
| 410 | Ask them to do it (and pay a fair price), or do it yourself, normally giving |
| 411 | back your enhancements to the free world of computing. |
| 412 | |
| 413 | Learn from it: If you like the style this is written, learn how to imitate |
| 414 | it. If you don't like the style, learn how to avoid those things you don't |
| 415 | like. I learnt so much, just from looking at code like Linux, XEmacs, |
| 416 | LilyPond, STL, etc. |
| 417 | |
| 418 | License |
| 419 | ------- |
| 420 | |
| 421 | This program is free software; you can redistribute it and/or |
| 422 | modify it under the terms of the GNU General Public License |
| 423 | as published by the Free Software Foundation; either version 2 |
| 424 | of the License, or (at your option) any later version. |
| 425 | |
| 426 | This program is distributed in the hope that it will be useful, |
| 427 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 428 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 429 | GNU General Public License for more details. |
| 430 | |
| 431 | You should have received a copy of the GNU General Public License |
| 432 | along with this program; if not, write to the Free Software |
| 433 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf |
| 434 | |
| 435 | Contact |
| 436 | ------- |
| 437 | |
| 438 | To contact me, mail me: Johannes dot Schindelin at gmx dot de |
| 439 | |