📄 rfbserver.c
字号:
for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { int x = REGION_RECTS(&updateRegion)[i].x1; int y = REGION_RECTS(&updateRegion)[i].y1; int w = REGION_RECTS(&updateRegion)[i].x2 - x; int h = REGION_RECTS(&updateRegion)[i].y2 - y; nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); } } else if (cl->preferredEncoding == rfbEncodingTight) { nUpdateRegionRects = 0; for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { int x = REGION_RECTS(&updateRegion)[i].x1; int y = REGION_RECTS(&updateRegion)[i].y1; int w = REGION_RECTS(&updateRegion)[i].x2 - x; int h = REGION_RECTS(&updateRegion)[i].y2 - y; int n = rfbNumCodedRectsTight(cl, x, y, w, h); if (n == 0) { nUpdateRegionRects = 0xFFFF; break; } nUpdateRegionRects += n; } } else { nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion); } fu->type = rfbFramebufferUpdate; if (nUpdateRegionRects != 0xFFFF) { fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) + nUpdateRegionRects + !!sendCursorShape + !!sendCursorPos); } else { fu->nRects = 0xFFFF; } ublen = sz_rfbFramebufferUpdateMsg; if (sendCursorShape) { cl->cursorWasChanged = FALSE; if (!rfbSendCursorShape(cl, pScreen)) return FALSE; } if (sendCursorPos) { cl->cursorWasMoved = FALSE; if (!rfbSendCursorPos(cl, pScreen)) return FALSE; } if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) { if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) { REGION_UNINIT(pScreen,&updateRegion); REGION_UNINIT(pScreen,&updateCopyRegion); return FALSE; } } REGION_UNINIT(pScreen,&updateCopyRegion); for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) { int x = REGION_RECTS(&updateRegion)[i].x1; int y = REGION_RECTS(&updateRegion)[i].y1; int w = REGION_RECTS(&updateRegion)[i].x2 - x; int h = REGION_RECTS(&updateRegion)[i].y2 - y; cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); switch (cl->preferredEncoding) { case rfbEncodingRaw: if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; case rfbEncodingRRE: if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; case rfbEncodingCoRRE: if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; case rfbEncodingHextile: if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; case rfbEncodingZlib: if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; case rfbEncodingTight: if (!rfbSendRectEncodingTight(cl, x, y, w, h)) { REGION_UNINIT(pScreen,&updateRegion); return FALSE; } break; } } REGION_UNINIT(pScreen,&updateRegion); if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl)) return FALSE; if (!rfbSendUpdateBuf(cl)) return FALSE; return TRUE;}/* * Send the copy region as a string of CopyRect encoded rectangles. * The only slightly tricky thing is that we should send the messages in * the correct order so that an earlier CopyRect will not corrupt the source * of a later one. */static BoolrfbSendCopyRegion(cl, reg, dx, dy) rfbClientPtr cl; RegionPtr reg; int dx, dy;{ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand; int x, y, w, h; rfbFramebufferUpdateRectHeader rect; rfbCopyRect cr; nrects = REGION_NUM_RECTS(reg); if (dx <= 0) { x_inc = 1; } else { x_inc = -1; } if (dy <= 0) { thisRect = 0; y_inc = 1; } else { thisRect = nrects - 1; y_inc = -1; } while (nrects > 0) { firstInNextBand = thisRect; nrectsInBand = 0; while ((nrects > 0) && (REGION_RECTS(reg)[firstInNextBand].y1 == REGION_RECTS(reg)[thisRect].y1)) { firstInNextBand += y_inc; nrects--; nrectsInBand++; } if (x_inc != y_inc) { thisRect = firstInNextBand - y_inc; } while (nrectsInBand > 0) { if ((ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect) > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } x = REGION_RECTS(reg)[thisRect].x1; y = REGION_RECTS(reg)[thisRect].y1; w = REGION_RECTS(reg)[thisRect].x2 - x; h = REGION_RECTS(reg)[thisRect].y2 - y; rect.r.x = Swap16IfLE(x); rect.r.y = Swap16IfLE(y); rect.r.w = Swap16IfLE(w); rect.r.h = Swap16IfLE(h); rect.encoding = Swap32IfLE(rfbEncodingCopyRect); memcpy(&updateBuf[ublen], (char *)&rect, sz_rfbFramebufferUpdateRectHeader); ublen += sz_rfbFramebufferUpdateRectHeader; cr.srcX = Swap16IfLE(x - dx); cr.srcY = Swap16IfLE(y - dy); memcpy(&updateBuf[ublen], (char *)&cr, sz_rfbCopyRect); ublen += sz_rfbCopyRect; cl->rfbRectanglesSent[rfbEncodingCopyRect]++; cl->rfbBytesSent[rfbEncodingCopyRect] += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect; thisRect += x_inc; nrectsInBand--; } thisRect = firstInNextBand; } return TRUE;}/* * Send a given rectangle in raw encoding (rfbEncodingRaw). */BoolrfbSendRectEncodingRaw(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ rfbFramebufferUpdateRectHeader rect; int nlines; int bytesPerLine = w * (cl->format.bitsPerPixel / 8); char *fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y) + (x * (rfbScreen.bitsPerPixel / 8))); /* Flush the buffer to guarantee correct alignment for translateFn(). */ if (ublen > 0) { if (!rfbSendUpdateBuf(cl)) return FALSE; } rect.r.x = Swap16IfLE(x); rect.r.y = Swap16IfLE(y); rect.r.w = Swap16IfLE(w); rect.r.h = Swap16IfLE(h); rect.encoding = Swap32IfLE(rfbEncodingRaw); memcpy(&updateBuf[ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); ublen += sz_rfbFramebufferUpdateRectHeader; cl->rfbRectanglesSent[rfbEncodingRaw]++; cl->rfbBytesSent[rfbEncodingRaw] += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h; nlines = (UPDATE_BUF_SIZE - ublen) / bytesPerLine; while (TRUE) { if (nlines > h) nlines = h; (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat, &cl->format, fbptr, &updateBuf[ublen], rfbScreen.paddedWidthInBytes, w, nlines); ublen += nlines * bytesPerLine; h -= nlines; if (h == 0) /* rect fitted in buffer, do next one */ return TRUE; /* buffer full - flush partial rect and do another nlines */ if (!rfbSendUpdateBuf(cl)) return FALSE; fbptr += (rfbScreen.paddedWidthInBytes * nlines); nlines = (UPDATE_BUF_SIZE - ublen) / bytesPerLine; if (nlines == 0) { rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d " "bytes per line\n", bytesPerLine); rfbCloseSock(cl->sock); return FALSE; } }}/* * Send an empty rectangle with encoding field set to value of * rfbEncodingLastRect to notify client that this is the last * rectangle in framebuffer update ("LastRect" extension of RFB * protocol). */static BoolrfbSendLastRectMarker(cl) rfbClientPtr cl;{ rfbFramebufferUpdateRectHeader rect; if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } rect.encoding = Swap32IfLE(rfbEncodingLastRect); rect.r.x = 0; rect.r.y = 0; rect.r.w = 0; rect.r.h = 0; memcpy(&updateBuf[ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); ublen += sz_rfbFramebufferUpdateRectHeader; cl->rfbLastRectMarkersSent++; cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader; return TRUE;}/* * Send the contents of updateBuf. Returns 1 if successful, -1 if * not (errno should be set). */BoolrfbSendUpdateBuf(cl) rfbClientPtr cl;{ /* int i; for (i = 0; i < ublen; i++) { fprintf(stderr,"%02x ",((unsigned char *)updateBuf)[i]); } fprintf(stderr,"\n"); */ if (ublen > 0 && WriteExact(cl->sock, updateBuf, ublen) < 0) { rfbLogPerror("rfbSendUpdateBuf: write"); rfbCloseSock(cl->sock); return FALSE; } ublen = 0; return TRUE;}/* * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the * client, using values from the currently installed colormap. */BoolrfbSendSetColourMapEntries(cl, firstColour, nColours) rfbClientPtr cl; int firstColour; int nColours;{ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); EntryPtr pent; int i, len; scme->type = rfbSetColourMapEntries; scme->firstColour = Swap16IfLE(firstColour); scme->nColours = Swap16IfLE(nColours); len = sz_rfbSetColourMapEntriesMsg; pent = (EntryPtr)&rfbInstalledColormap->red[firstColour]; for (i = 0; i < nColours; i++) { if (pent->fShared) { rgb[i*3] = Swap16IfLE(pent->co.shco.red->color); rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color); rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color); } else { rgb[i*3] = Swap16IfLE(pent->co.local.red); rgb[i*3+1] = Swap16IfLE(pent->co.local.green); rgb[i*3+2] = Swap16IfLE(pent->co.local.blue); } pent++; } len += nColours * 3 * 2; if (WriteExact(cl->sock, buf, len) < 0) { rfbLogPerror("rfbSendSetColourMapEntries: write"); rfbCloseSock(cl->sock); return FALSE; } return TRUE;}/* * rfbSendBell sends a Bell message to all the clients. */voidrfbSendBell(){ rfbClientPtr cl, nextCl; rfbBellMsg b; for (cl = rfbClientHead; cl; cl = nextCl) { nextCl = cl->next; if (cl->state != RFB_NORMAL) continue; b.type = rfbBell; if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) { rfbLogPerror("rfbSendBell: write"); rfbCloseSock(cl->sock); } }}/* * rfbSendServerCutText sends a ServerCutText message to all the clients. */voidrfbSendServerCutText(char *str, int len){ rfbClientPtr cl, nextCl; rfbServerCutTextMsg sct; if (rfbViewOnly) return; for (cl = rfbClientHead; cl; cl = nextCl) { nextCl = cl->next; if (cl->state != RFB_NORMAL || cl->viewOnly) continue; sct.type = rfbServerCutText; sct.length = Swap32IfLE(len); if (WriteExact(cl->sock, (char *)&sct, sz_rfbServerCutTextMsg) < 0) { rfbLogPerror("rfbSendServerCutText: write"); rfbCloseSock(cl->sock); continue; } if (WriteExact(cl->sock, str, len) < 0) { rfbLogPerror("rfbSendServerCutText: write"); rfbCloseSock(cl->sock); } }}/***************************************************************************** * * UDP can be used for keyboard and pointer events when the underlying * network is highly reliable. This is really here to support ORL's * videotile, whose TCP implementation doesn't like sending lots of small * packets (such as 100s of pen readings per second!). */voidrfbNewUDPConnection(sock) int sock;{ if (write(sock, &ptrAcceleration, 1) < 0) { rfbLogPerror("rfbNewUDPConnection: write"); }}/* * Because UDP is a message based service, we can't read the first byte and * then the rest of the packet separately like we do with TCP. We will always * get a whole packet delivered in one go, so we ask read() for the maximum * number of bytes we can possibly get. */voidrfbProcessUDPInput(sock) int sock;{ int n; rfbClientToServerMsg msg; if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) { if (n < 0) { rfbLogPerror("rfbProcessUDPInput: read"); } rfbDisconnectUDPSock(); return; } switch (msg.type) { case rfbKeyEvent: if (n != sz_rfbKeyEventMsg) { rfbLog("rfbProcessUDPInput: key event incorrect length\n"); rfbDisconnectUDPSock(); return; } if (!rfbViewOnly) { KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0); } break; case rfbPointerEvent: if (n != sz_rfbPointerEventMsg) { rfbLog("rfbProcessUDPInput: ptr event incorrect length\n"); rfbDisconnectUDPSock(); return; } if (!rfbViewOnly) { PtrAddEvent(msg.pe.buttonMask, Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0); } break; default: rfbLog("rfbProcessUDPInput: unknown message type %d\n", msg.type); rfbDisconnectUDPSock(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -