7
int measure_speeds = 1;
8
int speeds_net_rate = 0;
9
int speeds_net_rate_measured = 0;
10
int speeds_net_latency = 0;
11
int speeds_net_latency_measured = 0;
12
int speeds_read_rate = 0;
13
int speeds_read_rate_measured = 0;
16
int get_cmp_rate(void);
17
int get_raw_rate(void);
18
void initialize_speeds(void);
19
int get_read_rate(void);
20
int link_rate(int *latency, int *netrate);
21
int get_net_rate(void);
22
int get_net_latency(void);
23
void measure_send_rates(int init);
26
static void measure_display_hook(rfbClientPtr cl);
27
static int get_rate(int which);
28
static int get_latency(void);
31
static void measure_display_hook(rfbClientPtr cl) {
32
ClientData *cd = (ClientData *) cl->clientData;
39
static int get_rate(int which) {
40
rfbClientIteratorPtr iter;
42
int irate, irate_min = 1; /* 1 KB/sec */
43
int irate_max = 100000; /* 100 MB/sec */
45
double slowest = -1.0, rate;
46
static double save_rate = 1000 * NETRATE0;
52
iter = rfbGetClientIterator(screen);
53
while( (cl = rfbClientIteratorNext(iter)) ) {
54
ClientData *cd = (ClientData *) cl->clientData;
59
if (cl->state != RFB_NORMAL) {
62
if (cd->send_cmp_rate == 0.0 || cd->send_raw_rate == 0.0) {
68
rate = cd->send_cmp_rate;
70
rate = cd->send_raw_rate;
72
if (slowest == -1.0 || rate < slowest) {
77
rfbReleaseClientIterator(iter);
83
if (slowest == -1.0) {
89
irate = (int) (slowest/1000.0);
90
if (irate < irate_min) {
93
if (irate > irate_max) {
96
if (0) fprintf(stderr, "get_rate(%d) %d %.3f/%.3f\n", which, irate, save_rate, slowest);
101
static int get_latency(void) {
102
rfbClientIteratorPtr iter;
104
int ilat, ilat_min = 1; /* 1 ms */
105
int ilat_max = 2000; /* 2 sec */
106
double slowest = -1.0, lat;
107
static double save_lat = ((double) LATENCY0)/1000.0;
114
iter = rfbGetClientIterator(screen);
115
while( (cl = rfbClientIteratorNext(iter)) ) {
116
ClientData *cd = (ClientData *) cl->clientData;
121
if (cl->state != RFB_NORMAL) {
124
if (cd->latency == 0.0) {
130
if (slowest == -1.0 || lat > slowest) {
134
rfbReleaseClientIterator(iter);
140
if (slowest == -1.0) {
146
ilat = (int) (slowest * 1000.0);
147
if (ilat < ilat_min) {
150
if (ilat > ilat_max) {
157
int get_cmp_rate(void) {
161
int get_raw_rate(void) {
165
void initialize_speeds(void) {
169
speeds_read_rate = 0;
171
speeds_net_latency = 0;
172
if (! speeds_str || *speeds_str == '\0') {
175
s_in = strdup(speeds_str);
178
if (!strcmp(s_in, "modem")) {
179
s = strdup("6,4,200");
180
} else if (!strcmp(s_in, "dsl")) {
181
s = strdup("6,100,50");
182
} else if (!strcmp(s_in, "lan")) {
183
s = strdup("6,5000,1");
195
speeds_read_rate = (int) 1000000 * val;
197
speeds_net_rate = (int) 1000 * val;
199
speeds_net_latency = (int) val;
203
p = strtok(NULL, ",");
208
if (! speeds_read_rate) {
213
copy_image(fullscreen, 0, 0, 0, 0);
214
n = fullscreen->bytes_per_line * fullscreen->height;
215
} else if (scanline) {
216
copy_image(scanline, 0, 0, 0, 0);
217
n = scanline->bytes_per_line * scanline->height;
221
double rate = ((double) n) / dt;
222
speeds_read_rate_measured = (int) (rate/1000000.0);
223
if (speeds_read_rate_measured < 1) {
224
speeds_read_rate_measured = 1;
226
rfbLog("fb read rate: %d MB/sec\n",
227
speeds_read_rate_measured);
233
int get_read_rate(void) {
234
if (speeds_read_rate) {
235
return speeds_read_rate;
237
if (speeds_read_rate_measured) {
238
return speeds_read_rate_measured;
243
int link_rate(int *latency, int *netrate) {
244
*latency = get_net_latency();
245
*netrate = get_net_rate();
248
if (!strcmp(speeds_str, "modem")) {
250
} else if (!strcmp(speeds_str, "dsl")) {
252
} else if (!strcmp(speeds_str, "lan")) {
257
if (*latency == LATENCY0 && *netrate == NETRATE0) {
259
} else if (*latency > 150 || *netrate < 20) {
261
} else if (*latency > 50 || *netrate < 150) {
263
} else if (*latency < 10 && *netrate > 300) {
270
int get_net_rate(void) {
271
int spm = speeds_net_rate_measured;
272
if (speeds_net_rate) {
273
return speeds_net_rate;
275
if (! spm || spm == NETRATE0) {
276
speeds_net_rate_measured = get_cmp_rate();
278
if (speeds_net_rate_measured) {
279
return speeds_net_rate_measured;
284
int get_net_latency(void) {
285
int spm = speeds_net_latency_measured;
286
if (speeds_net_latency) {
287
return speeds_net_latency;
289
if (! spm || spm == LATENCY0) {
290
speeds_net_latency_measured = get_latency();
292
if (speeds_net_latency_measured) {
293
return speeds_net_latency_measured;
298
void measure_send_rates(int init) {
299
double cmp_rate, raw_rate;
300
static double now, start = 0.0;
301
static rfbDisplayHookPtr orig_display_hook = NULL;
302
double cmp_max = 1.0e+08; /* 100 MB/sec */
303
double cmp_min = 1000.0; /* 9600baud */
304
double lat_max = 5.0; /* 5 sec */
305
double lat_min = .0005; /* 0.5 ms */
306
int min_cmp = 10000, nclients;
307
rfbClientIteratorPtr iter;
308
rfbClientPtr cl0, cl;
309
int msg = 0, clcnt0 = 0, cc;
310
int db = 0, ouch_db = 0, ouch = 0;
312
if (! measure_speeds) {
315
if (speeds_net_rate && speeds_net_latency) {
322
if (! orig_display_hook) {
323
orig_display_hook = screen->displayHook;
331
if (now < last_client_gone+4.0) {
343
iter = rfbGetClientIterator(screen);
344
while( (cl = rfbClientIteratorNext(iter)) ) {
345
ClientData *cd = (ClientData *) cl->clientData;
350
if (cd->send_cmp_rate > 0.0) {
361
rfbReleaseClientIterator(iter);
366
while (cl != NULL && cc++ == 0) {
367
int defer, i, cbs, rbs;
369
double dt, dt1 = 0.0, dt2, dt3;
370
double tm, spin_max = 15.0, spin_lat_max = 1.5;
371
int got_t2 = 0, got_t3 = 0;
372
ClientData *cd = (ClientData *) cl->clientData;
375
for (i=0; i<MAX_ENCODINGS; i++) {
376
cbs += cl->bytesSent[i];
378
rbs = cl->rawBytesEquivalent;
380
cbs = rfbStatGetSentBytes(cl);
381
rbs = rfbStatGetSentBytesIfRaw(cl);
386
if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d "
387
"rbs: %d dt1: %.3f t: %.3f\n", init,
388
(int) sraRgnCountRects(cl->requestedRegion),
389
(int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now);
392
cd->cmp_bytes_sent = cbs;
393
cd->raw_bytes_sent = rbs;
397
/* first part of the bulk transfer of initial screen */
398
dt1 = dtime(&cd->timer);
400
if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d "
401
"rbs: %d dt1: %.3f t: %.3f\n", init,
402
(int) sraRgnCountRects(cl->requestedRegion),
403
(int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now);
409
cbs = cbs - cd->cmp_bytes_sent;
410
rbs = rbs - cd->raw_bytes_sent;
416
if (ouch_db) fprintf(stderr, "START-OUCH: %d\n", client_count);
417
clcnt0 = client_count;
418
#define OUCH ( ouch || (ouch = (!client_count || client_count != clcnt0 || dnow() < last_client_gone+4.0)) )
421
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-A\n");
424
if (sraRgnCountRects(cl->modifiedRegion)) {
426
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-B\n");
430
defer = screen->deferUpdateTime;
431
httpdir = screen->httpDir;
432
screen->deferUpdateTime = 0;
433
screen->httpDir = NULL;
435
/* mark a small rectangle: */
436
mark_rect_as_modified(0, 0, 16, 16, 1);
444
/* try to cut it down to avoid long pauses. */
448
/* when req1 = 1 mod1 == 0, end of 2nd part of bulk transfer */
450
int req0, req1, mod0, mod1;
452
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C1\n");
455
req0 = sraRgnCountRects(cl->requestedRegion);
456
mod0 = sraRgnCountRects(cl->modifiedRegion);
468
if (dt2 > spin_max) {
472
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C2\n");
475
req1 = sraRgnCountRects(cl->requestedRegion);
476
mod1 = sraRgnCountRects(cl->modifiedRegion);
478
if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d "
479
"fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f\n",
480
req0, req1, mod0, mod1,
482
cl->framebufferUpdateMessagesSent,
484
rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate),
487
if (req1 != 0 && mod1 == 0) {
492
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-D\n");
502
* Note: since often select(2) cannot sleep
503
* less than 1/HZ (e.g. 10ms), the resolution
504
* of the latency may be messed up by something
505
* of this order. Effect may occur on both ends,
506
* i.e. the viewer may not respond immediately.
509
for (tr = 0; tr < trm; tr++) {
512
/* mark a 2nd small rectangle: */
513
mark_rect_as_modified(0, 0, 16, 16, 1);
519
* when req1 > 0 and mod1 == 0, we say
520
* that is the "ping" time.
523
int req0, req1, mod0, mod1;
525
req0 = sraRgnCountRects(
526
cl->requestedRegion);
527
mod0 = sraRgnCountRects(
536
/* try to get it all */
540
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-E\n");
546
if (dt3 > spin_lat_max) {
549
req1 = sraRgnCountRects(
550
cl->requestedRegion);
552
mod1 = sraRgnCountRects(
555
if (db) fprintf(stderr, "dt3 calc: num rects req: %d/%d mod: %d/%d "
556
"fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f\n",
557
req0, req1, mod0, mod1,
559
cl->framebufferUpdateMessagesSent,
561
rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate),
565
if (req1 != 0 && mod1 == 0) {
577
} else if (got_t3 == 2) {
581
double rat = dts[1]/dts[2];
582
if (rat > 0.5 && rat < 2.0) {
597
screen->deferUpdateTime = defer;
598
screen->httpDir = httpdir;
600
if (OUCH && ouch_db) fprintf(stderr, "***OUCH-F\n");
606
if (dt3 <= dt2/2.0) {
607
/* guess only 1/2 a ping for reply... */
614
if (cmp_rate > cmp_max) {
617
if (cmp_rate <= cmp_min) {
621
cd->send_cmp_rate = cmp_rate;
622
cd->send_raw_rate = raw_rate;
627
if (dt3 <= lat_min) {
633
rfbLog("client %d network rate %.1f KB/sec (%.1f eff KB/sec)\n",
634
cd->uid, cmp_rate/1000.0, raw_rate/1000.0);
635
rfbLog("client %d latency: %.1f ms\n", cd->uid, 1000.0*dt3);
636
rfbLog("dt1: %.4f, dt2: %.4f dt3: %.4f bytes: %d\n",
642
int link, latency, netrate;
645
link = link_rate(&latency, &netrate);
646
if (link == LR_UNSET) {
648
} else if (link == LR_UNKNOWN) {
650
} else if (link == LR_DIALUP) {
652
} else if (link == LR_BROADBAND) {
653
str = "LR_BROADBAND";
654
} else if (link == LR_LAN) {
657
rfbLog("link_rate: %s - %d ms, %d KB/s\n", str, latency,
663
screen->displayHook = measure_display_hook;
666
screen->displayHook = orig_display_hook;