x11vnc options -allow, -localhost, -nodragging, -input_skip

minimize memory usage under -nofb
pull/1/head
runge 21 years ago
parent 7cb3958fd9
commit 11e3f6a6b0

@ -1,3 +1,7 @@
2004-01-09 Karl Runge <runge@karlrunge.com>
* x11vnc options -allow, -localhost, -nodragging, -input_skip
* minimize memory usage under -nofb
2003-12-08 Karl Runge <runge@karlrunge.com>
* add check for XKEYBOARD extension in configure.ac
* support XBell events (disable: "-nobell"), "-nofb" in x11vnc

@ -1,3 +1,11 @@
2004-01-09 Karl Runge <runge@karlrunge.com>
* options -allow / -localhost for simple IP based access screening
* option -nodragging to skip all screen updates during mouse drags
(thanks to Michal Sabala)
* option -input_skip to allow users to tune watch_loop dropthru rate
* try to avoid wasting RAM for framebuffer under -nofb
* cleanup wrt bpp vs. depth
2003-12-08 Karl Runge <runge@karlrunge.com>
* add Xbell support using XKEYBOARD extension (disable: -nobell)
* add "-nofb" to disable framebuffer, i.e. mouse + keyboard only (!)

@ -78,8 +78,8 @@
* their colors messed up. When using 8bpp indexed color, the colormap
* is attempted to be followed, but may become out of date. Use the
* -flashcmap option to have colormap flashing as the pointer moves
* windows with private colormaps (slow). Displays with mixed 8bpp and
* 24bpp visuals will incorrect display the non-default one.
* windows with private colormaps (slow). Displays with mixed depth 8 and
* 24 visuals will incorrect display the non-default one.
*
* Feature -id <windowid> can be picky: it can crash for things like the
* window not sufficiently mapped into server memory, use of -mouse, etc.
@ -117,7 +117,7 @@ Display *dpy = 0;
Visual *visual;
Window window, rootwin;
int scr;
int bpp;
int bpp, depth;
int button_mask = 0;
int dpy_x, dpy_y;
int off_x, off_y;
@ -168,6 +168,7 @@ hint_t *hint_list;
/* various command line options */
int shared = 0; /* share vnc display. */
char *allow_list = NULL; /* for -allow and -localhost */
int view_only = 0; /* clients can only watch. */
int inetd = 0; /* spawned from inetd(1) */
int connect_once = 1; /* disconnect after first connection session. */
@ -180,7 +181,10 @@ int nofb = 0; /* do not send any fb updates */
int local_cursor = 1; /* whether the viewer draws a local cursor */
int show_mouse = 0; /* display a cursor for the real mouse */
int show_root_cursor = 0; /* show X when on root background */
int watch_bell = 1;
int show_dragging = 1; /* process mouse movement events */
int delay_refresh = 0; /* when buttons are pressed, delay refreshes */
int ui_dropthru = 10; /* see watchloop. negative means ignore input */
int watch_bell = 1; /* watch for the bell using XKEYBOARD */
int using_shm = 1; /* whether mit-shm is used */
int flip_byte_order = 0; /* sometimes needed when using_shm = 0 */
@ -335,14 +339,51 @@ void client_gone(rfbClientPtr client) {
}
}
int check_access(char *addr) {
int allowed = 0;
char *p, *list;
if (allow_list == NULL || *allow_list == '\0') {
return 1;
}
if (addr == NULL || *addr == '\0') {
rfbLog("check_access: denying empty host IP address string.\n");
return 0;
}
list = strdup(allow_list);
p = strtok(list, ",");
while (p) {
char *q = strstr(addr, p);
if (q == addr) {
rfbLog("check_access: client %s matches pattern %s\n",
addr, p);
allowed = 1;
} else if(!strcmp(p,"localhost") && !strcmp(addr,"127.0.0.1")) {
/* also do host lookup someday... */
allowed = 1;
}
p = strtok(NULL, ",");
}
free(list);
return allowed;
}
enum rfbNewClientAction new_client(rfbClientPtr client) {
static accepted_client = 0;
last_event = last_input = time(0);
if (! check_access(client->host)) {
rfbLog("denying client: %s does not match %s\n", client->host,
allow_list ? allow_list : "(null)" );
return(RFB_CLIENT_REFUSE);
}
if (connect_once) {
if (screen->rfbDontDisconnect && screen->rfbNeverShared) {
if (! shared && accepted_client) {
fprintf(stderr, "denying additional client:"
" %s\n", client->host);
rfbLog("denying additional client: %s\n",
client->host);
return(RFB_CLIENT_REFUSE);
}
}
@ -546,6 +587,17 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
return;
}
got_user_input++;
/* if any button is pressed, then do not refresh the screen */
if (! show_dragging) {
if (mask) {
delay_refresh = 1;
} else {
delay_refresh = 0;
}
}
X_LOCK;
XTestFakeMotionEvent(dpy, scr, x + off_x, y + off_y, CurrentTime);
@ -554,7 +606,6 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
cursor_y = y;
last_event = last_input = time(0);
got_user_input++;
for (i=0; i < 5; i++) {
if ( (button_mask & (1<<i)) != (mask & (1<<i)) ) {
@ -580,7 +631,7 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
int xkb_base_event_type;
void initialize_bell_watch() {
void initialize_watch_bell() {
int ir, reason;
if (! XkbSelectEvents(dpy, XkbUseCoreKbd, XkbBellNotifyMask,
XkbBellNotifyMask) ) {
@ -1113,6 +1164,23 @@ void set_colormap(void) {
first = 0;
}
/*
* Presumably under -nofb the clients will never request the framebuffer.
* But we have gotten such a request... so let's just give them the current
* view on the display. n.b. x2vnc requests a 1x1 pixel for some workaround.
*/
void nofb_hook(rfbClientPtr cl) {
static int loaded_fb = 0;
XImage *fb;
if (loaded_fb) {
return;
}
rfbLog("framebuffer requested in -nofb mode by client %s\n", cl->host);
fb = XGetImage(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap);
screen->frameBuffer = fb->data;
loaded_fb = 1;
}
/*
* initialize the rfb framebuffer/screen
*/
@ -1174,14 +1242,19 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
= fb->blue_mask >> screen->rfbServerFormat.blueShift;
}
screen->frameBuffer = fb->data;
if (nofb) {
screen->frameBuffer = NULL;
screen->displayHook = nofb_hook;
} else {
screen->frameBuffer = fb->data;
}
if (inetd) {
int fd = dup(0);
if (fd < 3) {
rfbErr("dup(0) = %d failed.\n", fd);
perror("dup");
exit(1);
clean_up_exit(1);
}
fclose(stdin);
fclose(stdout);
@ -1222,6 +1295,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
bytes_per_line = screen->paddedWidthInBytes;
bpp = screen->rfbServerFormat.bitsPerPixel;
depth = screen->rfbServerFormat.depth;
}
/*
@ -1275,11 +1349,15 @@ void shm_create(XShmSegmentInfo *shm, XImage **ximg_ptr, int w, int h,
XImage *xim;
if (nofb) {
return;
}
X_LOCK;
if (! using_shm) {
/* we only need the XImage created */
xim = XCreateImage(dpy, visual, bpp, ZPixmap, 0, NULL, w, h,
xim = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL, w, h,
BitmapPad(dpy), 0);
X_UNLOCK;
@ -1316,7 +1394,7 @@ void shm_create(XShmSegmentInfo *shm, XImage **ximg_ptr, int w, int h,
return;
}
xim = XShmCreateImage(dpy, visual, bpp, ZPixmap, NULL, shm, w, h);
xim = XShmCreateImage(dpy, visual, depth, ZPixmap, NULL, shm, w, h);
if (xim == NULL) {
rfbErr("XShmCreateImage(%s) failed.\n", name);
@ -1362,7 +1440,7 @@ void shm_delete(XShmSegmentInfo *shm) {
}
void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
if (! using_shm) {
if (! using_shm || nofb) {
return;
}
X_LOCK;
@ -1554,6 +1632,7 @@ void tile_updates() {
}
}
/*
* copy_tile() is called on a tile with a known change (from a scanline
* diff) or a suspected change (from our various heuristics).
@ -2295,8 +2374,9 @@ void watch_loop(void) {
if (! use_threads) {
rfbProcessEvents(screen, -1);
if (got_user_input && cnt % 10 != 0) {
/* every 10-th drops thru to code below... */
if ((got_user_input || ui_dropthru < 0) &&
cnt % ui_dropthru != 0) {
/* every n-th drops thru to code below... */
cnt++;
XFlush(dpy);
continue;
@ -2311,20 +2391,42 @@ void watch_loop(void) {
usleep(200 * 1000);
continue;
}
if (nofb) {
continue;
}
rfbUndrawCursor(screen);
scan_for_updates();
if (watch_bell) {
/* n.b. assumes -nofb folks do not want bell... */
watch_bell_event();
}
usleep(waitms * 1000);
/*
* delay_refresh amounts to delaying rfb screen refreshes.
* During that time, XQueryPointer needs to be called for
* the events to take place on the x server.
*/
if (delay_refresh) {
Window root_w, child_w;
rfbBool ret;
int root_x, root_y, win_x, win_y, which = 0;
unsigned int mask;
X_LOCK;
if (0) {
XFlush(dpy);
} else {
ret = XQueryPointer(dpy, rootwin, &root_w,
&child_w, &root_x, &root_y, &win_x, &win_y,
&mask);
}
X_UNLOCK;
} else {
rfbUndrawCursor(screen);
scan_for_updates();
}
usleep(waitms * 1000);
cnt++;
}
}
@ -2367,6 +2469,11 @@ void print_help() {
"-shared VNC display is shared (default %s).\n"
"-forever Keep listening for more connections rather than exiting\n"
" as soon as the first client(s) disconnect. Same as -many\n"
"-allow addr1[,addr2..] Only allow client connections from IP addresses matching\n"
" the comma separated list of numerical addresses. Can be\n"
" a prefix, e.g. \"192.168.100.\" to match a simple subnet,\n"
" for more control build libvncserver with libwrap support.\n"
"-localhost Same as -allow 127.0.0.1\n"
"-inetd Launched by inetd(1): stdio instead of listening socket.\n"
"-noshm Do not use the MIT-SHM extension for the polling.\n"
" remote displays can be polled this way: be careful\n"
@ -2392,6 +2499,15 @@ void print_help() {
"-mouse Draw a 2nd cursor at the current X pointer position.\n"
"-mouseX As -mouse, but also draw an X on root background.\n"
"-X Shorthand for -mouseX -nocursor.\n"
"-nodragging Do not update the display during mouse dragging events.\n"
" Greatly improves response on slow links, but you lose\n"
" all visual feedback for drags and some menu traversals.\n"
"-input_skip n Experimental option difficult to explain! Only active in\n"
" non-threaded mode. See watch_loop() function for info.\n"
" Loop is: rfbProcessEvents, scan display, sleep. If\n"
" there is mouse or keyboard input the scan is skipped\n"
" except every n-th time thru the loop. Default n is 10,\n"
" n<0 means skip even with no user input. Need to improve!\n"
"\n"
"-defer time Time in ms to wait for updates before sending to\n"
" client [rfbDeferUpdateTime] (default %d).\n"
@ -2507,6 +2623,10 @@ int main(int argc, char** argv) {
view_only = 1;
} else if (!strcmp(argv[i], "-shared")) {
shared = 1;
} else if (!strcmp(argv[i], "-allow")) {
allow_list = argv[++i];
} else if (!strcmp(argv[i], "-localhost")) {
allow_list = "127.0.0.1";
} else if (!strcmp(argv[i], "-many")
|| !strcmp(argv[i], "-forever")) {
connect_once = 0;
@ -2531,6 +2651,11 @@ int main(int argc, char** argv) {
} else if (!strcmp(argv[i], "-mouseX")) {
show_mouse = 1;
show_root_cursor = 1;
} else if (!strcmp(argv[i], "-nodragging")) {
show_dragging = 0;
} else if (!strcmp(argv[i], "-input_skip")) {
ui_dropthru = atoi(argv[++i]);
if (! ui_dropthru) ui_dropthru = 1;
} else if (!strcmp(argv[i], "-X")) {
show_mouse = 1;
show_root_cursor = 1;
@ -2602,6 +2727,8 @@ int main(int argc, char** argv) {
if (! quiet) {
fprintf(stderr, "viewonly: %d\n", view_only);
fprintf(stderr, "shared: %d\n", shared);
fprintf(stderr, "allow: %s\n", allow_list ? allow_list
: "null");
fprintf(stderr, "inetd: %d\n", inetd);
fprintf(stderr, "conn_once: %d\n", connect_once);
fprintf(stderr, "flashcmap: %d\n", flash_cmap);
@ -2613,6 +2740,8 @@ int main(int argc, char** argv) {
fprintf(stderr, "mod_tweak: %d\n", use_modifier_tweak);
fprintf(stderr, "loc_curs: %d\n", local_cursor);
fprintf(stderr, "mouse: %d\n", show_mouse);
fprintf(stderr, "dragging: %d\n", show_dragging);
fprintf(stderr, "inputskip: %d\n", ui_dropthru);
fprintf(stderr, "root_curs: %d\n", show_root_cursor);
fprintf(stderr, "defer: %d\n", defer_update);
fprintf(stderr, "waitms: %d\n", waitms);
@ -2650,7 +2779,7 @@ int main(int argc, char** argv) {
fprintf(stderr, "Display does not support XTest extension.\n");
exit(1);
}
if (! XShmQueryExtension(dpy)) {
if (! nofb && ! XShmQueryExtension(dpy)) {
if (! using_shm) {
fprintf(stderr, "warning: display does not support "
"XShm.\n");
@ -2666,7 +2795,7 @@ int main(int argc, char** argv) {
fprintf(stderr, "warning: disabling bell.\n");
watch_bell = 0;
} else {
initialize_bell_watch();
initialize_watch_bell();
}
}
#endif
@ -2711,11 +2840,26 @@ int main(int argc, char** argv) {
set_offset();
}
fb = XGetImage(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap);
if (! quiet) fprintf(stderr, "Read initial data from display into framebuffer.\n");
if (nofb) {
/*
* This does not malloc the framebuffer, so can save a few
* MB of memory in nofb mode.
*/
fb = XCreateImage(dpy, visual, DefaultDepth(dpy, scr), ZPixmap,
0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0);
} else {
fb = XGetImage(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
ZPixmap);
}
if (! quiet) {
fprintf(stderr, "Read initial data from display into"
" framebuffer.\n");
}
if (fb->bits_per_pixel == 24 && ! quiet) {
fprintf(stderr, "warning: 24 bpp may have poor performance.\n");
fprintf(stderr, "warning: 24 bpp may have poor"
" performance.\n");
}
if (! dt) {

Loading…
Cancel
Save