📄 rfbserver.c
字号:
SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); if (i != N_ENC_CAPS) { rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); rfbCloseSock(cl->sock); return; } /* Send header and capability lists */ if (WriteExact(cl->sock, (char *)&intr_caps, sz_rfbInteractionCapsMsg) < 0 || WriteExact(cl->sock, (char *)&enc_list[0], sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { rfbLogPerror("rfbSendInteractionCaps: write"); rfbCloseSock(cl->sock); return; } /* Dispatch client input to rfbProcessClientNormalMessage(). */ cl->state = RFB_NORMAL;}/* * rfbProcessClientNormalMessage is called when the client has sent a normal * protocol message. */static voidrfbProcessClientNormalMessage(cl) rfbClientPtr cl;{ int n; rfbClientToServerMsg msg; char *str; if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } switch (msg.type) { case rfbSetPixelFormat: if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbSetPixelFormatMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; cl->format.depth = msg.spf.format.depth; cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0); cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0); cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); cl->format.redShift = msg.spf.format.redShift; cl->format.greenShift = msg.spf.format.greenShift; cl->format.blueShift = msg.spf.format.blueShift; cl->readyForSetColourMapEntries = TRUE; rfbSetTranslateFunction(cl); return; case rfbFixColourMapEntries: if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } rfbLog("rfbProcessClientNormalMessage: %s", "FixColourMapEntries unsupported\n"); rfbCloseSock(cl->sock); return; case rfbSetEncodings: { int i; CARD32 enc; if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbSetEncodingsMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); cl->preferredEncoding = -1; cl->useCopyRect = FALSE; cl->enableCursorShapeUpdates = FALSE; cl->enableCursorPosUpdates = FALSE; cl->enableLastRectEncoding = FALSE; cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; cl->tightQualityLevel = -1; for (i = 0; i < msg.se.nEncodings; i++) { if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } enc = Swap32IfLE(enc); switch (enc) { case rfbEncodingCopyRect: cl->useCopyRect = TRUE; break; case rfbEncodingRaw: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using raw encoding for client %s\n", cl->host); } break; case rfbEncodingRRE: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using rre encoding for client %s\n", cl->host); } break; case rfbEncodingCoRRE: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using CoRRE encoding for client %s\n", cl->host); } break; case rfbEncodingHextile: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using hextile encoding for client %s\n", cl->host); } break; case rfbEncodingZlib: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using zlib encoding for client %s\n", cl->host); } break; case rfbEncodingTight: if (cl->preferredEncoding == -1) { cl->preferredEncoding = enc; rfbLog("Using tight encoding for client %s\n", cl->host); } break; case rfbEncodingXCursor: rfbLog("Enabling X-style cursor updates for client %s\n", cl->host); cl->enableCursorShapeUpdates = TRUE; cl->useRichCursorEncoding = FALSE; cl->cursorWasChanged = TRUE; break; case rfbEncodingRichCursor: if (!cl->enableCursorShapeUpdates) { rfbLog("Enabling full-color cursor updates for client " "%s\n", cl->host); cl->enableCursorShapeUpdates = TRUE; cl->useRichCursorEncoding = TRUE; cl->cursorWasChanged = TRUE; } break; case rfbEncodingPointerPos: if (!cl->enableCursorPosUpdates) { rfbLog("Enabling cursor position updates for client %s\n", cl->host); cl->enableCursorPosUpdates = TRUE; cl->cursorWasMoved = TRUE; cl->cursorX = -1; cl->cursorY = -1; } break; case rfbEncodingLastRect: if (!cl->enableLastRectEncoding) { rfbLog("Enabling LastRect protocol extension for client " "%s\n", cl->host); cl->enableLastRectEncoding = TRUE; } break; default: if ( enc >= (CARD32)rfbEncodingCompressLevel0 && enc <= (CARD32)rfbEncodingCompressLevel9 ) { cl->zlibCompressLevel = enc & 0x0F; cl->tightCompressLevel = enc & 0x0F; rfbLog("Using compression level %d for client %s\n", cl->tightCompressLevel, cl->host); } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 && enc <= (CARD32)rfbEncodingQualityLevel9 ) { cl->tightQualityLevel = enc & 0x0F; rfbLog("Using image quality level %d for client %s\n", cl->tightQualityLevel, cl->host); } else { rfbLog("rfbProcessClientNormalMessage: ignoring unknown " "encoding %d\n", (int)enc); } } } if (cl->preferredEncoding == -1) { cl->preferredEncoding = rfbEncodingRaw; } if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { rfbLog("Disabling cursor position updates for client %s\n", cl->host); cl->enableCursorPosUpdates = FALSE; } return; } case rfbFramebufferUpdateRequest: { RegionRec tmpRegion; BoxRec box;#ifdef CORBA addCapability(cl, DISPLAY_DEVICE);#endif if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } box.x1 = Swap16IfLE(msg.fur.x); box.y1 = Swap16IfLE(msg.fur.y); box.x2 = box.x1 + Swap16IfLE(msg.fur.w); box.y2 = box.y1 + Swap16IfLE(msg.fur.h); SAFE_REGION_INIT(pScreen,&tmpRegion,&box,0); REGION_UNION(pScreen, &cl->requestedRegion, &cl->requestedRegion, &tmpRegion); if (!cl->readyForSetColourMapEntries) { /* client hasn't sent a SetPixelFormat so is using server's */ cl->readyForSetColourMapEntries = TRUE; if (!cl->format.trueColour) { if (!rfbSetClientColourMap(cl, 0, 0)) { REGION_UNINIT(pScreen,&tmpRegion); return; } } } if (!msg.fur.incremental) { REGION_UNION(pScreen,&cl->modifiedRegion,&cl->modifiedRegion, &tmpRegion); REGION_SUBTRACT(pScreen,&cl->copyRegion,&cl->copyRegion, &tmpRegion); } if (FB_UPDATE_PENDING(cl)) { rfbSendFramebufferUpdate(cl); } REGION_UNINIT(pScreen,&tmpRegion); return; } case rfbKeyEvent: cl->rfbKeyEventsRcvd++; if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbKeyEventMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; }#ifdef CORBA addCapability(cl, KEYBOARD_DEVICE); if (!isKeyboardEnabled(cl)) return;#endif if (!rfbViewOnly && !cl->viewOnly) { KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl); } return; case rfbPointerEvent: cl->rfbPointerEventsRcvd++; if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbPointerEventMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; }#ifdef CORBA addCapability(cl, POINTER_DEVICE); if (!isPointerEnabled(cl)) return;#endif if (pointerClient && (pointerClient != cl)) return; if (msg.pe.buttonMask == 0) pointerClient = NULL; else pointerClient = cl; if (!rfbViewOnly && !cl->viewOnly) { cl->cursorX = (int)Swap16IfLE(msg.pe.x); cl->cursorY = (int)Swap16IfLE(msg.pe.y); PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl); } return; case rfbClientCutText: if ((n = ReadExact(cl->sock, ((char *)&msg) + 1, sz_rfbClientCutTextMsg - 1)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); rfbCloseSock(cl->sock); return; } msg.cct.length = Swap32IfLE(msg.cct.length); str = (char *)xalloc(msg.cct.length); if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) { if (n != 0) rfbLogPerror("rfbProcessClientNormalMessage: read"); xfree(str); rfbCloseSock(cl->sock); return; } /* NOTE: We do not accept cut text from a view-only client */ if (!rfbViewOnly && !cl->viewOnly) rfbSetXCutText(str, msg.cct.length); xfree(str); return; default: rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", msg.type); rfbLog(" ... closing connection\n"); rfbCloseSock(cl->sock); return; }}/* * rfbSendFramebufferUpdate - send the currently pending framebuffer update to * the RFB client. */BoolrfbSendFramebufferUpdate(cl) rfbClientPtr cl;{ ScreenPtr pScreen = screenInfo.screens[0]; int i; int nUpdateRegionRects; rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)updateBuf; RegionRec updateRegion, updateCopyRegion; int dx, dy; Bool sendCursorShape = FALSE; Bool sendCursorPos = FALSE; /* * If this client understands cursor shape updates, cursor should be * removed from the framebuffer. Otherwise, make sure it's put up. */ if (cl->enableCursorShapeUpdates) { if (rfbScreen.cursorIsDrawn) rfbSpriteRemoveCursor(pScreen); if (!rfbScreen.cursorIsDrawn && cl->cursorWasChanged) sendCursorShape = TRUE; } else { if (!rfbScreen.cursorIsDrawn) rfbSpriteRestoreCursor(pScreen); } /* * Do we plan to send cursor position update? */ if (cl->enableCursorPosUpdates && cl->cursorWasMoved) sendCursorPos = TRUE; /* * The modifiedRegion may overlap the destination copyRegion. We remove * any overlapping bits from the copyRegion (since they'd only be * overwritten anyway). */ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion, &cl->modifiedRegion); /* * The client is interested in the region requestedRegion. The region * which should be updated now is the intersection of requestedRegion * and the union of modifiedRegion and copyRegion. If it's empty then * no update is needed. */ REGION_INIT(pScreen,&updateRegion,NullBox,0); REGION_UNION(pScreen, &updateRegion, &cl->copyRegion, &cl->modifiedRegion); REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion, &updateRegion); if ( !REGION_NOTEMPTY(pScreen,&updateRegion) && !sendCursorShape && !sendCursorPos ) { REGION_UNINIT(pScreen,&updateRegion); return TRUE; } /* * We assume that the client doesn't have any pixel data outside the * requestedRegion. In other words, both the source and destination of a * copy must lie within requestedRegion. So the region we can send as a * copy is the intersection of the copyRegion with both the requestedRegion * and the requestedRegion translated by the amount of the copy. We set * updateCopyRegion to this. */ REGION_INIT(pScreen,&updateCopyRegion,NullBox,0); REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion, &cl->requestedRegion); REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY); REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion, &cl->requestedRegion); dx = cl->copyDX; dy = cl->copyDY; /* * Next we remove updateCopyRegion from updateRegion so that updateRegion * is the part of this update which is sent as ordinary pixel data (i.e not * a copy). */ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion); /* * Finally we leave modifiedRegion to be the remainder (if any) of parts of * the screen which are modified but outside the requestedRegion. We also * empty both the requestedRegion and the copyRegion - note that we never * carry over a copyRegion for a future update. */ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, &cl->copyRegion); REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, &updateRegion); REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, &updateCopyRegion); REGION_EMPTY(pScreen, &cl->requestedRegion); REGION_EMPTY(pScreen, &cl->copyRegion); cl->copyDX = 0; cl->copyDY = 0; /* * Now send the update. */ cl->rfbFramebufferUpdateMessagesSent++; if (cl->preferredEncoding == rfbEncodingCoRRE) { 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; nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1) * ((h-1) / cl->correMaxHeight + 1)); } } else if (cl->preferredEncoding == rfbEncodingZlib) { nUpdateRegionRects = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -