~ubuntu-branches/ubuntu/dapper/vino/dapper

« back to all changes in this revision

Viewing changes to server/vino-server.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2004-10-12 19:36:40 UTC
  • Revision ID: james.westby@ubuntu.com-20041012193640-ybetkwuqt7e04dke
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003 Sun Microsystems, Inc.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
17
 * 02111-1307, USA.
 
18
 *
 
19
 * Authors:
 
20
 *      Mark McLoughlin <mark@skynet.ie>
 
21
 */
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#include "vino-server.h"
 
26
 
 
27
#include <rfb/rfb.h>
 
28
#include "vino-fb.h"
 
29
#ifdef VINO_ENABLE_HTTP_SERVER
 
30
#include "vino-http.h"
 
31
#endif
 
32
#include "vino-input.h"
 
33
#include "vino-cursor.h"
 
34
#include "vino-prompt.h"
 
35
#include "vino-util.h"
 
36
#include "vino-enums.h"
 
37
#include <sys/poll.h>
 
38
 
 
39
/* If an authentication attempt failes, delay the next
 
40
 * authentication attempt for 5 seconds.
 
41
 */
 
42
#define VINO_SERVER_AUTH_DEFER_LEN 5
 
43
 
 
44
struct _VinoServerPrivate
 
45
{
 
46
  rfbScreenInfoPtr  rfb_screen;
 
47
 
 
48
  GdkScreen        *screen;
 
49
  VinoFB           *fb;
 
50
  VinoCursorData   *cursor_data;
 
51
  VinoPrompt       *prompt;
 
52
 
 
53
  GIOChannel       *io_channel;
 
54
  guint             io_watch;
 
55
 
 
56
  GSList           *clients;
 
57
 
 
58
  VinoAuthMethod    auth_methods;
 
59
  char             *vnc_password;
 
60
 
 
61
#ifdef VINO_ENABLE_HTTP_SERVER
 
62
  VinoHTTP         *http;
 
63
#endif
 
64
 
 
65
  guint             on_hold : 1;
 
66
  guint             prompt_enabled : 1;
 
67
  guint             view_only : 1;
 
68
  guint             require_encryption : 1;
 
69
  guint             last_auth_failed : 1;
 
70
};
 
71
 
 
72
typedef struct
 
73
{
 
74
  rfbClientPtr  rfb_client;
 
75
  GIOChannel   *io_channel;
 
76
  guint         io_watch;
 
77
  guint         update_timeout;
 
78
 
 
79
  /* Deferred authentication */
 
80
  guint         auth_timeout;
 
81
  char         *auth_response;
 
82
  int           auth_resp_len;
 
83
} VinoServerClientInfo;
 
84
 
 
85
enum
 
86
{
 
87
  PROP_0,
 
88
  PROP_SCREEN,
 
89
  PROP_ON_HOLD,
 
90
  PROP_PROMPT_ENABLED,
 
91
  PROP_VIEW_ONLY,
 
92
  PROP_REQUIRE_ENCRYPTION,
 
93
  PROP_AUTH_METHODS,
 
94
  PROP_VNC_PASSWORD
 
95
};
 
96
 
 
97
static enum rfbNewClientAction vino_server_auth_client (VinoServer           *server,
 
98
                                                        VinoServerClientInfo *client,
 
99
                                                        const char           *response,
 
100
                                                        int                   length);
 
101
 
 
102
static void vino_server_setup_framebuffer   (VinoServer *server);
 
103
static void vino_server_release_framebuffer (VinoServer *server);
 
104
 
 
105
static gpointer parent_class;
 
106
 
 
107
static void
 
108
vino_server_handle_client_gone (rfbClientPtr rfb_client)
 
109
{
 
110
  VinoServer           *server = VINO_SERVER (rfb_client->screen->screenData);
 
111
  VinoServerClientInfo *client = NULL;
 
112
  GSList               *l;
 
113
 
 
114
  g_return_if_fail (VINO_IS_SERVER (server));
 
115
 
 
116
  dprintf (RFB, "Client with fd == %d gone\n", rfb_client->sock);
 
117
 
 
118
  vino_prompt_remove_client (server->priv->prompt, rfb_client);
 
119
 
 
120
  for (l = server->priv->clients; l; l = l->next)
 
121
    {
 
122
      client = (VinoServerClientInfo *) l->data;
 
123
 
 
124
      if (rfb_client == client->rfb_client)
 
125
        {
 
126
          dprintf (RFB, "Found client %p ... cleaning up\n", client->rfb_client);
 
127
 
 
128
          if (client->auth_timeout)
 
129
            g_source_remove (client->auth_timeout);
 
130
          client->auth_timeout = 0;
 
131
 
 
132
          if (client->auth_response)
 
133
            g_free (client->auth_response);
 
134
          client->auth_response = NULL;
 
135
          client->auth_resp_len = 0;
 
136
 
 
137
          if (client->update_timeout)
 
138
            g_source_remove (client->update_timeout);
 
139
          client->update_timeout = 0;
 
140
 
 
141
          g_source_remove (client->io_watch);
 
142
          client->io_watch = 0;
 
143
 
 
144
          g_io_channel_unref (client->io_channel);
 
145
          client->io_channel = NULL;
 
146
 
 
147
          g_free (l->data);
 
148
          server->priv->clients = g_slist_delete_link (server->priv->clients, l);
 
149
          break;
 
150
        }
 
151
    }
 
152
 
 
153
  if (!server->priv->clients)
 
154
    vino_server_release_framebuffer (server);
 
155
}
 
156
 
 
157
static gboolean
 
158
vino_server_update_client (rfbClientPtr rfb_client)
 
159
{
 
160
  VinoServer *server = VINO_SERVER (rfb_client->screen->screenData);
 
161
  const char *cursor_source;
 
162
  const char *cursor_mask;
 
163
  int         x, y;
 
164
  int         width, height;
 
165
 
 
166
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
167
 
 
168
  if (vino_cursor_get_x_source (server->priv->cursor_data,
 
169
                                &width, &height,
 
170
                                &cursor_source, &cursor_mask))
 
171
    {
 
172
      rfbCursorPtr rfb_cursor;
 
173
 
 
174
      rfb_cursor = rfbMakeXCursor (width, height, cursor_source, cursor_mask);
 
175
      rfbSetCursor (rfb_client->screen, rfb_cursor, TRUE);
 
176
    }
 
177
 
 
178
  vino_cursor_get_position (server->priv->cursor_data, &x, &y);
 
179
  rfbSetCursorPosition (rfb_client->screen, NULL, x, y);
 
180
 
 
181
  rfbUpdateClient (rfb_client);
 
182
 
 
183
  if (rfb_client->sock == -1)
 
184
    {
 
185
      rfbClientConnectionGone (rfb_client);
 
186
      return FALSE;
 
187
    }
 
188
  
 
189
  return TRUE;
 
190
}
 
191
 
 
192
static gboolean
 
193
vino_server_update_client_timeout (rfbClientPtr rfb_client)
 
194
{
 
195
  if (rfb_client->onHold)
 
196
    return TRUE;
 
197
 
 
198
  vino_server_update_client (rfb_client);
 
199
 
 
200
  return TRUE;
 
201
}
 
202
 
 
203
static void
 
204
vino_server_set_client_on_hold (VinoServer            *server,
 
205
                                VinoServerClientInfo  *client,
 
206
                                gboolean               on_hold)
 
207
{
 
208
  rfbClientPtr rfb_client = client->rfb_client;
 
209
 
 
210
  dprintf (RFB, "Setting client '%s' on hold: %s\n",
 
211
           rfb_client->host, on_hold ? "(true)" : "(false)");
 
212
 
 
213
  rfb_client->onHold = on_hold;
 
214
 
 
215
  /* We don't process any pending data from an client which is
 
216
   * on hold, so don't let it starve the rest of the mainloop.
 
217
   */
 
218
  g_source_set_priority (g_main_context_find_source_by_id (NULL, client->io_watch),
 
219
                         on_hold ? G_PRIORITY_LOW : G_PRIORITY_DEFAULT);
 
220
 
 
221
  if (!on_hold)
 
222
    {
 
223
      if (!client->update_timeout)
 
224
        client->update_timeout = g_timeout_add (50,
 
225
                                                (GSourceFunc) vino_server_update_client_timeout,
 
226
                                                rfb_client);
 
227
    }
 
228
  else
 
229
    {
 
230
      if (client->update_timeout)
 
231
        g_source_remove (client->update_timeout);
 
232
      client->update_timeout = 0;
 
233
    }
 
234
}
 
235
 
 
236
static inline gboolean
 
237
more_data_pending (int fd)
 
238
{
 
239
  struct pollfd pollfd = { fd, POLLIN|POLLPRI, 0 };
 
240
 
 
241
  return poll (&pollfd, 1, 0) == 1;
 
242
}
 
243
 
 
244
static gboolean
 
245
vino_server_client_data_pending (GIOChannel   *source,
 
246
                                 GIOCondition  condition,
 
247
                                 rfbClientPtr  rfb_client)
 
248
{
 
249
  if (rfb_client->onHold)
 
250
    return TRUE;
 
251
 
 
252
  do {
 
253
    rfbProcessClientMessage (rfb_client);
 
254
  } while (more_data_pending (rfb_client->sock));
 
255
  
 
256
  return vino_server_update_client (rfb_client);
 
257
}
 
258
 
 
259
static enum rfbNewClientAction
 
260
vino_server_handle_new_client (rfbClientPtr rfb_client)
 
261
{
 
262
  VinoServer           *server = VINO_SERVER (rfb_client->screen->screenData);
 
263
  VinoServerClientInfo *client;
 
264
 
 
265
  g_return_val_if_fail (VINO_IS_SERVER (server), RFB_CLIENT_REFUSE);
 
266
 
 
267
  dprintf (RFB, "New client on fd %d\n", rfb_client->sock);
 
268
 
 
269
  if (!server->priv->fb)
 
270
    vino_server_setup_framebuffer (server);
 
271
 
 
272
  client = g_new0 (VinoServerClientInfo, 1);
 
273
 
 
274
  rfb_client->clientData = client;
 
275
 
 
276
  client->rfb_client = rfb_client;
 
277
 
 
278
  client->rfb_client->clientGoneHook = vino_server_handle_client_gone;
 
279
 
 
280
  client->io_channel = g_io_channel_unix_new (rfb_client->sock);
 
281
 
 
282
  client->io_watch = g_io_add_watch (client->io_channel,
 
283
                                     G_IO_IN|G_IO_PRI,
 
284
                                     (GIOFunc) vino_server_client_data_pending,
 
285
                                     rfb_client);
 
286
 
 
287
  server->priv->clients = g_slist_prepend (server->priv->clients, client);
 
288
 
 
289
  vino_server_set_client_on_hold (server, client, server->priv->on_hold);
 
290
 
 
291
  return server->priv->on_hold ? RFB_CLIENT_ON_HOLD : RFB_CLIENT_ACCEPT;
 
292
}
 
293
 
 
294
static void
 
295
vino_server_handle_prompt_response (VinoServer         *server,
 
296
                                    rfbClientPtr        rfb_client,
 
297
                                    VinoPromptResponse  response)
 
298
{
 
299
  g_return_if_fail (VINO_IS_SERVER (server));
 
300
  g_return_if_fail (rfb_client != NULL);
 
301
 
 
302
  switch (response)
 
303
    {
 
304
    case VINO_RESPONSE_ACCEPT:
 
305
      vino_server_set_client_on_hold (server, rfb_client->clientData, FALSE);
 
306
      break;
 
307
    case VINO_RESPONSE_REJECT:
 
308
      rfbCloseClient (rfb_client);
 
309
      rfbClientConnectionGone (rfb_client);
 
310
      break;
 
311
    case VINO_RESPONSE_INVALID:
 
312
      g_assert_not_reached ();
 
313
      break;
 
314
    }
 
315
}
 
316
 
 
317
static enum rfbNewClientAction
 
318
vino_server_handle_authenticated_client (rfbClientPtr rfb_client)
 
319
{
 
320
  VinoServer           *server = VINO_SERVER (rfb_client->screen->screenData);
 
321
  VinoServerClientInfo *client = (VinoServerClientInfo *) rfb_client->clientData;
 
322
 
 
323
  g_return_val_if_fail (VINO_IS_SERVER (server), RFB_CLIENT_REFUSE);
 
324
 
 
325
  if (!server->priv->prompt_enabled)
 
326
    return RFB_CLIENT_ACCEPT;
 
327
 
 
328
  vino_prompt_add_client (server->priv->prompt, rfb_client);
 
329
 
 
330
  vino_server_set_client_on_hold (server, client, TRUE);
 
331
 
 
332
  return RFB_CLIENT_ON_HOLD;
 
333
}
 
334
 
 
335
static gboolean
 
336
vino_server_new_connection_pending (GIOChannel   *source,
 
337
                                    GIOCondition  condition,
 
338
                                    VinoServer   *server)
 
339
{
 
340
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
341
 
 
342
  rfbProcessNewConnection (server->priv->rfb_screen);
 
343
 
 
344
  return TRUE;
 
345
}
 
346
 
 
347
static void
 
348
vino_server_handle_key_event (rfbBool      down,
 
349
                              rfbKeySym    keySym,
 
350
                              rfbClientPtr rfb_client)
 
351
{
 
352
  VinoServer *server = VINO_SERVER (rfb_client->screen->screenData);
 
353
 
 
354
  g_return_if_fail (VINO_IS_SERVER (server));
 
355
 
 
356
  if (server->priv->view_only)
 
357
    return;
 
358
 
 
359
  vino_input_handle_key_event (server->priv->screen, keySym, down);
 
360
}
 
361
 
 
362
static void
 
363
vino_server_handle_pointer_event (int          buttonMask,
 
364
                                  int          x,
 
365
                                  int          y,
 
366
                                  rfbClientPtr rfb_client)
 
367
{
 
368
  VinoServer *server = VINO_SERVER (rfb_client->screen->screenData);
 
369
 
 
370
  g_return_if_fail (VINO_IS_SERVER (server));
 
371
 
 
372
  if (server->priv->view_only)
 
373
    return;
 
374
 
 
375
  vino_input_handle_pointer_event (server->priv->screen, buttonMask, x, y);
 
376
}
 
377
 
 
378
static void
 
379
vino_server_handle_clipboard_event (char         *str,
 
380
                                    int           len,
 
381
                                    rfbClientPtr  rfb_client)
 
382
{
 
383
  VinoServer *server = VINO_SERVER (rfb_client->screen->screenData);
 
384
 
 
385
  g_return_if_fail (VINO_IS_SERVER (server));
 
386
 
 
387
  if (server->priv->view_only)
 
388
    return;
 
389
 
 
390
  vino_input_handle_clipboard_event (server->priv->screen, str, len);
 
391
}
 
392
 
 
393
static gboolean
 
394
vino_server_auth_client_deferred (VinoServerClientInfo *client)
 
395
{
 
396
  VinoServer              *server = VINO_SERVER (client->rfb_client->screen->screenData);
 
397
  enum rfbNewClientAction  result;
 
398
 
 
399
  result = vino_server_auth_client (server,
 
400
                                    client,
 
401
                                    client->auth_response,
 
402
                                    client->auth_resp_len);
 
403
 
 
404
  if (result == RFB_CLIENT_ACCEPT)
 
405
    vino_server_set_client_on_hold (server, client, FALSE);
 
406
 
 
407
  rfbAuthPasswordChecked (client->rfb_client, result);
 
408
 
 
409
  g_free (client->auth_response);
 
410
  client->auth_response = NULL;
 
411
  client->auth_resp_len = 0;
 
412
  client->auth_timeout  = 0;
 
413
 
 
414
  return FALSE;
 
415
}
 
416
 
 
417
static void
 
418
vino_server_defer_client_auth (VinoServer           *server,
 
419
                               VinoServerClientInfo *client,
 
420
                               const char           *response,
 
421
                               int                   length)
 
422
{
 
423
  client->auth_resp_len = length;
 
424
  client->auth_response = g_new (char, length);
 
425
  memcpy (client->auth_response, response, length);
 
426
 
 
427
  vino_server_set_client_on_hold (server, client, TRUE);
 
428
 
 
429
  client->auth_timeout = g_timeout_add (VINO_SERVER_AUTH_DEFER_LEN * 1000,
 
430
                                        (GSourceFunc) vino_server_auth_client_deferred,
 
431
                                        client);
 
432
}
 
433
 
 
434
static enum rfbNewClientAction
 
435
vino_server_auth_client (VinoServer           *server,
 
436
                         VinoServerClientInfo *client,
 
437
                         const char           *response,
 
438
                         int                   length)
 
