/* pipe the output to sort|uniq -u and you'll get the errors. */ int main(int argc, char** argv) { sraRegionPtr region, region1, region2; sraRectangleIterator* i; sraRect rect; rfbBool b; region = sraRgnCreateRect(10, 10, 600, 300); region1 = sraRgnCreateRect(40, 50, 350, 200); region2 = sraRgnCreateRect(0, 0, 20, 40); sraRgnPrint(region); printf("\n[(10-300)[(10-600)]]\n\n"); b = sraRgnSubtract(region, region1); printf("%s ",b?"true":"false"); sraRgnPrint(region); printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n"); sraRgnOr(region, region2); printf("%ld\n6\n\n", sraRgnCountRects(region)); i = sraRgnGetIterator(region); while(sraRgnIteratorNext(i, &rect)) printf("%dx%d+%d+%d ", rect.x2-rect.x1,rect.y2-rect.y1, rect.x1,rect.y1); sraRgnReleaseIterator(i); printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n"); i = sraRgnGetReverseIterator(region,1,0); while(sraRgnIteratorNext(i, &rect)) printf("%dx%d+%d+%d ", rect.x2-rect.x1,rect.y2-rect.y1, rect.x1,rect.y1); sraRgnReleaseIterator(i); printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n"); i = sraRgnGetReverseIterator(region,1,1); while(sraRgnIteratorNext(i, &rect)) printf("%dx%d+%d+%d ", rect.x2-rect.x1,rect.y2-rect.y1, rect.x1,rect.y1); sraRgnReleaseIterator(i); printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n"); sraRgnDestroy(region); sraRgnDestroy(region1); sraRgnDestroy(region2); return(0); }
void measure_send_rates(int init) { double cmp_rate, raw_rate; static double now, start = 0.0; static rfbDisplayHookPtr orig_display_hook = NULL; double cmp_max = 1.0e+08; /* 100 MB/sec */ double cmp_min = 1000.0; /* 9600baud */ double lat_max = 5.0; /* 5 sec */ double lat_min = .0005; /* 0.5 ms */ int min_cmp = 10000, nclients; rfbClientIteratorPtr iter; rfbClientPtr cl0, cl; int msg = 0, clcnt0 = 0, cc; int db = 0, ouch_db = 0, ouch = 0; if (! measure_speeds) { return; } if (speeds_net_rate && speeds_net_latency) { return; } if (!client_count) { return; } if (! orig_display_hook) { orig_display_hook = screen->displayHook; } if (start == 0.0) { dtime(&start); } dtime0(&now); if (now < last_client_gone+4.0) { return; } now = now - start; nclients = 0; if (!screen) { return; } cl0 = NULL; iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { ClientData *cd = (ClientData *) cl->clientData; if (! cd) { continue; } if (cd->send_cmp_rate > 0.0) { continue; } if (cl->onHold) { continue; } nclients++; if (cl0 == NULL) { cl0 = cl; } } rfbReleaseClientIterator(iter); cl = cl0; cc = 0; while (cl != NULL && cc++ == 0) { int defer, i, cbs, rbs; char *httpdir; double dt, dt1 = 0.0, dt2, dt3; double tm, spin_max = 15.0, spin_lat_max = 1.5; int got_t2 = 0, got_t3 = 0; ClientData *cd = (ClientData *) cl->clientData; #if 0 for (i=0; i<MAX_ENCODINGS; i++) { cbs += cl->bytesSent[i]; } rbs = cl->rawBytesEquivalent; #else #if LIBVNCSERVER_HAS_STATS cbs = rfbStatGetSentBytes(cl); rbs = rfbStatGetSentBytesIfRaw(cl); #endif #endif if (init) { if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d " "rbs: %d dt1: %.3f t: %.3f\n", init, (int) sraRgnCountRects(cl->requestedRegion), (int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now); cd->timer = dnow(); cd->cmp_bytes_sent = cbs; cd->raw_bytes_sent = rbs; continue; } /* first part of the bulk transfer of initial screen */ dt1 = dtime(&cd->timer); if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d " "rbs: %d dt1: %.3f t: %.3f\n", init, (int) sraRgnCountRects(cl->requestedRegion), (int) sraRgnCountRects(cl->modifiedRegion), cbs, rbs, dt1, now); if (dt1 <= 0.0) { continue; } cbs = cbs - cd->cmp_bytes_sent; rbs = rbs - cd->raw_bytes_sent; if (cbs < min_cmp) { continue; } if (ouch_db) fprintf(stderr, "START-OUCH: %d\n", client_count); clcnt0 = client_count; #define OUCH ( ouch || (ouch = (!client_count || client_count != clcnt0 || dnow() < last_client_gone+4.0)) ) rfbPE(1000); if (OUCH && ouch_db) fprintf(stderr, "***OUCH-A\n"); if (OUCH) continue; if (use_threads) LOCK(cl->updateMutex); if (sraRgnCountRects(cl->modifiedRegion)) { rfbPE(1000); if (OUCH && ouch_db) fprintf(stderr, "***OUCH-B\n"); if (use_threads) UNLOCK(cl->updateMutex); if (OUCH) continue; } if (use_threads) UNLOCK(cl->updateMutex); defer = screen->deferUpdateTime; httpdir = screen->httpDir; screen->deferUpdateTime = 0; screen->httpDir = NULL; /* mark a small rectangle: */ mark_rect_as_modified(0, 0, 16, 16, 1); dtime0(&tm); dt2 = 0.0; dt3 = 0.0; if (dt1 < 0.25) { /* try to cut it down to avoid long pauses. */ spin_max = 5.0; } /* when req1 = 1 mod1 == 0, end of 2nd part of bulk transfer */ while (1) { int req0, req1, mod0, mod1; if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C1\n"); if (OUCH) break; if (use_threads) LOCK(cl->updateMutex); req0 = sraRgnCountRects(cl->requestedRegion); mod0 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (use_threads) { usleep(1000); } else { if (mod0) { rfbPE(1000); } else { rfbCFD(1000); } } dt = dtime(&tm); dt2 += dt; if (dt2 > spin_max) { break; } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-C2\n"); if (OUCH) break; if (use_threads) LOCK(cl->updateMutex); req1 = sraRgnCountRects(cl->requestedRegion); mod1 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d " "fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f\n", req0, req1, mod0, mod1, #if 0 cl->framebufferUpdateMessagesSent, #else #if LIBVNCSERVER_HAS_STATS rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), #endif #endif dt, dt2, tm); if (req1 != 0 && mod1 == 0) { got_t2 = 1; break; } } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-D\n"); if (OUCH) goto ouch; if (! got_t2) { dt2 = 0.0; } else { int tr, trm = 3; double dts[10]; /* * Note: since often select(2) cannot sleep * less than 1/HZ (e.g. 10ms), the resolution * of the latency may be messed up by something * of this order. Effect may occur on both ends, * i.e. the viewer may not respond immediately. */ for (tr = 0; tr < trm; tr++) { usleep(5000); /* mark a 2nd small rectangle: */ mark_rect_as_modified(0, 0, 16, 16, 1); i = 0; dtime0(&tm); dt3 = 0.0; /* * when req1 > 0 and mod1 == 0, we say * that is the "ping" time. */ while (1) { int req0, req1, mod0, mod1; if (use_threads) LOCK(cl->updateMutex); req0 = sraRgnCountRects(cl->requestedRegion); mod0 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (i == 0) { rfbPE(0); } else { if (use_threads) { usleep(1000); } else { /* try to get it all */ rfbCFD(1000*1000); } } if (OUCH && ouch_db) fprintf(stderr, "***OUCH-E\n"); if (OUCH) goto ouch; dt = dtime(&tm); i++; dt3 += dt; if (dt3 > spin_lat_max) { break; } if (use_threads) LOCK(cl->updateMutex); req1 = sraRgnCountRects(cl->requestedRegion); mod1 = sraRgnCountRects(cl->modifiedRegion); if (use_threads) UNLOCK(cl->updateMutex); if (db) fprintf(stderr, "dt3 calc: num rects req: %d/%d mod: %d/%d " "fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f\n", req0, req1, mod0, mod1, #if 0 cl->framebufferUpdateMessagesSent, #else #if LIBVNCSERVER_HAS_STATS rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), #endif #endif dt, dt3, tm); if (req1 != 0 && mod1 == 0) { dts[got_t3++] = dt3; break; } } } if (! got_t3) { dt3 = 0.0; } else { if (got_t3 == 1) { dt3 = dts[0]; } else if (got_t3 == 2) { dt3 = dts[1]; } else { if (dts[2] > 0.0) { double rat = dts[1]/dts[2]; if (rat > 0.5 && rat < 2.0) { dt3 = dts[1]+dts[2]; dt3 *= 0.5; } else { dt3 = dts[1]; } } else { dt3 = dts[1]; } } } } ouch: screen->deferUpdateTime = defer; screen->httpDir = httpdir; if (OUCH && ouch_db) fprintf(stderr, "***OUCH-F\n"); if (OUCH) break; dt = dt1 + dt2; if (dt3 <= dt2/2.0) { /* guess only 1/2 a ping for reply... */ dt = dt - dt3/2.0; } cmp_rate = cbs/dt; raw_rate = rbs/dt; if (cmp_rate > cmp_max) { cmp_rate = cmp_max; } if (cmp_rate <= cmp_min) { cmp_rate = cmp_min; } cd->send_cmp_rate = cmp_rate; cd->send_raw_rate = raw_rate; if (dt3 > lat_max) { dt3 = lat_max; } if (dt3 <= lat_min) { dt3 = lat_min; } cd->latency = dt3; rfbLog("client %d network rate %.1f KB/sec (%.1f eff KB/sec)\n", cd->uid, cmp_rate/1000.0, raw_rate/1000.0); rfbLog("client %d latency: %.1f ms\n", cd->uid, 1000.0*dt3); rfbLog("dt1: %.4f, dt2: %.4f dt3: %.4f bytes: %d\n", dt1, dt2, dt3, cbs); msg = 1; } if (msg) { int link, latency, netrate; char *str = "error"; link = link_rate(&latency, &netrate); if (link == LR_UNSET) { str = "LR_UNSET"; } else if (link == LR_UNKNOWN) { str = "LR_UNKNOWN"; } else if (link == LR_DIALUP) { str = "LR_DIALUP"; } else if (link == LR_BROADBAND) { str = "LR_BROADBAND"; } else if (link == LR_LAN) { str = "LR_LAN"; } rfbLog("link_rate: %s - %d ms, %d KB/s\n", str, latency, netrate); } if (init) { if (nclients) { screen->displayHook = measure_display_hook; } } else { screen->displayHook = orig_display_hook; } }