x11vnc: -chatwindow, -scale WxH, -enc changes.

pull/1/head
runge 16 years ago
parent 16c7ea1b35
commit 1c03dd4d51

@ -1,3 +1,11 @@
2008-10-19 Karl Runge <runge@karlrunge.com>
* x11vnc: -chatwindow for chat window on X console using SSVNC
as a helper. Print suggestion for X_ShmAttach failure.
Allow -scale WxH for different X- and Y-scaling factors.
Workaround for missing -enc cipher EVP_aes_256_cfb. Modify
message digest and salt/IV parameters. Try to improve compile
time by breaking up large if blocks.
2008-09-21 Karl Runge <runge@karlrunge.com>
* x11vnc: Add symmetric key encryption -enc cipher:keyfile,
works with SSVNC. Make -remap work on MacOSX console.

File diff suppressed because it is too large Load Diff

@ -226,6 +226,26 @@ int trap_getimage_xerror(Display *d, XErrorEvent *error) {
static int Xerror(Display *d, XErrorEvent *error) {
X_UNLOCK;
if (getenv("X11VNC_PRINT_XERROR")) {
fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n",
error->request_code, error->minor_code, error->error_code);
}
if (xshm_opcode > 0 && error->request_code == xshm_opcode) {
if (error->minor_code == X_ShmAttach) {
char *dstr = DisplayString(dpy);
fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n");
fprintf(stderr, " Is your DISPLAY=%s on a remote machine?\n", dstr);
if (strstr(dstr, "localhost:")) {
fprintf(stderr, " Note: DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n");
} else if (dstr[0] != ':') {
fprintf(stderr, " Note: DISPLAY=hostname:N suggests a remote display.\n");
}
fprintf(stderr, " Suggestion, use: x11vnc -display :0 ... for local display :0\n\n");
}
}
interrupted(0);
if (d) {} /* unused vars warning: */

@ -40,6 +40,7 @@ void set_client_input(char *str);
void set_child_info(void);
int cmd_ok(char *cmd);
void client_gone(rfbClientPtr client);
void client_gone_chat_helper(rfbClientPtr client);
void reverse_connect(char *str);
void set_vnc_connect_prop(char *str);
void read_vnc_connect_prop(int);
@ -48,6 +49,8 @@ void read_x11vnc_remote_prop(int);
void check_connect_inputs(void);
void check_gui_inputs(void);
enum rfbNewClientAction new_client(rfbClientPtr client);
enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client);
rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len);
void start_client_info_sock(char *host_port_cookie);
void send_client_info(char *str);
void adjust_grabs(int grab, int quiet);
@ -2788,6 +2791,40 @@ static void turn_off_truecolor_ad(rfbClientPtr client) {
}
}
/*
* some overrides for the local console text chat.
* could be useful in general for local helpers.
*/
rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len) {
if (cl != chat_window_client) {
rfbLog("invalid client during chat_helper login\n");
return FALSE;
} else {
if (!cl->host) {
rfbLog("empty cl->host during chat_helper login\n");
return FALSE;
}
if (strcmp(cl->host, "127.0.0.1")) {
rfbLog("invalid cl->host during chat_helper login: %s\n", cl->host);
return FALSE;
}
rfbLog("chat_helper login accepted\n");
return TRUE;
}
}
enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client) {
client->clientGoneHook = client_gone_chat_helper;
rfbLog("new chat helper\n");
return(RFB_CLIENT_ACCEPT);
}
void client_gone_chat_helper(rfbClientPtr client) {
rfbLog("finished chat helper\n");
chat_window_client = NULL;
}
/*
* libvncserver callback for when a new client connects
*/

@ -19,6 +19,7 @@ extern void set_client_input(char *str);
extern void set_child_info(void);
extern int cmd_ok(char *cmd);
extern void client_gone(rfbClientPtr client);
extern void client_gone_chat_helper(rfbClientPtr client);
extern void reverse_connect(char *str);
extern void set_vnc_connect_prop(char *str);
extern void read_vnc_connect_prop(int);
@ -27,6 +28,8 @@ extern void read_x11vnc_remote_prop(int);
extern void check_connect_inputs(void);
extern void check_gui_inputs(void);
extern enum rfbNewClientAction new_client(rfbClientPtr client);
extern enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client);
extern rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len);
extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str);
extern void adjust_grabs(int grab, int quiet);