439
{
 
440
  rfbClientPtr  rfb_client;
 
441
  char         *password;
 
442
 
 
443
  if (!(server->priv->auth_methods & VINO_AUTH_VNC))
 
444
    goto auth_failed;
 
445
 
 
446
  if (!server->priv->vnc_password)
 
447
    goto auth_failed;
 
448
 
 
449
  if (!(password = vino_base64_unencode (server->priv->vnc_password)))
 
450
    {
 
451
      g_warning ("Failed to base64 unencode VNC password\n");
 
452
      goto auth_failed;
 
453
    }
 
454
 
 
455
  rfb_client = client->rfb_client;
 
456
 
 
457
  vncEncryptBytes (client->rfb_client->authChallenge, password);
 
458
 
 
459
  memset (password, 0, strlen (password));
 
460
  g_free (password);
 
461
 
 
462
  if (memcmp (rfb_client->authChallenge, response, length))
 
463
    {
 
464
      memset (rfb_client->authChallenge, 0, CHALLENGESIZE);
 
465
      g_warning ("VNC authentication failure from '%s'\n", rfb_client->host);
 
466
      goto auth_failed;
 
467
    }
 
468
 
 
469
  memset (rfb_client->authChallenge, 0, CHALLENGESIZE);
 
470
 
 
471
  server->priv->last_auth_failed = FALSE;
 
472
 
 
473
  return RFB_CLIENT_ACCEPT;
 
474
 
 
475
 auth_failed:
 
476
  /* Delay the next authentication attempt so as to make
 
477
   * brute force guessing of the password infeasible.
 
478
   */
 
479
  server->priv->last_auth_failed = TRUE;
 
480
  return RFB_CLIENT_REFUSE;
 
481
}
 
482
 
 
483
static enum rfbNewClientAction
 
484
vino_server_check_vnc_password (rfbClientPtr  rfb_client,
 
485
                                const char   *response,
 
486
                                int           length)
 
487
{
 
488
  VinoServer           *server = VINO_SERVER (rfb_client->screen->screenData);
 
489
  VinoServerClientInfo *client = (VinoServerClientInfo *) rfb_client->clientData;
 
490
 
 
491
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
492
 
 
493
  if (!response || length != CHALLENGESIZE)
 
494
    {
 
495
      server->priv->last_auth_failed = TRUE;
 
496
      return RFB_CLIENT_REFUSE;
 
497
    }
 
498
 
 
499
  if (server->priv->last_auth_failed)
 
500
    {
 
501
      g_warning ("Deferring authentication of '%s' for %d seconds\n",
 
502
                 rfb_client->host, VINO_SERVER_AUTH_DEFER_LEN);
 
503
      vino_server_defer_client_auth (server, client, response, length);
 
504
      return RFB_CLIENT_ON_HOLD;
 
505
    }
 
506
 
 
507
  return vino_server_auth_client (server, client, response, length);
 
508
}
 
509
 
 
510
static void
 
511
vino_server_handle_damage_notify (VinoServer *server)
 
512
{
 
513
  GdkRectangle *rects;
 
514
  int           i, n_rects;
 
515
 
 
516
  g_return_if_fail (VINO_IS_SERVER (server));
 
517
  
 
518
  rects = vino_fb_get_damage (server->priv->fb, &n_rects, TRUE);
 
519
 
 
520
  for (i = 0; i < n_rects; i++)
 
521
    rfbMarkRectAsModified (server->priv->rfb_screen,
 
522
                           rects [i].x,
 
523
                           rects [i].y,
 
524
                           rects [i].x + rects [i].width,
 
525
                           rects [i].y + rects [i].height);
 
526
 
 
527
  g_free (rects);
 
528
}
 
529
 
 
530
static void
 
531
vino_server_init_pixel_format (VinoServer       *server,
 
532
                               rfbScreenInfoPtr  rfb_screen)
 
533
 
 
534
{
 
535
  rfbPixelFormat *format = &rfb_screen->rfbServerFormat;
 
536
  gulong          red_mask, green_mask, blue_mask;
 
537
 
 
538
  rfb_screen->bitsPerPixel       = vino_fb_get_bits_per_pixel (server->priv->fb);
 
539
  rfb_screen->depth              = vino_fb_get_depth (server->priv->fb);
 
540
  rfb_screen->paddedWidthInBytes = vino_fb_get_rowstride (server->priv->fb);
 
541
 
 
542
  format->bitsPerPixel = rfb_screen->bitsPerPixel;
 
543
  format->depth        = rfb_screen->depth;
 
544
 
 
545
  vino_fb_get_color_masks (server->priv->fb,
 
546
                           &red_mask, &green_mask, &blue_mask);
 
547
  
 
548
  format->redShift = 0;
 
549
  while (!(red_mask & (1 << format->redShift)))
 
550
    format->redShift++;
 
551
  
 
552
  format->greenShift = 0;
 
553
  while (!(green_mask & (1 << format->greenShift)))
 
554
    format->greenShift++;
 
555
 
 
556
  format->blueShift = 0;
 
557
  while (!(blue_mask & (1 << format->blueShift)))
 
558
    format->blueShift++;
 
559
 
 
560
  format->redMax   = red_mask   >> format->redShift;
 
561
  format->greenMax = green_mask >> format->greenShift;
 
562
  format->blueMax  = blue_mask  >> format->blueShift;
 
563
 
 
564
  dprintf (RFB,
 
565
           "Initialized pixel format: %dbpp, depth = %d\n"
 
566
           "\tred:   mask = %.8lx, max = %d, shift = %d\n"
 
567
           "\tgreen: mask = %.8lx, max = %d, shift = %d\n"
 
568
           "\tblue:  mask = %.8lx, max = %d, shift = %d\n",
 
569
           format->bitsPerPixel, format->depth,
 
570
           red_mask,   format->redMax,   format->redShift,
 
571
           green_mask, format->greenMax, format->greenShift,
 
572
           blue_mask,  format->blueMax,  format->blueShift);
 
573
}
 
574
 
 
575
static void
 
576
vino_server_screen_size_changed (VinoServer *server)
 
577
{
 
578
  g_return_if_fail (VINO_IS_SERVER (server));
 
579
 
 
580
  rfbNewFramebuffer (server->priv->rfb_screen,
 
581
                     vino_fb_get_pixels (server->priv->fb),
 
582
                     gdk_screen_get_width (server->priv->screen),
 
583
                     gdk_screen_get_height (server->priv->screen),
 
584
                     -1, -1, -1);
 
585
 
 
586
  vino_server_init_pixel_format (server, server->priv->rfb_screen);
 
587
}
 
588
 
 
589
static void
 
590
vino_server_setup_framebuffer (VinoServer *server)
 
591
{
 
592
  g_return_if_fail (server->priv->fb == NULL);
 
593
  g_return_if_fail (server->priv->cursor_data == NULL);
 
594
 
 
595
  server->priv->fb = vino_fb_new (server->priv->screen);
 
596
 
 
597
  g_signal_connect_swapped (server->priv->fb, "size-changed",
 
598
                            G_CALLBACK (vino_server_screen_size_changed),
 
599
                            server);
 
600
  g_signal_connect_swapped (server->priv->fb, "damage-notify",
 
601
                            G_CALLBACK (vino_server_handle_damage_notify),
 
602
                            server);
 
603
 
 
604
  server->priv->rfb_screen->frameBuffer = vino_fb_get_pixels (server->priv->fb);
 
605
  
 
606
  vino_server_init_pixel_format (server, server->priv->rfb_screen);
 
607
 
 
608
  server->priv->cursor_data = vino_cursor_init (server->priv->screen);
 
609
}
 
610
 
 
611
static void
 
612
vino_server_release_framebuffer (VinoServer *server)
 
613
{
 
614
  g_return_if_fail (server->priv->fb != NULL);
 
615
  g_return_if_fail (server->priv->cursor_data != NULL);
 
616
 
 
617
  if (server->priv->cursor_data)
 
618
    vino_cursor_finalize (server->priv->cursor_data);
 
619
  server->priv->cursor_data = NULL;
 
620
 
 
621
  server->priv->rfb_screen->frameBuffer = NULL;
 
622
 
 
623
  g_object_unref (server->priv->fb);
 
624
  server->priv->fb = NULL;
 
625
}
 
626
 
 
627
static void
 
628
vino_server_init_from_screen (VinoServer *server,
 
629
                              GdkScreen  *screen)
 
630
{
 
631
  rfbScreenInfoPtr rfb_screen;
 
632
 
 
633
  g_return_if_fail (server->priv->screen == NULL);
 
634
  g_return_if_fail (screen != NULL);
 
635
  
 
636
  server->priv->screen = screen;
 
637
 
 
638
  server->priv->prompt = vino_prompt_new (screen);
 
639
 
 
640
  g_signal_connect_swapped (server->priv->prompt, "response",
 
641
                            G_CALLBACK (vino_server_handle_prompt_response),
 
642
                            server);
 
643
 
 
644
  /* libvncserver NOTE:
 
645
   *   we don't pass in argc or argv
 
646
   *   samplesPerPixel is totally unused (3 below)
 
647
   *   bitsPerSample and bytesPerPixel get set in
 
648
   *   set_pixel_format()
 
649
   */
 
650
  server->priv->rfb_screen = rfb_screen = 
 
651
    rfbGetScreen (NULL, NULL,
 
652
                  gdk_screen_get_width  (screen),
 
653
                  gdk_screen_get_height (screen),
 
654
                  -1, -1, -1);
 
655
 
 
656
  /* libvncserver NOTE:
 
657
   *   DeferUpdateTime is the number of milliseconds to wait
 
658
   *   before actually responding to a frame buffer update
 
659
   *   request.
 
660
   *   setting autoPort enables autoProbing a port between
 
661
   *   5900-6000
 
662
   */
 
663
  rfb_screen->rfbDeferUpdateTime = 0;
 
664
  rfb_screen->autoPort           = TRUE;
 
665
  rfb_screen->rfbAlwaysShared    = TRUE;
 
666
 
 
667
  rfbInitServer (rfb_screen);
 
668
  
 
669
  /* libvncserver NOTE:
 
670
   *   there's no user_data for newClientHook. You have
 
671
   *   to use screenData
 
672
   */
 
673
  rfb_screen->screenData              = server;
 
674
  rfb_screen->newClientHook           = vino_server_handle_new_client;
 
675
  rfb_screen->authenticatedClientHook = vino_server_handle_authenticated_client;
 
676
 
 
677
  /* libvncserver NOTE:
 
678
   *   all these hooks should take an rfbClientPtr as the
 
679
   *   first argument rather than the last.
 
680
   */
 
681
  rfb_screen->kbdAddEvent = vino_server_handle_key_event;
 
682
  rfb_screen->ptrAddEvent = vino_server_handle_pointer_event;
 
683
  rfb_screen->setXCutText = vino_server_handle_clipboard_event;
 
684
 
 
685
  rfb_screen->passwordCheck = vino_server_check_vnc_password;
 
686
 
 
687
  dprintf (RFB, "Creating watch for listening socket %d - port %d\n",
 
688
           rfb_screen->rfbListenSock, rfb_screen->rfbPort);
 
689
 
 
690
  server->priv->io_channel = g_io_channel_unix_new (rfb_screen->rfbListenSock);
 
691
  server->priv->io_watch =
 
692
    g_io_add_watch (server->priv->io_channel,
 
693
                    G_IO_IN|G_IO_PRI,
 
694
                    (GIOFunc) vino_server_new_connection_pending,
 
695
                    server);
 
696
 
 
697
#ifdef VINO_ENABLE_HTTP_SERVER
 
698
  server->priv->http = vino_http_get (rfb_screen->rfbPort);
 
699
#endif
 
700
}
 
701
 
 
702
static void
 