@ -555,6 +555,7 @@ static void setup_cursors(void) {
rfbCursorPtr rfb_curs;
char *scale = NULL;
int i, j, n = 0;
int w_in = 0, h_in = 0;
static int first = 1;
if (verbose) {
@ -689,17 +690,27 @@ static void setup_cursors(void) {
} else if (scaling && scale_str) {
scale = scale_str;
}
if (scale && sscanf(scale, "%dx%d", &i, &j) == 2) {
if (wdpy_x > 0) {
w_in = wdpy_x;
h_in = wdpy_y;
} else {
w_in = dpy_x;
h_in = dpy_y;
}
}
/* scale = NULL zeroes everything */
parse_scale_string(scale, &scale_cursor_fac, &scaling_cursor,
parse_scale_string(scale, &scale_cursor_fac_x, &scale_cursor_fac_y, &scaling_cursor,
&scaling_cursor_blend, &j, &j, &scaling_cursor_interpolate,
&scale_cursor_numer, &scale_cursor_denom);
&scale_cursor_numer, &scale_cursor_denom, w_in, h_in);
for (i=0; i<n; i++) {
/* create rfbCursors for the special cursors: */
cursor_info_t *ci = cursors[i];
if (scaling_cursor && scale_cursor_fac != 1.0) {
if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) {
int w, h, x, y, k;
unsigned long *pixels;
@ -982,7 +993,7 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
}
}
if (scaling_cursor && scale_cursor_fac != 1.0) {
if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) {
int W, H;
char *pixels_use = (char *) pixels;
unsigned int *pixels32 = NULL;
@ -990,8 +1001,8 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
W = w;
H = h;
w = scale_round(W, scale_cursor_fac);
h = scale_round(H, scale_cursor_fac);
w = scale_round(W, scale_cursor_fac_x);
h = scale_round(H, scale_cursor_fac_y);
pixels_new = (char *) malloc(4*w*h);
@ -1011,7 +1022,7 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
pixels_use = (char *) pixels32;
}
scale_rect(scale_cursor_fac, scaling_cursor_blend,
scale_rect(scale_cursor_fac_x, scale_cursor_fac_y, scaling_cursor_blend,
scaling_cursor_interpolate,
4, pixels_use, 4*W, pixels_new, 4*w,
W, H, w, h, 0, 0, W, H, 0);
@ -1040,8 +1051,8 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
pixels = (unsigned long *) pixels_new;
xhot = scale_round(xhot, scale_cursor_fac);
yhot = scale_round(yhot, scale_cursor_fac);
xhot = scale_round(xhot, scale_cursor_fac_x);
yhot = scale_round(yhot, scale_cursor_fac_y);
}
len = w * h;

@ -9,6 +9,7 @@
/*
* ultravnc_dsm_helper.c unix/openssl UltraVNC encryption encoder/decoder.
* (also a generic symmetric encryption tunnel)
*
* compile via:
@ -30,6 +31,7 @@
* any-client <=> ultravnc_dsm_helper <--network--> ultravnc_dsm_helper(reverse mode) <=> any-server
*
* e.g. to connect a non-ultra-dsm-vnc viewer to a non-ultra-dsm-vnc server
* without using SSH or SSL.
*
* -----------------------------------------------------------------------
* Copyright (c) 2008 Karl J. Runge <runge@karlrunge.com>
@ -58,7 +60,7 @@ static char *usage =
"e.g.: ultravnc_dsm_helper arc4 ./arc4.key 5901 snoopy.com:5900\n"
"\n"
" cipher: specify 'msrc4', 'msrc4_sc', 'arc4', 'aesv2',\n"
" 'aes-cfb', 'blowfish', or '3des'.\n"
" 'aes-cfb', 'aes256', 'blowfish', or '3des'.\n"
"\n"
" 'msrc4_sc' enables a workaround for UVNC SC -plugin use.\n"
"\n"
@ -84,7 +86,11 @@ static char *usage =
"\n"
"\n"
" Also: cipher may be cipher@n,m where n is the salt size and m is the\n"
" initialization vector size. E.g. aesv2@8,16\n"
" initialization vector size. E.g. aesv2@8,16 Use n=-1 to disable salt\n"
" and the MD5 hash (i.e. insert the keydata directly into the cipher.)\n"
"\n"
" Use cipher@md+n,m to change the message digest. E.g. arc4@sha+8,16\n"
" Supported: 'md5', 'sha', 'sha1', 'ripemd160'.\n"
;
/*
@ -93,8 +99,8 @@ static char *usage =
*
* Note that when running as a module we still assume we have been
* forked off of the parent process and are communicating back to it
* via a socket. So we still exit(3) at the end or on error. And
* the globals would not work.
* via a socket. So we *still* exit(3) at the end or on error. And
* the global settings won't work.
*/
#ifdef ENC_MODULE
# define main __enc_main
@ -124,21 +130,25 @@ static char *prog = "ultravnc_dsm_helper";
#include <netdb.h>
/* Solaris (sysv?) needs INADDR_NONE */
#ifndef INADDR_NONE
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#endif
#if ENC_HAVE_OPENSSL
/* openssl includes */
#if ENC_HAVE_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
static const EVP_CIPHER *Cipher;
static const EVP_MD *Digest;
#endif
static char *cipher = NULL; /* name of cipher, e.g. "aesv2" */
static int reverse = 0; /* listening connection */
static int msrc4_sc = 0; /* enables workaround for SC I/II */
static int noultra = 0; /* manage salt and iv differently than ultradsm */
static int noultra = 0; /* manage salt/iv differently from ultradsm */
static int nomd = 0; /* use the keydata directly, no md5 or salt */
static int pw_in = 0; /* pw=.... read in */
/* The data that was read in from key file (or pw=password) */
@ -157,6 +167,7 @@ static int ivec_size = IVEC;
/* To track parent and child pids */
static pid_t parent, child;
/* transfer buffer size */
#define BSIZE 8192
/* Some very verbose debugging stuff I enable for testing */
@ -170,6 +181,9 @@ static pid_t parent, child;
# define PRINT_IVEC
# define PRINT_KEYDATA
# define PRINT_KEYSTR_AND_FRIENDS
# define PRINT_LOOP_DBG1
# define PRINT_LOOP_DBG2
# define PRINT_LOOP_DBG3
#endif
static void enc_connections(int, char*, int);
@ -185,6 +199,15 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
#else
#if defined(NO_EVP_aes_256_cfb) || (defined (__SVR4) && defined (__sun) && !defined(EVP_aes_256_cfb) && !defined(ASSUME_EVP_aes_256_cfb))
/*
* For Solaris 10 missing 192 & 256 bit crypto.
* Note that EVP_aes_256_cfb is a macro.
*/
#undef EVP_aes_256_cfb
#define EVP_aes_256_cfb() EVP_aes_128_cfb(); {fprintf(stderr, "Not compiled with EVP_aes_256_cfb() 'aes256' support.\n"); exit(1);}
#endif
/* If we are a module, enc_do() is the only interface we export. */
@ -197,8 +220,9 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
char tmp[16];
int fd, len, listen_port, connect_port, mbits;
/* check for noultra mode: */
q = ciph;
/* check for noultra mode: */
if (strstr(q, "noultra:") == q) {
noultra = 1;
q += strlen("noultra:");
@ -227,13 +251,16 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
} else if (strstr(q, "aes-cfb") == q) {
Cipher = EVP_aes_128_cfb(); cipher = "aes-cfb";
} else if (strstr(q, "aes256") == q) {
Cipher = EVP_aes_256_cfb(); cipher = "aes256";
} else if (strstr(q, "blowfish") == q) {
Cipher = EVP_bf_cfb(); cipher = "blowfish";
} else if (strstr(q, "3des") == q) {
Cipher = EVP_des_ede3_ofb(); cipher = "3des";
Cipher = EVP_des_ede3_cfb(); cipher = "3des";
} else {
} else if (strstr(q, ".") == q) {
/* otherwise, try to guess cipher from key filename: */
if (strstr(keyfile, "arc4.key")) {
Cipher = EVP_rc4(); cipher = "arc4";
@ -247,33 +274,76 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
} else if (strstr(keyfile, "aes-cfb.key")) {
Cipher = EVP_aes_128_cfb(); cipher = "aes-cfb";
} else if (strstr(keyfile, "aes256.key")) {
Cipher = EVP_aes_256_cfb(); cipher = "aes256";
} else if (strstr(keyfile, "blowfish.key")) {
Cipher = EVP_bf_cfb(); cipher = "blowfish";
} else if (strstr(keyfile, "3des.key")) {
Cipher = EVP_des_ede3_ofb(); cipher = "3des";
Cipher = EVP_des_ede3_cfb(); cipher = "3des";
} else {
fprintf(stderr, "cannot figure out cipher, supply 'msrc4', 'arc4', or 'aesv2' ...\n");
exit(1);
}
} else {
fprintf(stderr, "cannot figure out cipher, supply 'msrc4', 'arc4', or 'aesv2' ...\n");
exit(1);
}
/* look for user specified salt and IV sizes at the end: */
/* set the default message digest (md5) */
Digest = EVP_md5();
/*
* Look for user specified salt and IV sizes at the end
* ( ciph@salt,iv and ciph@[md+]salt,iv ):
*/
p = strchr(q, '@');
if (p) {
int s, v;
if (sscanf(p+1, "%d,%d", &s, &v) == 2) {
if (0 <= s && s <= SALT) {
p++;
if (strstr(p, "md5+") == p) {
Digest = EVP_md5(); p += strlen("md5+");
} else if (strstr(p, "sha+") == p) {
Digest = EVP_sha(); p += strlen("sha+");
} else if (strstr(p, "sha1+") == p) {
Digest = EVP_sha1(); p += strlen("sha1+");
} else if (strstr(p, "ripe+") == p) {
Digest = EVP_ripemd160(); p += strlen("ripe+");
} else if (strstr(p, "ripemd160+") == p) {
Digest = EVP_ripemd160(); p += strlen("ripemd160+");
}
if (sscanf(p, "%d,%d", &s, &v) == 2) {
/* cipher@n,m */
if (-1 <= s && s <= SALT) {
salt_size = s;
} else {
fprintf(stderr, "%s: invalid salt size: %d\n",
prog, s);
exit(1);
}
if (0 <= v && v <= EVP_MAX_IV_LENGTH) {
ivec_size = v;
} else {
fprintf(stderr, "%s: invalid IV size: %d\n",
prog, v);
exit(1);
}
} else if (sscanf(p+1, "%d", &s) == 1) {
if (0 <= s && s <= SALT) {
} else if (sscanf(p, "%d", &s) == 1) {
/* cipher@n */
if (-1 <= s && s <= SALT) {
salt_size = s;
} else {
fprintf(stderr, "%s: invalid salt size: %d\n",
prog, s);
exit(1);
}
}
if (salt_size == -1) {
/* let salt = -1 mean skip both MD5 and salt */
nomd = 1;
salt_size = 0;
}
}
@ -292,20 +362,24 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
connect_host = strdup(rhp);
/* check for and read in the key file */
memset(keydata, 0, sizeof(keydata));
if (stat(keyfile, &sb) != 0) {
if (strstr(keyfile, "pw=") == keyfile) {
/* user specified key/password on cmdline */
int i;
len = 0;
pw_in = 1;
for (i=0; i < strlen(keyfile); i++) {
/* load the string to keydata: */
int n = i + strlen("pw=");
keydata[i] = keyfile[n];
if (keyfile[n] == '\0') break;
len++;
if (i > 100) break;
}
goto readed_in;
}
/* otherwise invalid file */
perror("stat");
exit(1);
}
@ -330,6 +404,7 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
readed_in:
/* check for ultravnc msrc4 format 'rc4.key' */
mbits = 0;
if (strstr(keydata, "128 bit") == keydata) {
@ -373,7 +448,6 @@ extern void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
* encrypt or decrypt.
*/
static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
/*
* We keep both E and D aspects in case we revert back to a
* single process calling select(2) on all fds...
@ -388,9 +462,9 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
unsigned char salt[SALT+1];
unsigned char ivec[EVP_MAX_IV_LENGTH];
int i, cnt, len, n = 0, m, vb = 0, pa = 1, first = 1;
int i, cnt, len, m, n = 0, vb = 0, pa = 1, first = 1;
int whoops = 1; /* for the msrc4 problem */
char *encstr;
char *encstr, *encsym;
/* zero the buffers */
memset(buf, 0, BSIZE);
@ -404,6 +478,10 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
salt_size = MSRC4_SALT; /* 11 vs. 16 */
}
if (msrc4_sc) {
whoops = 1; /* force workaround in SC mode */
}
if (getenv("ENCRYPT_VERBOSE")) {
vb = 1; /* let user turn on some debugging via env. var. */
}
@ -415,10 +493,7 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
encrypt = (!encrypt);
}
encstr = encrypt ? "encrypt" : "decrypt"; /* string for messages */
if (msrc4_sc) {
whoops = 1;
}
encsym = encrypt ? "+" : "-";
if (encrypt) {
/* encrypter initializes the salt and initialization vector */
@ -426,7 +501,8 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
/*
* Our salt is 16 bytes but I believe only the first 8
* bytes are used by EVP_BytesToKey(3). Since we send it
* to the other "plugin" we need to keep it 16.
* to the other "plugin" we need to keep it 16. Also,
* the IV size can depend on the cipher type. Again, 16.
*/
RAND_bytes(salt, salt_size);
RAND_bytes(ivec, ivec_size);
@ -452,18 +528,23 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
tv.tv_usec = 100 * 1000;
select(1, NULL, NULL, NULL, &tv);
if (salt_size+ivec_size == 0) {
n = 0; /* no salt or iv, skip reading. */
} else {
n = read(sock_fr, buf, salt_size+ivec_size+96);
}
if (n == 0 && salt_size+ivec_size > 0) {
fprintf(stderr, "%s: decrypt finished.\n", prog);
goto finished;
}
if (n < salt_size+ivec_size) {
if (msrc4_sc && n == 12) {
fprintf(stderr, "%s: only %d bytes read. Assuming UVNC Single Click server.\n", prog, n);
fprintf(stderr, "%s: only %d bytes read. Assuming "
"UVNC Single Click server.\n", prog, n);
} else {
if (n < 0) perror("read");
fprintf(stderr, "%s: could not read enough for salt and ivec: n=%d\n", prog, n);
fprintf(stderr, "%s: could not read enough for salt "
"and ivec: n=%d\n", prog, n);
goto finished;
}
}
@ -482,7 +563,10 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
psrc = buf + salt_size + ivec_size;
if (n > 0) {
/* copy it down to the start of buf for sending below */
/*
* copy it down to the start of buf for
* sending below:
*/
for (i=0; i < n; i++) {
buf[i] = psrc[i];
}
@ -505,37 +589,74 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
fprintf(stderr, "%s: %s - WARNING: MSRC4 mode and IGNORING random salt\n", prog, encstr);
fprintf(stderr, "%s: %s - WARNING: and initialization vector!!\n", prog, encstr);
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit_ex(ctx, Cipher, NULL, (unsigned char *) keydata, NULL, encrypt);
if (pw_in) {
/* for pw=xxxx a md5 hash is used */
EVP_BytesToKey(Cipher, Digest, NULL, keydata,
keydata_len, 1, keystr, NULL);
EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, NULL,
encrypt);
} else {
/* otherwise keydata as is */
EVP_CipherInit_ex(ctx, Cipher, NULL,
(unsigned char *) keydata, NULL, encrypt);
}
} else {
/* XXX might not be correct */
exit(1);
EVP_BytesToKey(Cipher, EVP_md5(), NULL, keydata, keydata_len, 1, keystr, ivec);
EVP_BytesToKey(Cipher, Digest, NULL, keydata,
keydata_len, 1, keystr, ivec);
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, ivec, encrypt);
EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, ivec,
encrypt);
}
} else {
unsigned char *in_salt;
/* check salt and IV source and size. */
if (salt_size <= 0) {
/* let salt_size = 0 mean keep it out of the MD5 */
fprintf(stderr, "%s: %s - WARNING: no salt\n", prog, encstr);
fprintf(stderr, "%s: %s - WARNING: no salt\n",
prog, encstr);
in_salt = NULL;
} else {
in_salt = salt;
}
if (ivec_size < Cipher->iv_len) {
fprintf(stderr, "%s: %s - WARNING: short IV %d < %d\n", prog, encstr, ivec_size, Cipher->iv_len);
fprintf(stderr, "%s: %s - WARNING: short IV %d < %d\n",
prog, encstr, ivec_size, Cipher->iv_len);
}
/* make the hashed value and place in keystr */
/* XXX N.B.: DSM plugin had count=0, and overwrote ivec by not passing NULL iv */
/*
* XXX N.B.: DSM plugin had count=0, and overwrote ivec
* by not passing NULL iv.
*/
if (nomd) {
/* special mode: no salt or md5, use keydata directly */
int sz = keydata_len < EVP_MAX_KEY_LENGTH ?
keydata_len : EVP_MAX_KEY_LENGTH;
fprintf(stderr, "%s: %s - WARNING: no-md5 specified: ignoring salt & hash\n", prog, encstr);
memcpy(keystr, keydata, sz);
} else if (noultra && ivec_size > 0) {
/* "normal" mode, don't overwrite ivec. */
EVP_BytesToKey(Cipher, Digest, in_salt, keydata,
keydata_len, 1, keystr, NULL);
if (noultra && ivec_size > 0) {
EVP_BytesToKey(Cipher, EVP_md5(), in_salt, keydata, keydata_len, 1, keystr, NULL);
} else {
/* even under noultra we overwrite ivec if ivec_size = 0 */
EVP_BytesToKey(Cipher, EVP_md5(), in_salt, keydata, keydata_len, 1, keystr, ivec);
/*
* Ultra DSM compatibility mode. Note that this
* clobbers the ivec we set up above! Under
* noultra we overwrite ivec only if ivec_size=0.
*/
EVP_BytesToKey(Cipher, Digest, in_salt, keydata,
keydata_len, 1, keystr, ivec);
}
@ -545,7 +666,10 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
/* set the cipher & initialize */
/* XXX N.B.: DSM plugin had encrypt=1 for both (i.e. perfectly symmetric) */
/*
* XXX N.B.: DSM plugin had encrypt=1 for both
* (i.e. perfectly symmetric)
*/
EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, ivec, encrypt);
}
@ -562,27 +686,28 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
/* skip sending salt+iv */
first = 0;
continue;
} else {
/* use that first block of data placed in buf */
}
/* use that first block of data placed in buf above */
} else if (first && n == 0 && salt_size + ivec_size == 0) {
first = 0;
continue;
} else {
/* general case of loop, read some in: */
n = read(sock_fr, buf, BSIZE);
}
/* debug output: */
if (vb) fprintf(stderr, "%s%d/%d ", encrypt ? "+" : "-", n, errno);
if (n <= 0) {} else if (encrypt) {ENC_PT_DBG(buf, n);} else {DEC_CT_DBG(buf, n);}
if (vb) fprintf(stderr, "%s%d/%d ", encsym, n, errno);
PRINT_LOOP_DBG1;
if (n == 0 || (n < 0 && errno != EINTR)) {
/* failure to read any data... it is EOF or fatal error. */
/* failure to read any data, it is EOF or fatal error */
int err = errno;
/* debug output: */
char tmp[32]; int err = errno;
if (encrypt) {ENC_PT_DBG("--EOF--", 7);} else {DEC_CT_DBG("--EOF--", 7);}
sprintf(tmp, "err=%d,n=%d", err, n);
PRINT_LOOP_DBG2;
fprintf(stderr, "%s: %s - input stream finished: n=%d, err=%d", prog, encstr, n, err);
if (encrypt) {ENC_PT_DBG(tmp, strlen(tmp));} else {DEC_CT_DBG(tmp, strlen(tmp));}
/* EOF or fatal error */
break;
@ -602,8 +727,8 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
}
/* debug output: */
if (vb) fprintf(stderr, "c%d/%d ", cnt, n);
if (encrypt) {ENC_CT_DBG(out, cnt);} else {DEC_PT_DBG(out, cnt);}
if (vb) fprintf(stderr, "%sc%d/%d ", encsym, cnt, n);
PRINT_LOOP_DBG3;
/* write transformed data to the other end: */
len = cnt;
@ -613,7 +738,7 @@ static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
m = write(sock_to, psrc, len);
/* debug output: */
if (vb) fprintf(stderr, "m%s%d/%d ", encrypt ? "+" : "-", m, errno);
if (vb) fprintf(stderr, "m%s%d/%d ", encsym, m, errno);
if (m > 0) {
/* scoot them by how much was written: */
@ -697,7 +822,8 @@ static void enc_connections(int listen_port, char *connect_host, int connect_por
exit(1);
}
ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof(one));
if (ret < 0) {
perror("setsockopt");
exit(1);
@ -715,7 +841,8 @@ static void enc_connections(int listen_port, char *connect_host, int connect_por
exit(1);
}
fprintf(stderr, "%s: waiting for connection on port: %d\n", prog, listen_port);
fprintf(stderr, "%s: waiting for connection on port: %d\n",
prog, listen_port);
/* wait for a connection: */
clen = sizeof(client);
@ -769,6 +896,8 @@ static void enc_connections(int listen_port, char *connect_host, int connect_por
if (child == (pid_t) -1) {
/* couldn't fork... */
perror("fork");
close(conn1);
close(conn2);
exit(1);
}
@ -797,7 +926,7 @@ extern int main (int argc, char *argv[]) {
q = strstr(argv[2], "pw=");
if (q) {
while (*q != '\0') {
*q = '\0';
*q = '\0'; /* now ps(1) won't show it */
q++;
}
}

@ -296,6 +296,10 @@ void print_help(int mode) {
" the notation \"m/n\" may be used to denote fractions\n"
" exactly, e.g. -scale 2/3\n"
"\n"
" To scale asymmetrically in the horizontal and vertical\n"
" directions, specify a WxH geometry to stretch to:\n"
" e.g. '-scale 1024x768', or also '-scale 0.9x0.75'\n"
"\n"
" Scaling Options: can be added after \"fraction\" via\n"
" \":\", to supply multiple \":\" options use commas.\n"
" If you just want a quick, rough scaling without\n"
@ -316,6 +320,8 @@ void print_help(int mode) {
" and height to be multiples of scaling denominator\n"
" (e.g. 3 for 2/3).\n"
"\n"
"-geometry WxH Same as -scale WxH\n"
"\n"
"-scale_cursor frac By default if -scale is supplied the cursor shape is\n"
" scaled by the same factor. Depending on your usage,\n"
" you may want to scale the cursor independently of the\n"
@ -1734,9 +1740,9 @@ void print_help(int mode) {
" choice of implementation).\n"
"\n"
" cipher can be one of: arc4, aesv2, aes-cfb, blowfish,\n"
" or 3des. See the OpenSSL documentation for more info.\n"
" The keysize is 128 bits. Here is one way to make a\n"
" keyfile with that many bits:\n"
" aes256, or 3des. See the OpenSSL documentation for\n"
" more info. The keysize is 128 bits (except for aes256).\n"
" Here is one way to make a keyfile with that many bits:\n"
"\n"
" dd if=/dev/random of=./my.key bs=16 count=1\n"
"\n"
@ -1774,6 +1780,18 @@ void print_help(int mode) {
" although you may be forced to if the other side of the\n"
" tunnel is not under your control.\n"
"\n"
" To skip the salt and EVP_BytesToKey MD5 entirely (no\n"
" hashing is done: the keydata is directly inserted into\n"
" the cipher) specify \"-1\" for the salt, e.g.\n"
"\n"
" -enc blowfish@-1,16:./my.key\n"
"\n"
" The message digest can also be changed to something\n"
" besides the default MD5. Use cipher@md+n,m where \"md\"\n"
" can be one of sha, sha1, md5, or ripe. For example:\n"
"\n"
" -enc arc4@sha+8,16:./my.key\n"
"\n"
" The SSVNC vnc viewer project supplies a symmetric\n"
" encryption tool named \"ultravnc_dsm_helper\" that can\n"
" be used on the viewer side. For example:\n"
@ -1783,14 +1801,20 @@ void print_help(int mode) {
" where h:p is the hostname and port of the x11vnc server.\n"
" ultravnc_dsm_helper may also be used standalone to\n"
" provide a symmetric encryption tunnel for any viewer\n"
" or server (VNC or otherwise.)\n"
" or server (VNC or otherwise.) The cipher (1st arg)\n"
" is basically the same syntax as we use above.\n"
"\n"
" Also see the 'Non-Ultra DSM' SSVNC option for the\n"
" 'UltraVNC DSM Encryption Plugin' advanced option.\n"
"\n"
"-https [port] Choose a separate HTTPS port (-ssl mode only).\n"
" For both ways of using the viewer, you can specify the\n"
" salt,ivec sizes (in GUI or, e.g. arc4@8,16).\n"
"\n"
" In -ssl mode, it turns out you can use the\n"
"-https [port] Use a special, separate HTTPS port (-ssl mode only)\n"
" for HTTPS Java viewer applet downloading. I.e. not 5900\n"
" and not 5800 (the defaults.)\n"
"\n"
" BACKGROUND: In -ssl mode, it turns out you can use the\n"
" single VNC port (e.g. 5900) for both VNC and HTTPS\n"
" connections. (HTTPS is used to retrieve a SSL-aware\n"
" VncViewer.jar applet that is provided with x11vnc).\n"
@ -1808,14 +1832,15 @@ void print_help(int mode) {
" or VNC Viewer applet. That's right 3 separate \"Are\n"
" you sure you want to connect?\" dialogs!)\n"
"\n"
" So use the -https option to provide a separate, more\n"
" reliable HTTPS port that x11vnc will listen on. If\n"
" USAGE: So use the -https option to provide a separate,\n"
" more reliable HTTPS port that x11vnc will listen on. If\n"
" [port] is not provided (or is 0), one is autoselected.\n"
" The URL to use is printed out at startup.\n"
"\n"
" The SSL Java applet directory is specified via the\n"
" -httpdir option. If not supplied it will try to guess\n"
" the directory as though the -http option was supplied.\n"
" -httpdir option. If not supplied, -https will try\n"
" to guess the directory as though the -http option\n"
" was supplied.\n"
"\n"
"-httpsredir [port] In -ssl mode with the Java applet retrieved via HTTPS,\n"
" when the HTML file containing applet parameters\n"
@ -3261,6 +3286,25 @@ void print_help(int mode) {
" and ServerInput. The others managed by libvncserver\n"
" (textchat, 1/n scaling, rfbEncodingUltra) are not.\n"
"\n"
"-chatwindow Place a local UltraVNC chat window on the X11 display\n"
" that x11vnc is polling. That way the person on the VNC\n"
" viewer-side can chat with the person at the physical\n"
" X11 console. (e.g. helpdesk w/o telephone)\n"
"\n"
" For this to work the SSVNC package (version 1.0.21 or\n"
" later) MUST BE installed on the system where x11vnc runs\n"
" and the 'ssvnc' command must be available in $PATH.\n"
" The ssvncviewer is used as a chat window helper.\n"
" See http://www.karlrunge.com/x11vnc/ssvnc.html\n"
"\n"
" This option implies '-rfbversion 3.6' so as to trick\n"
" UltraVNC viewers, otherwise they assume chat is not\n"
" available. To specify a different rfbversion, place\n"
" it after the -chatwindow option on the cmdline.\n"
"\n"
" See also the remote control 'chaton' and 'chatoff'\n"
" actions. These can also be set from the tkx11vnc GUI.\n"
"\n"
"-noxdamage Do not use the X DAMAGE extension to detect framebuffer\n"
" changes even if it is available. Use -xdamage if your\n"
" default is to have it off.\n"
@ -4158,6 +4202,10 @@ void print_help(int mode) {
" serverdpms disable -noserverdpms mode.\n"
" noultraext enable -noultraext mode.\n"
" ultraext disable -noultraext mode.\n"
" chatwindow enable local chatwindow mode.\n"
" nochatwindow disable local chatwindow mode.\n"
" chaton begin chat using local window.\n"
" chatoff end chat using local window.\n"
" xdamage enable xdamage polling hints.\n"
" noxdamage disable xdamage polling hints.\n"
" xd_area:A set -xd_area max pixel area to \"A\"\n"
@ -4293,16 +4341,17 @@ void print_help(int mode) {
" nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area\n"
" scr_skip scr_inc scr_keys scr_term scr_keyrepeat\n"
" scr_parms scrollcopyrect scr noscrollcopyrect noscr\n"
" fixscreen noxrecord xrecord reset_record pointer_mode pm\n"
" input_skip allinput noallinput input grabkbd nograbkbd\n"
" grabptr nograbptr grabalways nograbalways grablocal\n"
" client_input ssltimeout speeds wmdt debug_pointer dp\n"
" nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n"
" nodk keycode deferupdate defer wait_ui wait_bog\n"
" nowait_bog slow_fb xrefresh wait readtimeout nap nonap\n"
" sb screen_blank fbpm nofbpm dpms nodpms clientdpms\n"
" noclientdpms forcedpms noforcedpms noserverdpms\n"
" serverdpms noultraext ultraext fs gaps grow fuzz snapfb\n"
" fixscreen noxrecord xrecord reset_record pointer_mode\n"
" pm input_skip allinput noallinput input grabkbd\n"
" nograbkbd grabptr nograbptr grabalways nograbalways\n"
" grablocal client_input ssltimeout speeds wmdt\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard\n"
" dk nodebug_keyboard nodk keycode deferupdate defer\n"
" wait_ui wait_bog nowait_bog slow_fb xrefresh wait\n"
" readtimeout nap nonap sb screen_blank fbpm nofbpm dpms\n"
" nodpms clientdpms noclientdpms forcedpms noforcedpms\n"
" noserverdpms serverdpms noultraext ultraext chatwindow\n"
" nochatwindow chaton chatoff fs gaps grow fuzz snapfb\n"
" nosnapfb rawfb uinput_accel uinput_thresh uinput_reset\n"
" uinput_always progressive rfbport http nohttp httpport\n"
" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n"
@ -4319,9 +4368,9 @@ void print_help(int mode) {
" macnomenu nomacmenu macuskbd nomacuskbd noremote\n"
"\n"
" aro= noop display vncdisplay desktopname guess_desktop\n"
" http_url auth xauth users rootshift clipshift\n"
" scale_str scaled_x scaled_y scale_numer scale_denom\n"
" scale_fac scaling_blend scaling_nomult4 scaling_pad\n"
" http_url auth xauth users rootshift clipshift scale_str\n"
" scaled_x scaled_y scale_numer scale_denom scale_fac_x\n"
" scale_fac_y scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer\n"
" nocmds passwdfile unixpw unixpw_nis unixpw_list ssl\n"
" ssl_pem sslverify stunnel stunnel_pem https httpsredir\n"

@ -388,6 +388,8 @@ int no_ultra_dpms = 0;
int no_ultra_ext = 0;
int saw_ultra_chat = 0;
int saw_ultra_file = 0;
int chat_window = 0;
rfbClientPtr chat_window_client = NULL;
int watch_selection = 1; /* normal selection/cutbuffer maintenance */
int watch_primary = 1; /* more dicey, poll for changes in PRIMARY */

@ -287,6 +287,8 @@ extern int no_ultra_dpms;
extern int no_ultra_ext;
extern int saw_ultra_chat;
extern int saw_ultra_file;
extern int chat_window;
extern rfbClientPtr chat_window_client;
extern int watch_selection;
extern int watch_primary;

File diff suppressed because it is too large Load Diff

@ -24,7 +24,7 @@ void free_tiles(void);
void shm_delete(XShmSegmentInfo *shm);
void shm_clean(XShmSegmentInfo *shm, XImage *xim);
void initialize_polling_images(void);
void scale_rect(double factor, int blend, int interpolate, int Bpp,
void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark);
void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark);
@ -737,7 +737,7 @@ weights for this scaled pixel are:
* the loop over the 4 pixels.
*/
void scale_rect(double factor, int blend, int interpolate, int Bpp,
void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark) {
/*
@ -773,7 +773,7 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
int b, k;
double pixave[4]; /* for averaging pixel values */
if (factor <= 1.0) {
if (factor_x <= 1.0 && factor_y <= 1.0) {
shrink = 1;
} else {
shrink = 0;
@ -787,8 +787,8 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
* This new way is probably the best we can do, take the inverse
* of the scaling factor to double precision.
*/
dx = 1.0/factor;
dy = 1.0/factor;
dx = 1.0/factor_x;
dy = 1.0/factor_y;
/*
* There is some speedup if the pixel weights are constant, so
@ -797,15 +797,18 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
* If scale = 1/n and n divides Nx and Ny, the pixel weights
* are constant (e.g. 1/2 => equal on 2x2 square).
*/
if (factor != last_factor || Nx != last_Nx || Ny != last_Ny) {
if (factor_x != last_factor || Nx != last_Nx || Ny != last_Ny) {
constant_weights = -1;
mag_int = -1;
last_Nx = Nx;
last_Ny = Ny;
last_factor = factor;
last_factor = factor_x;
}
if (constant_weights < 0 && factor_x != factor_y) {
constant_weights = 0;
mag_int = 0;
if (constant_weights < 0) {
} else if (constant_weights < 0) {
int n = 0;
constant_weights = 0;
@ -814,7 +817,7 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
for (i = 2; i<=128; i++) {
double test = ((double) 1)/ i;
double diff, eps = 1.0e-7;
diff = factor - test;
diff = factor_x - test;
if (-eps < diff && diff < eps) {
n = i;
break;
@ -839,18 +842,18 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
for (i = 2; i<=32; i++) {
double test = (double) i;
double diff, eps = 1.0e-7;
diff = factor - test;
diff = factor_x - test;
if (-eps < diff && diff < eps) {
n = i;
break;
}
}
if (! blend && factor > 1.0 && n) {
if (! blend && factor_x > 1.0 && n) {
mag_int = n;
}
}
if (mark && factor > 1.0 && blend) {
if (mark && factor_x > 1.0 && blend) {
/*
* kludge: correct for interpolating blurring leaking
* up or left 1 destination pixel.
@ -1296,7 +1299,7 @@ void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark) {
dst_fb = rfb_fb;
dst_bpl = rfb_bytes_per_line;
scale_rect(scale_fac, scaling_blend, scaling_interpolate, fac * Bpp,
scale_rect(scale_fac_x, scale_fac_y, scaling_blend, scaling_interpolate, fac * Bpp,
src_fb, fac * main_bytes_per_line, dst_fb, dst_bpl, dpy_x, dpy_y,
scaled_x, scaled_y, X1, Y1, X2, Y2, mark);
}
@ -2623,7 +2626,7 @@ static void nap_set(int tile_cnt) {
if (! nap_ok && client_count) {
if(now > last_fb_bytes_sent + no_fbu_blank) {
if (debug_tiles > 1) {
printf("nap_set: nap_ok=1: now: %d last: %d\n",
fprintf(stderr, "nap_set: nap_ok=1: now: %d last: %d\n",
(int) now, (int) last_fb_bytes_sent);
}
nap_ok = 1;
@ -2683,10 +2686,16 @@ static void nap_check(int tile_cnt) {
dt_fbu = (int) (now - last_fb_bytes_sent);
if (dt_fbu > screen_blank) {
/* sleep longer for no fb requests */
if (debug_tiles > 1) {
fprintf(stderr, "screen blank sleep1: %d ms / 16\n", 2 * ms);
}
nap_sleep(2 * ms, 16);
return;
}
if (dt_ev > screen_blank) {
if (debug_tiles > 1) {
fprintf(stderr, "screen blank sleep2: %d ms / 8\n", ms);
}
nap_sleep(ms, 8);
return;
}
@ -2699,6 +2708,9 @@ static void nap_check(int tile_cnt) {
} else if (now - last_local_input <= 3) {
nap_ok = 0;
} else {
if (debug_tiles > 1) {
fprintf(stderr, "nap_check sleep: %d ms / 1\n", ms);
}
nap_sleep(ms, 1);
}
}

@ -11,7 +11,7 @@ extern void free_tiles(void);
extern void shm_delete(XShmSegmentInfo *shm);
extern void shm_clean(XShmSegmentInfo *shm, XImage *xim);
extern void initialize_polling_images(void);
extern void scale_rect(double factor, int blend, int interpolate, int Bpp,
extern void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark);
extern void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark);

@ -26,6 +26,7 @@
#include "avahi.h"
#include "solid.h"
#include "inet.h"
#include "xrandr.h"
#include <rfb/rfbclient.h>
@ -40,8 +41,8 @@ void free_old_fb(void);
void check_padded_fb(void);
void install_padded_fb(char *geom);
XImage *initialize_xdisplay_fb(void);
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom);
void parse_scale_string(char *str, double *factor_x, double *factor_y, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom, int w_in, int h_in);
int parse_rotate_string(char *str, int *mode);
int scale_round(int len, double fac);
void initialize_screen(int *argc, char **argv, XImage *fb);
@ -54,6 +55,8 @@ rfbBool vnc_reflect_send_pointer(int x, int y, int mask);
rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down);
rfbBool vnc_reflect_send_cuttext(char *str, int len);
void watch_loop(void);
static void debug_colormap(XImage *fb);
static void set_visual(char *str);
static void nofb_hook(rfbClientPtr cl);
@ -65,6 +68,11 @@ static void initialize_clipshift(void);
static int wait_until_mapped(Window win);
static void setup_scaling(int *width_in, int *height_in);
static void check_filexfer(void);
static void record_last_fb_update(void);
static void check_cursor_changes(void);
static int choose_delay(double dt);
int rawfb_reset = -1;
int rawfb_dev_video = 0;
int rawfb_vnc_reflect = 0;
@ -2194,14 +2202,15 @@ if (0) fprintf(stderr, "DefaultDepth: %d visial_id: %d\n", depth, (int) visual_
#endif /* NO_X11 */
}
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom) {
void parse_scale_string(char *str, double *factor_x, double *factor_y, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom, int w_in, int h_in) {
int m, n;
char *p, *tstr;
double f;
double f, f2;
*factor = 1.0;
*factor_x = 1.0;
*factor_y = 1.0;
*scaling = 0;
*blend = 1;
*nomult4 = 0;
@ -2240,19 +2249,26 @@ void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
}
*p = '\0';
}
if (strchr(tstr, '.') != NULL) {
double test, diff, eps = 1.0e-7;
if (sscanf(tstr, "%lf", &f) != 1) {
if (sscanf(tstr, "%lfx%lf", &f, &f2) == 2) {
*factor_x = (double) f;
*factor_y = (double) f2;
} else if (sscanf(tstr, "%lf", &f) != 1) {
rfbLogEnable(1);
rfbLog("invalid -scale arg: %s\n", tstr);
clean_up_exit(1);
} else {
*factor_x = (double) f;
*factor_y = (double) f;
}
*factor = (double) f;
/* look for common fractions from small ints: */
if (*factor_x == *factor_y) {
for (n=2; n<=10; n++) {
for (m=1; m<n; m++) {
test = ((double) m)/ n;
diff = *factor - test;
diff = *factor_x - test;
if (-eps < diff && diff < eps) {
*numer = m;
*denom = n;
@ -2264,11 +2280,15 @@ void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
break;
}
}
if (*factor < 0.01) {
if (*factor_x < 0.01) {
rfbLogEnable(1);
rfbLog("-scale factor too small: %f\n", scale_fac);
rfbLog("-scale factor too small: %f\n", *factor_x);
clean_up_exit(1);
}
}
} else if (sscanf(tstr, "%dx%d", &m, &n) == 2 && w_in > 0 && h_in > 0) {
*factor_x = ((double) m) / ((double) w_in);
*factor_y = ((double) n) / ((double) h_in);
} else {
if (sscanf(tstr, "%d/%d", &m, &n) != 2) {
if (sscanf(tstr, "%d", &m) != 1) {
@ -2285,18 +2305,19 @@ void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
rfbLog("invalid -scale arg: %s\n", tstr);
clean_up_exit(1);
}
*factor = ((double) m)/ n;
if (*factor < 0.01) {
*factor_x = ((double) m)/ n;
*factor_y = ((double) m)/ n;
if (*factor_x < 0.01) {
rfbLogEnable(1);
rfbLog("-scale factor too small: %f\n", *factor);
rfbLog("-scale factor too small: %f\n", *factor_x);
clean_up_exit(1);
}
*numer = m;
*denom = n;
}
if (*factor == 1.0) {
if (*factor_x == 1.0 && *factor_y == 1.0) {
if (! quiet) {
rfbLog("scaling disabled for factor %f\n", *factor);
rfbLog("scaling disabled for factor %f %f\n", *factor_x, *factor_y);
}
} else {
*scaling = 1;
@ -2347,13 +2368,13 @@ static void setup_scaling(int *width_in, int *height_in) {
int width = *width_in;
int height = *height_in;
parse_scale_string(scale_str, &scale_fac, &scaling, &scaling_blend,
parse_scale_string(scale_str, &scale_fac_x, &scale_fac_y, &scaling, &scaling_blend,
&scaling_nomult4, &scaling_pad, &scaling_interpolate,
&scale_numer, &scale_denom);
&scale_numer, &scale_denom, *width_in, *height_in);
if (scaling) {
width = scale_round(width, scale_fac);
height = scale_round(height, scale_fac);
width = scale_round(width, scale_fac_x);
height = scale_round(height, scale_fac_y);
if (scale_denom && scaling_pad) {
/* it is not clear this padding is useful anymore */
rfbLog("width %% denom: %d %% %d = %d\n", width,
@ -2487,8 +2508,8 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
setup_scaling(&width, &height);
if (scaling) {
rfbLog("scaling screen: %dx%d -> %dx%d scale_fac=%.5f\n",
fb->width, fb->height, scaled_x, scaled_y, scale_fac);
rfbLog("scaling screen: %dx%d -> %dx%d\n", fb->width, fb->height, scaled_x, scaled_y);
rfbLog("scaling screen: scale_fac_x=%.5f scale_fac_y=%.5f\n", scale_fac_x, scale_fac_y);
rfb_bytes_per_line = (main_bytes_per_line / fb->width) * width;
} else {
@ -3240,4 +3261,562 @@ void set_vnc_desktop_name(void) {
}
}
static void check_cursor_changes(void) {
static double last_push = 0.0;
if (unixpw_in_progress) return;
cursor_changes += check_x11_pointer();
if (cursor_changes) {
double tm, max_push = 0.125, multi_push = 0.01, wait = 0.02;
int cursor_shape, dopush = 0, link, latency, netrate;
if (! all_clients_initialized()) {
/* play it safe */
return;
}
if (0) cursor_shape = cursor_shape_updates_clients(screen);
dtime0(&tm);
link = link_rate(&latency, &netrate);
if (link == LR_DIALUP) {
max_push = 0.2;
wait = 0.05;
} else if (link == LR_BROADBAND) {
max_push = 0.075;
wait = 0.05;
} else if (link == LR_LAN) {
max_push = 0.01;
} else if (latency < 5 && netrate > 200) {
max_push = 0.01;
}
if (tm > last_push + max_push) {
dopush = 1;
} else if (cursor_changes > 1 && tm > last_push + multi_push) {
dopush = 1;
}
if (dopush) {
mark_rect_as_modified(0, 0, 1, 1, 1);
fb_push_wait(wait, FB_MOD);
last_push = tm;
} else {
rfbPE(0);
}
}
cursor_changes = 0;
}
/*
* These watch_loop() releated were moved from x11vnc.c so we could try
* to remove -O2 from its compilation. TDB new file, e.g. watch.c.
*/
static void check_filexfer(void) {
static time_t last_check = 0;
rfbClientIteratorPtr iter;
rfbClientPtr cl;
int transferring = 0;
if (time(NULL) <= last_check) {
return;
}
#if 0
if (getenv("NOFT")) {
return;
}
#endif
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->fileTransfer.receiving) {
transferring = 1;
break;
}
if (cl->fileTransfer.sending) {
transferring = 1;
break;
}
}
rfbReleaseClientIterator(iter);
if (transferring) {
double start = dnow();
while (dnow() < start + 0.5) {
rfbCFD(5000);
rfbCFD(1000);
rfbCFD(0);
}
} else {
last_check = time(NULL);
}
}
static void record_last_fb_update(void) {
static int rbs0 = -1;
static time_t last_call = 0;
time_t now = time(NULL);
int rbs = -1;
rfbClientIteratorPtr iter;
rfbClientPtr cl;
if (last_fb_bytes_sent == 0) {
last_fb_bytes_sent = now;
last_call = now;
}
if (now <= last_call + 1) {
/* check every second or so */
return;
}
if (unixpw_in_progress) return;
last_call = now;
if (! screen) {
return;
}
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
#if 0
rbs += cl->rawBytesEquivalent;
#else
rbs += rfbStatGetSentBytesIfRaw(cl);
#endif
}
rfbReleaseClientIterator(iter);
if (rbs != rbs0) {
rbs0 = rbs;
if (debug_tiles > 1) {
fprintf(stderr, "record_last_fb_update: %d %d\n",
(int) now, (int) last_fb_bytes_sent);
}
last_fb_bytes_sent = now;
}
}
static int choose_delay(double dt) {
static double t0 = 0.0, t1 = 0.0, t2 = 0.0, now;
static int x0, y0, x1, y1, x2, y2, first = 1;
int dx0, dy0, dx1, dy1, dm, i, msec = waitms;
double cut1 = 0.15, cut2 = 0.075, cut3 = 0.25;
double bogdown_time = 0.25, bave = 0.0;
int bogdown = 1, bcnt = 0;
int ndt = 8, nave = 3;
double fac = 1.0;
int db = 0;
static double dts[8];
if (waitms == 0) {
return waitms;
}
if (nofb) {
return waitms;
}
if (first) {
for(i=0; i<ndt; i++) {
dts[i] = 0.0;
}
first = 0;
}
now = dnow();
/*
* first check for bogdown, e.g. lots of activity, scrolling text
* from command output, etc.
*/
if (nap_ok) {
dt = 0.0;
}
if (! wait_bog) {
bogdown = 0;
} else if (button_mask || now < last_keyboard_time + 2*bogdown_time) {
/*
* let scrolls & keyboard input through the normal way
* otherwise, it will likely just annoy them.
*/
bogdown = 0;
} else if (dt > 0.0) {
/*
* inspect recent dt's:
* 0 1 2 3 4 5 6 7 dt
* ^ ^ ^
*/
for (i = ndt - (nave - 1); i < ndt; i++) {
bave += dts[i];
bcnt++;
if (dts[i] < bogdown_time) {
bogdown = 0;
break;
}
}
bave += dt;
bcnt++;
bave = bave / bcnt;
if (dt < bogdown_time) {
bogdown = 0;
}
} else {
bogdown = 0;
}
/* shift for next time */
for (i = 0; i < ndt-1; i++) {
dts[i] = dts[i+1];
}
dts[ndt-1] = dt;
if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnowx());
if (bogdown) {
if (use_xdamage) {
/* DAMAGE can queue ~1000 rectangles for a scroll */
clear_xdamage_mark_region(NULL, 0);
}
msec = (int) (1000 * 1.75 * bave);
if (dts[ndt - nave - 1] > 0.75 * bave) {
msec = 1.5 * msec;
set_xdamage_mark(0, 0, dpy_x, dpy_y);
}
if (msec > 1500) {
msec = 1500;
}
if (msec < waitms) {
msec = waitms;
}
db = (db || debug_tiles);
if (db) fprintf(stderr, "bogg[%d] %.3f %.3f %.3f %.3f\n",
msec, dts[ndt-4], dts[ndt-3], dts[ndt-2], dts[ndt-1]);
return msec;
}
/* next check for pointer motion, keystrokes, to speed up */
t2 = dnow();
x2 = cursor_x;
y2 = cursor_y;
dx0 = nabs(x1 - x0);
dy0 = nabs(y1 - y0);
dx1 = nabs(x2 - x1);
dy1 = nabs(y2 - y1);
if (dx1 > dy1) {
dm = dx1;
} else {
dm = dy1;
}
if ((dx0 || dy0) && (dx1 || dy1)) {
if (t2 < t0 + cut1 || t2 < t1 + cut2 || dm > 20) {
fac = wait_ui * 1.25;
}
} else if ((dx1 || dy1) && dm > 40) {
fac = wait_ui;
}
if (fac == 1 && t2 < last_keyboard_time + cut3) {
fac = wait_ui;
}
msec = (int) ((double) waitms / fac);
if (msec == 0) {
msec = 1;
}
x0 = x1;
y0 = y1;
t0 = t1;
x1 = x2;
y1 = y2;
t1 = t2;
return msec;
}
/*
* main x11vnc loop: polls, checks for events, iterate libvncserver, etc.
*/
void watch_loop(void) {
int cnt = 0, tile_diffs = 0, skip_pe = 0;
double tm, dtr, dt = 0.0;
time_t start = time(NULL);
if (use_threads) {
rfbRunEventLoop(screen, -1, TRUE);
}
while (1) {
char msg[] = "new client: %s taking unixpw client off hold.\n";
got_user_input = 0;
got_pointer_input = 0;
got_local_pointer_input = 0;
got_pointer_calls = 0;
got_keyboard_input = 0;
got_keyboard_calls = 0;
urgent_update = 0;
x11vnc_current = dnow();
if (! use_threads) {
dtime0(&tm);
if (! skip_pe) {
if (unixpw_in_progress) {
rfbClientPtr cl = unixpw_client;
if (cl && cl->onHold) {
rfbLog(msg, cl->host);
unixpw_client->onHold = FALSE;
}
} else {
measure_send_rates(1);
}
unixpw_in_rfbPE = 1;
/*
* do a few more since a key press may
* have induced a small change we want to
* see quickly (just 1 rfbPE will likely
* only process the subsequent "up" event)
*/
if (tm < last_keyboard_time + 0.16) {
rfbPE(0);
rfbPE(0);
rfbPE(-1);
rfbPE(0);
rfbPE(0);
} else {
rfbPE(-1);
}
unixpw_in_rfbPE = 0;
if (unixpw_in_progress) {
/* rfbPE loop until logged in. */
skip_pe = 0;
check_new_clients();
continue;
} else {
measure_send_rates(0);
fb_update_sent(NULL);
}
} else {
if (unixpw_in_progress) {
skip_pe = 0;
check_new_clients();
continue;
}
}
dtr = dtime(&tm);
if (! cursor_shape_updates) {
/* undo any cursor shape requests */
disable_cursor_shape_updates(screen);
}
if (screen && screen->clientHead) {
int ret = check_user_input(dt, dtr,
tile_diffs, &cnt);
/* true: loop back for more input */
if (ret == 2) {
skip_pe = 1;
}
if (ret) {
if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
continue;
}
}
/* watch for viewonly input piling up: */
if ((got_pointer_calls > got_pointer_input) ||
(got_keyboard_calls > got_keyboard_input)) {
eat_viewonly_input(10, 3);
}
} else {
/* -threads here. */
if (wireframe && button_mask) {
check_wireframe();
}
}
skip_pe = 0;
if (shut_down) {
clean_up_exit(0);
}
if (unixpw_in_progress) {
check_new_clients();
continue;
}
if (! urgent_update) {
if (do_copy_screen) {
do_copy_screen = 0;
copy_screen();
}
check_new_clients();
check_ncache(0, 0);
check_xevents(0);
check_autorepeat();
check_pm();
check_filexfer();
check_keycode_state();
check_connect_inputs();
check_gui_inputs();
check_stunnel();
check_openssl();
check_https();
record_last_fb_update();
check_padded_fb();
check_fixscreen();
check_xdamage_state();
check_xrecord_reset(0);
check_add_keysyms();
check_new_passwds(0);
#ifdef ENABLE_GRABLOCAL
if (grab_local) {
check_local_grab();
}
#endif
if (started_as_root) {
check_switched_user();
}
if (first_conn_timeout < 0) {
start = time(NULL);
first_conn_timeout = -first_conn_timeout;
}
}
if (rawfb_vnc_reflect) {
static time_t lastone = 0;
if (time(NULL) > lastone + 10) {
lastone = time(NULL);
vnc_reflect_process_client();
}
}
if (! screen || ! screen->clientHead) {
/* waiting for a client */
if (first_conn_timeout) {
if (time(NULL) - start > first_conn_timeout) {
rfbLog("No client after %d secs.\n",
first_conn_timeout);
shut_down = 1;
}
}
usleep(200 * 1000);
continue;
}
if (first_conn_timeout && all_clients_initialized()) {
first_conn_timeout = 0;
}
if (nofb) {
/* no framebuffer polling needed */
if (cursor_pos_updates) {
check_x11_pointer();
}
#ifdef MACOSX
else check_x11_pointer();
#endif
continue;
}
if (button_mask && (!show_dragging || pointer_mode == 0)) {
/*
* if any button is pressed in this mode do
* not update rfb screen, but do flush the
* X11 display.
*/
X_LOCK;
XFlush_wr(dpy);
X_UNLOCK;
dt = 0.0;
} else {
static double last_dt = 0.0;
double xdamage_thrash = 0.4;
check_cursor_changes();
/* for timing the scan to try to detect thrashing */
if (use_xdamage && last_dt > xdamage_thrash) {
clear_xdamage_mark_region(NULL, 0);
}
if (unixpw_in_progress) continue;
if (rawfb_vnc_reflect) {
vnc_reflect_process_client();
}
dtime0(&tm);
#if !NO_X11
if (xrandr_present && !xrandr && xrandr_maybe) {
int delay = 180;
/* there may be xrandr right after xsession start */
if (tm < x11vnc_start + delay || tm < last_client + delay) {
int tw = 20;
if (auth_file != NULL) {
tw = 120;
}
X_LOCK;
if (tm < x11vnc_start + tw || tm < last_client + tw) {
XSync(dpy, False);
} else {
XFlush_wr(dpy);
}
X_UNLOCK;
}
check_xrandr_event("before-scan");
}
#endif
if (use_snapfb) {
int t, tries = 3;
copy_snap();
for (t=0; t < tries; t++) {
tile_diffs = scan_for_updates(0);
}
} else {
tile_diffs = scan_for_updates(0);
}
dt = dtime(&tm);
if (! nap_ok) {
last_dt = dt;
}
if ((debug_tiles || debug_scroll > 1 || debug_wireframe > 1)
&& (tile_diffs > 4 || debug_tiles > 1)) {
double rate = (tile_x * tile_y * bpp/8 * tile_diffs) / dt;
fprintf(stderr, "============================= TILES: %d dt: %.4f"
" t: %.4f %.2f MB/s nap_ok: %d\n", tile_diffs, dt,
tm - x11vnc_start, rate/1000000.0, nap_ok);
}
}
/* sleep a bit to lessen load */
if (! urgent_update) {
int wait = choose_delay(dt);
if (wait > 2*waitms) {
/* bog case, break it up */
nap_sleep(wait, 10);
} else {
usleep(wait * 1000);
}
}
cnt++;
}
}

@ -15,8 +15,8 @@ extern void check_padded_fb(void);
extern void install_padded_fb(char *geom);
extern XImage *initialize_xdisplay_fb(void);
extern XImage *initialize_raw_fb(int);
extern void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom);
extern void parse_scale_string(char *str, double *factor_x, double *factor_y, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom, int w_in, int h_in);
extern int parse_rotate_string(char *str, int *mode);
extern int scale_round(int len, double fac);
extern void initialize_screen(int *argc, char **argv, XImage *fb);

@ -128,6 +128,11 @@ Clients
tightfilexfer
ultrafilexfer
proxy:
=GAL Chat::
chatwindow
=DRA chaton
=DRA chatoff
=GAL LOFF
=GAL Java-applet::
=D http
httpdir:
@ -1061,6 +1066,12 @@ The default port listened on is 5800, so the URL is typically:
http://hostname:5800/
but this can be altered by -httpport, etc.
"
set helptext(Chat:) "
In this sub-menu are some options for enabling a local chat window
and starting or stopping the current chat. This is the UltraVNC
Text Chat support in x11vnc.
"
set helptext(ScrollCopyRect:) "

@ -139,6 +139,11 @@ char gui_code[] = "";
" tightfilexfer\n"
" ultrafilexfer\n"
" proxy:\n"
" =GAL Chat::\n"
" chatwindow\n"
" =DRA chaton\n"
" =DRA chatoff\n"
" =GAL LOFF\n"
" =GAL Java-applet::\n"
" =D http\n"
" httpdir:\n"
@ -1074,6 +1079,12 @@ char gui_code[] = "";
"but this can be altered by -httpport, etc.\n"
"\"\n"
"\n"
" set helptext(Chat:) \"\n"
"In this sub-menu are some options for enabling a local chat window\n"
"and starting or stopping the current chat. This is the UltraVNC \n"
"Text Chat support in x11vnc.\n"
"\"\n"
"\n"
" set helptext(ScrollCopyRect:) \"\n"
"This sub-menu has some options for the x11vnc Scroll detection and\n"
"CopyRect speedup scheme.\n"

@ -155,8 +155,8 @@ void unixpw_screen(int init) {
y = dpy_y / 4;
if (scaling) {
x = (int) (x * scale_fac);
y = (int) (y * scale_fac);
x = (int) (x * scale_fac_x);
y = (int) (y * scale_fac_y);
x = nfix(x, scaled_x);
y = nfix(y, scaled_y);
}
@ -1231,10 +1231,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x = text_x();
y = text_y();
if (scaling) {
int x2 = x / scale_fac;
int y2 = y / scale_fac;
int w2 = char_w / scale_fac;
int h2 = char_h / scale_fac;
int x2 = x / scale_fac_x;
int y2 = y / scale_fac_y;
int w2 = char_w / scale_fac_x;
int h2 = char_h / scale_fac_y;
x2 = nfix(x2, dpy_x);
y2 = nfix(y2, dpy_y);

@ -1189,6 +1189,7 @@ void user_supplied_opts(char *opts) {
"geometry", "geom", "ge",
"noncache", "nc",
"nodisplay", "nd",
"viewonly", "vo",
NULL
};
@ -1247,6 +1248,8 @@ void user_supplied_opts(char *opts) {
if (!solid_str) {
solid_str = strdup(solid_default);
}
} else if (!strcmp(p, "viewonly") || !strcmp(p, "vo")) {
view_only = 1;
} else if (strstr(p, "solid=") == p ||
strstr(p, "so=") == p) {
use_solid_bg = 1;
@ -1826,6 +1829,7 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
char fdgeom[128], fdsess[128], fdopts[128], fdprog[128];
char fdxsrv[128], fdxdum[128], fdcups[128], fdesd[128];
char fdnas[128], fdsmb[128], fdtag[128];
char cdout[128];
if (opts) {
opts++;
@ -1847,6 +1851,7 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
fdnas[0] = '\0';
fdsmb[0] = '\0';
fdtag[0] = '\0';
cdout[0] = '\0';
if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') {
char *q, *p, *t = strdup(keep_unixpw_opts);
@ -1955,6 +1960,9 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
if (fdxdum[0] == '\0' && getenv("FD_XDUMMY_NOROOT")) {
snprintf(fdxdum, 120, "%s", getenv("FD_XDUMMY_NOROOT"));
}
if (getenv("CREATE_DISPLAY_OUTPUT")) {
snprintf(cdout, 120, "CREATE_DISPLAY_OUTPUT='%s'", getenv("CREATE_DISPLAY_OUTPUT"));
}
set_env("FD_GEOM", fdgeom);
set_env("FD_OPTS", fdopts);
@ -1998,13 +2006,14 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
+ strlen(fdtag) + 1
+ strlen(fdxdum) + 1
+ strlen(fdsess) + 1
+ strlen(cdout) + 1
+ strlen(opts) + 1);
sprintf(create_cmd, "env USER='%s' FD_GEOM='%s' FD_SESS='%s' "
"FD_OPTS='%s' FD_PROG='%s' FD_XSRV='%s' FD_CUPS='%s' "
"FD_ESD='%s' FD_NAS='%s' FD_SMB='%s' FD_TAG='%s' "
"FD_XDUMMY_NOROOT='%s' /bin/sh %s %s",
"FD_XDUMMY_NOROOT='%s' %s /bin/sh %s %s",
uu, fdgeom, fdsess, fdopts, fdprog, fdxsrv,
fdcups, fdesd, fdnas, fdsmb, fdtag, fdxdum, tmp, opts);
fdcups, fdesd, fdnas, fdsmb, fdtag, fdxdum, cdout, tmp, opts);
} else {
create_cmd = (char *) malloc(strlen(tmp)
+ strlen("/bin/sh ") + 1 + strlen(opts) + 1);
@ -2158,6 +2167,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
if (!strcmp(cmd, "FINDDISPLAY") ||
strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
char *nd = "";
char fdout[128];
tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) {
rfbLog("wait_for_client: open failed: %s\n", tmp);
@ -2183,9 +2193,14 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
}
check_nodisplay(&nd);
fdout[0] = '\0';
if (getenv("FIND_DISPLAY_OUTPUT")) {
snprintf(fdout, 120, " FIND_DISPLAY_OUTPUT='%s' ", getenv("FIND_DISPLAY_OUTPUT"));
}
cmd = (char *) malloc(strlen("env X11VNC_SKIP_DISPLAY='' ")
+ strlen(nd) + strlen(tmp) + strlen("/bin/sh ") + 1);
sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' /bin/sh %s", nd, tmp);
+ strlen(nd) + strlen(tmp) + strlen("/bin/sh ") + strlen(fdout) + 1);
sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' %s /bin/sh %s", nd, fdout, tmp);
}
rfbLog("wait_for_client: running: %s\n", cmd);

@ -8116,7 +8116,7 @@ void scale_mark_xrootpmap(void) {
dst_fb = rfb_fb;
dst_bpl = rfb_bytes_per_line;
scale_rect(scale_fac, scaling_blend, scaling_interpolate, fac * Bpp,
scale_rect(scale_fac_x, scale_fac_y, scaling_blend, scaling_interpolate, fac * Bpp,
src_fb, fac * main_bytes_per_line, dst_fb, dst_bpl, dpy_x, yfac * dpy_y,
scaled_x, yfac * scaled_y, 0, yn, dpy_x, yn + dpy_y, mark);
}

@ -1,8 +1,8 @@
.\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "September 2008" "x11vnc " "User Commands"
.TH X11VNC "1" "October 2008" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.9.5, lastmod: 2008-09-21
version: 0.9.5, lastmod: 2008-10-18
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@ -336,6 +336,10 @@ is taken as a floating point number, alternatively
the notation "m/n" may be used to denote fractions
exactly, e.g. \fB-scale\fR 2/3
.IP
To scale asymmetrically in the horizontal and vertical
directions, specify a WxH geometry to stretch to:
e.g. '-scale 1024x768', or also '-scale 0.9x0.75'
.IP
Scaling Options: can be added after \fIfraction\fR via
":", to supply multiple ":" options use commas.
If you just want a quick, rough scaling without
@ -356,6 +360,10 @@ scheme even when shrinking, ":pad" pad scaled width
and height to be multiples of scaling denominator
(e.g. 3 for 2/3).
.PP
\fB-geometry\fR \fIWxH\fR
.IP
Same as \fB-scale\fR WxH
.PP
\fB-scale_cursor\fR \fIfrac\fR
.IP
By default if \fB-scale\fR is supplied the cursor shape is
@ -1953,9 +1961,9 @@ to tunnelling with the symmetric cipher (an unfortunate
choice of implementation).
.IP
cipher can be one of: arc4, aesv2, aes-cfb, blowfish,
or 3des. See the OpenSSL documentation for more info.
The keysize is 128 bits. Here is one way to make a
keyfile with that many bits:
aes256, or 3des. See the OpenSSL documentation for
more info. The keysize is 128 bits (except for aes256).
Here is one way to make a keyfile with that many bits:
.IP
dd if=/dev/random of=./my.key bs=16 count=1
.IP
@ -1994,6 +2002,18 @@ It is not a good idea to set either one to zero,
although you may be forced to if the other side of the
tunnel is not under your control.
.IP
To skip the salt and EVP_BytesToKey MD5 entirely (no
hashing is done: the keydata is directly inserted into
the cipher) specify "-1" for the salt, e.g.
.IP
\fB-enc\fR blowfish@-1,16:./my.key
.IP
The message digest can also be changed to something
besides the default MD5. Use cipher@md+n,m where "md"
can be one of sha, sha1, md5, or ripe. For example:
.IP
\fB-enc\fR arc4@sha+8,16:./my.key
.IP
The SSVNC vnc viewer project supplies a symmetric
encryption tool named "ultravnc_dsm_helper" that can
be used on the viewer side. For example:
@ -2003,16 +2023,22 @@ ssvncviewer exec='ultravnc_dsm_helper arc4 my.key 0 h:p'
where h:p is the hostname and port of the x11vnc server.
ultravnc_dsm_helper may also be used standalone to
provide a symmetric encryption tunnel for any viewer
or server (VNC or otherwise.)
or server (VNC or otherwise.) The cipher (1st arg)
is basically the same syntax as we use above.
.IP
Also see the 'Non-Ultra DSM' SSVNC option for the
\'UltraVNC DSM Encryption Plugin' advanced option.
.IP
For both ways of using the viewer, you can specify the
salt,ivec sizes (in GUI or, e.g. arc4@8,16).
.PP
\fB-https\fR \fI[port]\fR
.IP
Choose a separate HTTPS port (-ssl mode only).
Use a special, separate HTTPS port (-ssl mode only)
for HTTPS Java viewer applet downloading. I.e. not 5900
and not 5800 (the defaults.)
.IP
In \fB-ssl\fR mode, it turns out you can use the
BACKGROUND: In \fB-ssl\fR mode, it turns out you can use the
single VNC port (e.g. 5900) for both VNC and HTTPS
connections. (HTTPS is used to retrieve a SSL-aware
VncViewer.jar applet that is provided with x11vnc).
@ -2030,14 +2056,15 @@ ponder the Certificate dialogs in his browser, Java VM,
or VNC Viewer applet. That's right 3 separate "Are
you sure you want to connect?" dialogs!)
.IP
So use the \fB-https\fR option to provide a separate, more
reliable HTTPS port that x11vnc will listen on. If
USAGE: So use the \fB-https\fR option to provide a separate,
more reliable HTTPS port that x11vnc will listen on. If
[port] is not provided (or is 0), one is autoselected.
The URL to use is printed out at startup.
.IP
The SSL Java applet directory is specified via the
\fB-httpdir\fR option. If not supplied it will try to guess
the directory as though the \fB-http\fR option was supplied.
\fB-httpdir\fR option. If not supplied, \fB-https\fR will try
to guess the directory as though the \fB-http\fR option
was supplied.
.PP
\fB-httpsredir\fR \fI[port]\fR
.IP
@ -3805,6 +3832,27 @@ Disable the following UltraVNC extensions: SingleWindow
and ServerInput. The others managed by libvncserver
(textchat, 1/n scaling, rfbEncodingUltra) are not.
.PP
\fB-chatwindow\fR
.IP
Place a local UltraVNC chat window on the X11 display
that x11vnc is polling. That way the person on the VNC
viewer-side can chat with the person at the physical
X11 console. (e.g. helpdesk w/o telephone)
.IP
For this to work the SSVNC package (version 1.0.21 or
later) MUST BE installed on the system where x11vnc runs
and the 'ssvnc' command must be available in $PATH.
The ssvncviewer is used as a chat window helper.
See http://www.karlrunge.com/x11vnc/ssvnc.html
.IP
This option implies '-rfbversion 3.6' so as to trick
UltraVNC viewers, otherwise they assume chat is not
available. To specify a different rfbversion, place
it after the \fB-chatwindow\fR option on the cmdline.
.IP
See also the remote control 'chaton' and 'chatoff'
actions. These can also be set from the tkx11vnc GUI.
.PP
\fB-noxdamage\fR
.IP
Do not use the X DAMAGE extension to detect framebuffer
@ -5004,6 +5052,14 @@ noultraext enable \fB-noultraext\fR mode.
.IP
ultraext disable \fB-noultraext\fR mode.
.IP
chatwindow enable local chatwindow mode.
.IP
nochatwindow disable local chatwindow mode.
.IP
chaton begin chat using local window.
.IP
chatoff end chat using local window.
.IP
xdamage enable xdamage polling hints.
.IP
noxdamage disable xdamage polling hints.
@ -5213,16 +5269,17 @@ nowireframe nowf wireframelocal wfl nowireframelocal
nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area
scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode pm
input_skip allinput noallinput input grabkbd nograbkbd
grabptr nograbptr grabalways nograbalways grablocal
client_input ssltimeout speeds wmdt debug_pointer dp
nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
nodk keycode deferupdate defer wait_ui wait_bog
nowait_bog slow_fb xrefresh wait readtimeout nap nonap
sb screen_blank fbpm nofbpm dpms nodpms clientdpms
noclientdpms forcedpms noforcedpms noserverdpms
serverdpms noultraext ultraext fs gaps grow fuzz snapfb
fixscreen noxrecord xrecord reset_record pointer_mode
pm input_skip allinput noallinput input grabkbd
nograbkbd grabptr nograbptr grabalways nograbalways
grablocal client_input ssltimeout speeds wmdt
debug_pointer dp nodebug_pointer nodp debug_keyboard
dk nodebug_keyboard nodk keycode deferupdate defer
wait_ui wait_bog nowait_bog slow_fb xrefresh wait
readtimeout nap nonap sb screen_blank fbpm nofbpm dpms
nodpms clientdpms noclientdpms forcedpms noforcedpms
noserverdpms serverdpms noultraext ultraext chatwindow
nochatwindow chaton chatoff fs gaps grow fuzz snapfb
nosnapfb rawfb uinput_accel uinput_thresh uinput_reset
uinput_always progressive rfbport http nohttp httpport
httpdir enablehttpproxy noenablehttpproxy alwaysshared
@ -5239,9 +5296,9 @@ macnoresize macresize nomacnoresize maciconanim macmenu
macnomenu nomacmenu macuskbd nomacuskbd noremote
.IP
aro= noop display vncdisplay desktopname guess_desktop
http_url auth xauth users rootshift clipshift
scale_str scaled_x scaled_y scale_numer scale_denom
scale_fac scaling_blend scaling_nomult4 scaling_pad
http_url auth xauth users rootshift clipshift scale_str
scaled_x scaled_y scale_numer scale_denom scale_fac_x
scale_fac_y scaling_blend scaling_nomult4 scaling_pad
scaling_interpolate inetd privremote unsafe safer
nocmds passwdfile unixpw unixpw_nis unixpw_list ssl
ssl_pem sslverify stunnel stunnel_pem https httpsredir

File diff suppressed because it is too large Load Diff

@ -423,7 +423,8 @@ extern int raw_fb_bytes_per_line; /* of actual raw region we poll, not our raw_f
/* scaling parameters */
extern char *scale_str;
extern double scale_fac;
extern double scale_fac_x;
extern double scale_fac_y;
extern int scaling;
extern int scaling_blend; /* for no blending option (very course) */
extern int scaling_nomult4; /* do not require width = n * 4 */
@ -438,7 +439,8 @@ extern int rotating_cursors;
/* scale cursor */
extern char *scale_cursor_str;
extern double scale_cursor_fac;
extern double scale_cursor_fac_x;
extern double scale_cursor_fac_y;
extern int scaling_cursor;
extern int scaling_cursor_blend;
extern int scaling_cursor_interpolate;

@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.5 lastmod: 2008-09-21";
char lastmod[] = "0.9.5 lastmod: 2008-10-18";
/* X display info */
@ -86,7 +86,8 @@ int raw_fb_bytes_per_line = 0;
/* scaling parameters */
char *scale_str = NULL;
double scale_fac = 1.0;
double scale_fac_x = 1.0;
double scale_fac_y = 1.0;
int scaling = 0;
int scaling_blend = 1; /* for no blending option (very course) */
int scaling_nomult4 = 0; /* do not require width = n * 4 */
@ -101,7 +102,8 @@ int rotating_cursors = 0;
/* scale cursor */
char *scale_cursor_str = NULL;
double scale_cursor_fac = 1.0;
double scale_cursor_fac_x = 1.0;
double scale_cursor_fac_y = 1.0;
int scaling_cursor = 0;
int scaling_cursor_blend = 1;
int scaling_cursor_interpolate = 0;

@ -1494,27 +1494,137 @@ void set_server_input(rfbClientPtr cl, int grab) {
#endif
}
static int wsock_timeout_sock = -1;
static void wsock_timeout (int sig) {
rfbLog("sig: %d, wsock_timeout.\n", sig);
if (wsock_timeout_sock >= 0) {
close(wsock_timeout_sock);
wsock_timeout_sock = -1;
}
}
static void try_local_chat_window(void) {
int i, port, lsock;
char cmd[100];
struct sockaddr_in addr;
#ifdef __hpux
int addrlen = sizeof(addr);
#else
socklen_t addrlen = sizeof(addr);
#endif
for (i = 0; i < 90; i++) {
/* find an open port */
port = 7300 + i;
lsock = rfbListenOnTCPPort(port, htonl(INADDR_LOOPBACK));
if (lsock >= 0) {
break;
}
port = 0;
}
if (port == 0) {
return;
}
/* have ssvncvncviewer connect back to us (n.b. sockpair fails) */
sprintf(cmd, "ssvnc -cmd VNC://localhost:%d -chatonly", port);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return;
} else if (pid == 0) {
char *args[4];
int d;
args[0] = "/bin/sh";
args[1] = "-c";
/* "ssvnc -cmd VNC://fd=0 -chatonly"; */
args[2] = cmd;
args[3] = NULL;
for (d = 3; d < 256; d++) {
close(d);
}
set_env("VNCVIEWER_PASSWORD", "moo");
execvp(args[0], args);
perror("exec");
exit(1);
} else {
int i, sock = -1;
rfbNewClientHookPtr new_save;
signal(SIGALRM, wsock_timeout);
wsock_timeout_sock = lsock;
alarm(10);
sock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
alarm(0);
signal(SIGALRM, SIG_DFL);
close(lsock);
if (sock < 0) {
return;
}
new_save = screen->newClientHook;
screen->newClientHook = new_client_chat_helper;
chat_window_client = rfbNewClient(screen, sock);
screen->newClientHook = new_save;
if (chat_window_client != NULL) {
rfbPasswordCheckProcPtr pwchk_save = screen->passwordCheck;
rfbBool save_shared1 = screen->alwaysShared;
rfbBool save_shared2 = screen->neverShared;
screen->alwaysShared = TRUE;
screen->neverShared = FALSE;
screen->passwordCheck = password_check_chat_helper;
for (i=0; i<30; i++) {
rfbPE(-1);
if (!chat_window_client) {
break;
}
if (chat_window_client->state == RFB_NORMAL) {
break;
}
}
screen->passwordCheck = pwchk_save;
screen->alwaysShared = save_shared1;
screen->neverShared = save_shared2;
}
}
}
void set_text_chat(rfbClientPtr cl, int len, char *txt) {
int dochat = 1;
rfbClientIteratorPtr iter;
rfbClientPtr cl2;
unsigned int ulen = (unsigned int) len;
if (no_ultra_ext || ! dochat) {
return;
}
#if 0
rfbLog("set_text_chat: len=%d\n", len);
rfbLog("set_text_chat: len=0x%x txt='", len);
if (0 < len && len < 10000) write(2, txt, len);
fprintf(stderr, "'\n");
#endif
if (unixpw_in_progress) {
rfbLog("set_text_chat: unixpw_in_progress, dropping client.\n");
rfbCloseClient(cl);
return;
}
if (chat_window && chat_window_client == NULL && ulen == rfbTextChatOpen) {
try_local_chat_window();
}
saw_ultra_chat = 1;
iter = rfbGetClientIterator(screen);
@ -1523,10 +1633,15 @@ void set_text_chat(rfbClientPtr cl, int len, char *txt) {
if (cl2 == cl) {
continue;
}
if (cl2->state != RFB_NORMAL) {
continue;
}
if (ulen == rfbTextChatOpen) {
rfbSendTextChatMessage(cl2, rfbTextChatOpen, "");
} else if (ulen == rfbTextChatClose) {
rfbSendTextChatMessage(cl2, rfbTextChatClose, "");
/* not clear what is going on WRT close and finished... */
rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
} else if (ulen == rfbTextChatFinished) {
rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
} else if (len <= rfbTextMaxSize) {
@ -1534,6 +1649,11 @@ void set_text_chat(rfbClientPtr cl, int len, char *txt) {
}
}
rfbReleaseClientIterator(iter);
if (ulen == rfbTextChatClose && cl != NULL) {
/* not clear what is going on WRT close and finished... */
rfbSendTextChatMessage(cl, rfbTextChatFinished, "");
}
}
int get_keyboard_led_state_hook(rfbScreenInfoPtr s) {

@ -162,6 +162,8 @@ int check_xrandr_event(char *msg) {
if (! xrandr && ! xrandr_maybe) {
return 0;
}
if (xrandr_base_event_type && XCheckTypedEvent(dpy,
xrandr_base_event_type + RRScreenChangeNotify, &xev)) {
int do_change, qout = 0;
@ -172,8 +174,10 @@ int check_xrandr_event(char *msg) {
if (first && ! xrandr) {
fprintf(stderr, "\n");
if (getenv("X11VNC_DEBUG_XRANDR") == NULL) {
qout = 1;
}
}
first = 0;
rfbLog("check_xrandr_event():\n");
@ -230,11 +234,15 @@ int check_xrandr_event(char *msg) {
XDisplayWidth(dpy, scr), XDisplayHeight(dpy, scr));
rfbLog("check_xrandr_event(): returning control to"
" caller...\n");
return do_change;
}
#else
xev.type = 0;
#endif
return 0;
}

@ -52,6 +52,7 @@ extern int known_xrandr_mode(char *s);
} \
trapped_getimage_xerror = 0; \
XSetErrorHandler(old_getimage_handler); \
XFlush_wr(dpy); \
check_xrandr_event(y); \
X_UNLOCK; \
return(x); \

@ -9,6 +9,7 @@
#include "macosx.h"
int xshm_present = 0;
int xshm_opcode = 0;
int xtest_present = 0;
int xtrap_present = 0;
int xrecord_present = 0;
@ -32,6 +33,7 @@ XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth,
Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
Bool XShmQueryExtension_wr(Display *disp);
int XShmGetEventBase_wr(Display *disp);
XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
unsigned int width, unsigned int height, Bool show_cursor);
@ -203,6 +205,15 @@ Bool XShmQueryExtension_wr(Display *disp) {
#endif
}
int XShmGetEventBase_wr(Display *disp) {
#if LIBVNCSERVER_HAVE_XSHM
return XShmGetEventBase(disp);
#else
if (!disp) {}
return 0;
#endif
}
/* wrapper for overlay screen reading: */
XImage *xreadscreen(Display *disp, Drawable d, int x, int y,

@ -4,6 +4,7 @@
/* -- xwrappers.h -- */
extern int xshm_present;
extern int xshm_opcode;
extern int xtest_present;
extern int xtrap_present;
extern int xrecord_present;
@ -27,6 +28,7 @@ extern XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth
extern Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
extern Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
extern Bool XShmQueryExtension_wr(Display *disp);
extern int XShmGetEventBase_wr(Display *disp);
extern XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
unsigned int width, unsigned int height, Bool show_cursor);

Loading…
Cancel
Save