703
vino_server_finalize (GObject *object)
 
704
{
 
705
  VinoServer *server = VINO_SERVER (object);
 
706
 
 
707
#ifdef VINO_ENABLE_HTTP_SERVER
 
708
  if (server->priv->http)
 
709
    {
 
710
      vino_http_remove_rfb_port (server->priv->http,
 
711
                                 server->priv->rfb_screen->rfbPort);
 
712
      g_object_unref (server->priv->http);
 
713
    }
 
714
  server->priv->http = NULL;
 
715
#endif /* VINO_ENABLE_HTTP_SERVER */
 
716
 
 
717
  if (server->priv->io_watch)
 
718
    g_source_remove (server->priv->io_watch);
 
719
  server->priv->io_watch = 0;
 
720
 
 
721
  if (server->priv->io_channel)
 
722
    g_io_channel_unref (server->priv->io_channel);
 
723
  server->priv->io_channel = NULL;
 
724
  
 
725
  if (server->priv->rfb_screen)
 
726
    rfbScreenCleanup (server->priv->rfb_screen);
 
727
  server->priv->rfb_screen = NULL;
 
728
 
 
729
  /* ClientGoneHook should get invoked for each
 
730
   * client from rfbScreenCleanup()
 
731
   */
 
732
  g_assert (server->priv->clients == NULL);
 
733
 
 
734
  if (server->priv->vnc_password)
 
735
    g_free (server->priv->vnc_password);
 
736
  server->priv->vnc_password = NULL;
 
737
 
 
738
  if (server->priv->prompt)
 
739
    g_object_unref (server->priv->prompt);
 
740
  server->priv->prompt = NULL;
 
741
 
 
742
  if (server->priv->cursor_data)
 
743
    vino_cursor_finalize (server->priv->cursor_data);
 
744
  server->priv->cursor_data = NULL;
 
745
 
 
746
  if (server->priv->fb)
 
747
    g_object_unref (server->priv->fb);
 
748
  server->priv->fb = NULL;
 
749
  
 
750
  g_free (server->priv);
 
751
  server->priv = NULL;
 
752
 
 
753
  if (G_OBJECT_CLASS (parent_class)->finalize)
 
754
    G_OBJECT_CLASS (parent_class)->finalize (object);
 
755
}
 
756
 
 
757
static void
 
758
vino_server_set_property (GObject      *object,
 
759
                          guint         prop_id,
 
760
                          const GValue *value,
 
761
                          GParamSpec   *pspec)
 
762
{
 
763
  VinoServer *server = VINO_SERVER (object);
 
764
 
 
765
  switch (prop_id)
 
766
    {
 
767
    case PROP_SCREEN:
 
768
      vino_server_init_from_screen (server, g_value_get_object (value));
 
769
      break;
 
770
    case PROP_ON_HOLD:
 
771
      vino_server_set_on_hold (server, g_value_get_boolean (value));
 
772
      break;
 
773
    case PROP_PROMPT_ENABLED:
 
774
      vino_server_set_prompt_enabled (server, g_value_get_boolean (value));
 
775
      break;
 
776
    case PROP_VIEW_ONLY:
 
777
      vino_server_set_view_only (server, g_value_get_boolean (value));
 
778
      break;
 
779
    case PROP_REQUIRE_ENCRYPTION:
 
780
      vino_server_set_require_encryption (server, g_value_get_boolean (value));
 
781
      break;
 
782
    case PROP_AUTH_METHODS:
 
783
      vino_server_set_auth_methods (server, g_value_get_flags (value));
 
784
      break;
 
785
    case PROP_VNC_PASSWORD:
 
786
      vino_server_set_vnc_password (server, g_value_get_string (value));
 
787
      break;
 
788
    default:
 
789
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
790
      break;
 
791
    }
 
792
}
 
793
 
 
794
static void
 
795
vino_server_get_property (GObject    *object,
 
796
                          guint       prop_id,
 
797
                          GValue     *value,
 
798
                          GParamSpec *pspec)
 
799
{
 
800
  VinoServer *server = VINO_SERVER (object);
 
801
 
 
802
  switch (prop_id)
 
803
    {
 
804
    case PROP_SCREEN:
 
805
      g_value_set_object (value, server->priv->screen);
 
806
      break;
 
807
    case PROP_ON_HOLD:
 
808
      g_value_set_boolean (value, server->priv->on_hold);
 
809
      break;
 
810
    case PROP_PROMPT_ENABLED:
 
811
      g_value_set_boolean (value, server->priv->prompt_enabled);
 
812
      break;
 
813
    case PROP_VIEW_ONLY:
 
814
      g_value_set_boolean (value, server->priv->view_only);
 
815
      break;
 
816
    case PROP_REQUIRE_ENCRYPTION:
 
817
      g_value_set_boolean (value, server->priv->view_only);
 
818
      break;
 
819
    case PROP_AUTH_METHODS:
 
820
      g_value_set_flags (value, server->priv->auth_methods);
 
821
      break;
 
822
    case PROP_VNC_PASSWORD:
 
823
      g_value_set_string (value, server->priv->vnc_password);
 
824
      break;
 
825
    default:
 
826
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
827
      break;
 
828
    }
 
829
}
 
830
 
 
831
static void
 
832
vino_server_instance_init (VinoServer *server)
 
833
{
 
834
  server->priv = g_new0 (VinoServerPrivate, 1);
 
835
}
 
836
 
 
837
static void
 
838
vino_server_class_init (VinoServerClass *klass)
 
839
{
 
840
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
841
  
 
842
  parent_class = g_type_class_peek_parent (klass);
 
843
  
 
844
  gobject_class->finalize     = vino_server_finalize;
 
845
  gobject_class->set_property = vino_server_set_property;
 
846
  gobject_class->get_property = vino_server_get_property;
 
847
 
 
848
  g_object_class_install_property (gobject_class,
 
849
                                   PROP_SCREEN,
 
850
                                   g_param_spec_object ("screen",
 
851
                                                        _("Screen"),
 
852
                                                        _("The screen for which to create a VNC server"),
 
853
                                                        GDK_TYPE_SCREEN,
 
854
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
855
  
 
856
  g_object_class_install_property (gobject_class,
 
857
                                   PROP_ON_HOLD,
 
858
                                   g_param_spec_boolean ("on-hold",
 
859
                                                         _("On Hold"),
 
860
                                                         _("Place all clients on hold"),
 
861
                                                         TRUE,
 
862
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
863
 
 
864
  g_object_class_install_property (gobject_class,
 
865
                                   PROP_PROMPT_ENABLED,
 
866
                                   g_param_spec_boolean ("prompt-enabled",
 
867
                                                         _("Prompt enabled"),
 
868
                                                         _("Prompt the user about connection attempts"),
 
869
                                                         TRUE,
 
870
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
871
 
 
872
  g_object_class_install_property (gobject_class,
 
873
                                   PROP_VIEW_ONLY,
 
874
                                   g_param_spec_boolean ("view-only",
 
875
                                                         _("View Only"),
 
876
                                                         _("Disallow keyboard/pointer input from clients"),
 
877
                                                         FALSE,
 
878
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
879
 
 
880
  g_object_class_install_property (gobject_class,
 
881
                                   PROP_REQUIRE_ENCRYPTION,
 
882
                                   g_param_spec_boolean ("require-encryption",
 
883
                                                         _("Require Encryption"),
 
884
                                                         _("Require clients to use encryption"),
 
885
                                                         TRUE,
 
886
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
887
 
 
888
  g_object_class_install_property (gobject_class,
 
889
                                   PROP_AUTH_METHODS,
 
890
                                   g_param_spec_flags ("auth-methods",
 
891
                                                       _("Authentication methods"),
 
892
                                                       _("The authentication methods this server should allow"),
 
893
                                                       VINO_TYPE_AUTH_METHOD,
 
894
                                                       VINO_AUTH_NONE,
 
895
                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
896
  
 
897
  g_object_class_install_property (gobject_class,
 
898
                                   PROP_VNC_PASSWORD,
 
899
                                   g_param_spec_string ("vnc-password",
 
900
                                                        _("VNC Password"),
 
901
                                                        _("The password (base64 encoded) used to authenticate types using the VncAuth method"),
 
902
                                                        NULL,
 
903
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
904
}
 
905
 
 
906
GType
 
907
vino_server_get_type (void)
 
908
{
 
909
  static GType object_type = 0;
 
910
 
 
911
  if (!object_type)
 
912
    {
 
913
      static const GTypeInfo object_info =
 
914
        {
 
915
          sizeof (VinoServerClass),
 
916
          (GBaseInitFunc) NULL,
 
917
          (GBaseFinalizeFunc) NULL,
 
918
          (GClassInitFunc) vino_server_class_init,
 
919
          NULL,           /* class_finalize */
 
920
          NULL,           /* class_data */
 
921
          sizeof (VinoServer),
 
922
          0,              /* n_preallocs */
 
923
          (GInstanceInitFunc) vino_server_instance_init,
 
924
        };
 
925
      
 
926
      object_type = g_type_register_static (G_TYPE_OBJECT,
 
927
                                            "VinoServer",
 
928
                                            &object_info, 0);
 
929
    }
 
930
 
 
931
  return object_type;
 
932
}
 
933
 
 
934
 
 
935
VinoServer *
 
936
vino_server_new (GdkScreen *screen,
 
937
                 gboolean   view_only)
 
938
{
 
939
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
940
 
 
941
  return g_object_new (VINO_TYPE_SERVER,
 
942
                       "screen", screen,
 
943
                       "view-only", view_only,
 
944
                       NULL);
 
945
}
 
946
 
 
947
GdkScreen *
 
948
vino_server_get_screen (VinoServer *server)
 
949
{
 
950
  g_return_val_if_fail (VINO_IS_SERVER (server), NULL);
 
951
 
 
952
  return server->priv->screen;
 
953
}
 
954
 
 
955
gboolean
 
956
vino_server_get_view_only (VinoServer *server)
 
957
{
 
958
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
959
 
 
960
  return server->priv->view_only;
 
961
}
 
962
 
 
963
void
 
964
vino_server_set_view_only (VinoServer *server,
 
965
                           gboolean    view_only)
 
966
{
 
967
  g_return_if_fail (VINO_IS_SERVER (server));
 
968
 
 
969
  view_only = view_only != FALSE;
 
970
 
 
971
  if (server->priv->view_only != view_only)
 
972
    {
 
973
      server->priv->view_only = view_only;
 
974
 
 
975
      g_object_notify (G_OBJECT (server), "view-only");
 
976
    }
 
977
}
 
978
 
 
979
gboolean
 
980
vino_server_get_on_hold (VinoServer *server)
 
981
{
 
982
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
983
 
 
984
  return server->priv->on_hold;
 
985
}
 
986
 
 
987
void
 
988
vino_server_set_on_hold (VinoServer *server,
 
989
                         gboolean    on_hold)
 
990
{
 
991
  g_return_if_fail (VINO_IS_SERVER (server));
 
992
 
 
993
  on_hold = on_hold != FALSE;
 
994
 
 
995
  if (server->priv->on_hold != on_hold)
 
996
    {
 
997
      GSList *l;
 
998
 
 
999
      server->priv->on_hold = on_hold;
 
1000
 
 
1001
      for (l = server->priv->clients; l; l = l->next)
 
1002
        {
 
1003
          VinoServerClientInfo *client = l->data;
 
1004
 
 
1005
          /* If a client is on hold before we have initialized,
 
1006
           * we want to leave it on hold until the deferred
 
1007
           * authentication or the prompt has completed.
 
1008
           *
 
1009
           * FIXME: this isn't correct, though - e.g if we're
 
1010
           * in the middle of prompting and you toggle the
 
1011
           * server on and off then the client gets through.
 
1012
           */
 
1013
          if (client->rfb_client->state == RFB_NORMAL)
 
1014
            vino_server_set_client_on_hold (server, client, on_hold);
 
1015
        }
 
1016
 
 
1017
      g_object_notify (G_OBJECT (server), "on-hold");
 
1018
    }
 
1019
}
 
1020
 
 
1021
gboolean
 
1022
vino_server_get_prompt_enabled (VinoServer *server)
 
1023
{
 
1024
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
1025
 
 
1026
  return server->priv->prompt_enabled;
 
1027
}
 
1028
 
 
1029
void
 
1030
vino_server_set_prompt_enabled (VinoServer *server,
 
1031
                                gboolean    prompt_enabled)
 
1032
{
 
1033
  g_return_if_fail (VINO_IS_SERVER (server));
 
1034
 
 
1035
  prompt_enabled = prompt_enabled != FALSE;
 
1036
 
 
1037
  if (server->priv->prompt_enabled != prompt_enabled)
 
1038
    {
 
1039
      server->priv->prompt_enabled = prompt_enabled;
 
1040
 
 
1041
      g_object_notify (G_OBJECT (server), "prompt-enabled");
 
1042
    }
 
1043
}
 
1044
 
 
1045
static void
 
1046
vino_server_update_security_types (VinoServer *server)
 
1047
{
 
1048
  rfbClearSecurityTypes (server->priv->rfb_screen);
 
1049
  rfbClearAuthTypes (server->priv->rfb_screen);
 
1050
 
 
1051
#ifdef HAVE_GNUTLS
 
1052
  rfbAddSecurityType (server->priv->rfb_screen, rfbTLS);
 
1053
#endif
 
1054
      
 
1055
  if (server->priv->auth_methods & VINO_AUTH_VNC)
 
1056
    {
 
1057
      rfbAddAuthType (server->priv->rfb_screen, rfbVncAuth);
 
1058
#ifdef HAVE_GNUTLS
 
1059
      if (!server->priv->require_encryption)
 
1060
#endif
 
1061
        rfbAddSecurityType (server->priv->rfb_screen, rfbVncAuth);
 
1062
    }
 
1063
      
 
1064
  if (server->priv->auth_methods & VINO_AUTH_NONE)
 
1065
    {
 
1066
      rfbAddAuthType (server->priv->rfb_screen, rfbNoAuth);
 
1067
#ifdef HAVE_GNUTLS
 
1068
      if (!server->priv->require_encryption)
 
1069
#endif
 
1070
        rfbAddSecurityType (server->priv->rfb_screen, rfbNoAuth);
 
1071
    }
 
1072
}
 
1073
void
 
1074
vino_server_set_require_encryption (VinoServer *server,
 
1075
                                    gboolean    require_encryption)
 
1076
{
 
1077
  g_return_if_fail (VINO_IS_SERVER (server));
 
1078
  
 
1079
  require_encryption = require_encryption != FALSE;
 
1080
 
 
1081
  if (server->priv->require_encryption != require_encryption)
 
1082
    {
 
1083
      server->priv->require_encryption = require_encryption;
 
1084
 
 
1085
      vino_server_update_security_types (server);
 
1086
 
 
1087
      g_object_notify (G_OBJECT (server), "require-encryption");
 
1088
    }
 
1089
}
 
1090
 
 
1091
gboolean
 
1092
vino_server_get_require_encryption (VinoServer *server)
 
1093
{
 
1094
  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
1095
 
 
1096
  return server->priv->require_encryption;
 
1097
}
 
1098
 
 
1099
void
 
1100
vino_server_set_auth_methods (VinoServer     *server,
 
1101
                              VinoAuthMethod  auth_methods)
 
1102
{
 
1103
  g_return_if_fail (VINO_IS_SERVER (server));
 
1104
  g_return_if_fail (auth_methods != VINO_AUTH_INVALID);
 
1105
 
 
1106
  if (server->priv->auth_methods != auth_methods)
 
1107
    {
 
1108
      server->priv->auth_methods = auth_methods;
 
1109
 
 
1110
      vino_server_update_security_types (server);
 
1111
 
 
1112
      g_object_notify (G_OBJECT (server), "auth-methods");
 
1113
    }
 
1114
}
 
1115
 
 
1116
VinoAuthMethod
 
1117
vino_server_get_auth_methods (VinoServer *server)
 
1118
{
 
1119
  g_return_val_if_fail (VINO_IS_SERVER (server), VINO_AUTH_INVALID);
 
1120
 
 
1121
  return server->priv->auth_methods;
 
1122
}
 
1123
 
 
1124
void
 
1125
vino_server_set_vnc_password (VinoServer *server,
 
1126
                              const char *vnc_password)
 
1127
{
 
1128
  g_return_if_fail (VINO_IS_SERVER (server));
 
1129
 
 
1130
  if (server->priv->vnc_password)
 
1131
    g_free (server->priv->vnc_password);
 
1132
 
 
1133
  server->priv->vnc_password = g_strdup (vnc_password);
 
1134
 
 
1135
  g_object_notify (G_OBJECT (server), "vnc-password");
 
1136
}
 
1137
 
 
1138
G_CONST_RETURN char *
 
1139
vino_server_get_vnc_password (VinoServer *server)
 
1140
{
 
1141
  g_return_val_if_fail (VINO_IS_SERVER (server), NULL);
 
1142
 
 
1143
  return server->priv->vnc_password;
 
1144
}