1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 52 unchanged lines hidden (view full) ---

61#include "base/socket.hh"
62#include "base/trace.hh"
63#include "debug/VNC.hh"
64#include "sim/byteswap.hh"
65#include "sim/core.hh"
66
67using namespace std;
68
69/** @file
70 * Implementiation of a VNC server
71 */
72
73/**
74 * Poll event for the listen socket
75 */
76VncServer::ListenEvent::ListenEvent(VncServer *vs, int fd, int e)
77 : PollEvent(fd, e), vncserver(vs)
78{
79}
80

--- 19 unchanged lines hidden (view full) ---

100 else if (revent & POLLNVAL)
101 vncserver->detach();
102}
103
104/**
105 * VncServer
106 */
107VncServer::VncServer(const Params *p)
104 : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
105 dataFd(-1), _videoWidth(1), _videoHeight(1), clientRfb(0), keyboard(NULL),
106 mouse(NULL), sendUpdate(false), videoMode(VideoConvert::UnknownMode),
107 vc(NULL), captureEnabled(p->frame_capture), captureCurrentFrame(0),
108 captureLastHash(0), captureBitmap(0)
108 : VncInput(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
109 dataFd(-1), sendUpdate(false)
110{
111 if (p->port)
112 listen(p->port);
113
114 curState = WaitForProtocolVersion;
115
116 // currently we only support this one pixel format
117 // unpacked 32bit rgb (rgb888 + 8 bits of nothing/alpha)

--- 5 unchanged lines hidden (view full) ---

123 pixelFormat.truecolor = 1;
124 pixelFormat.redmax = 0xff;
125 pixelFormat.greenmax = 0xff;
126 pixelFormat.bluemax = 0xff;
127 pixelFormat.redshift = 16;
128 pixelFormat.greenshift = 8;
129 pixelFormat.blueshift = 0;
130
130 if (captureEnabled) {
131 // remove existing frame output directory if it exists, then create a
132 // clean empty directory
133 const string FRAME_OUTPUT_SUBDIR = "frames_" + name();
134 simout.remove(FRAME_OUTPUT_SUBDIR, true);
135 captureOutputDirectory = simout.createSubdirectory(
136 FRAME_OUTPUT_SUBDIR);
137 }
138
131 DPRINTF(VNC, "Vnc server created at port %d\n", p->port);
132}
133
134VncServer::~VncServer()
135{
136 if (dataFd != -1)
137 ::close(dataFd);
138

--- 313 unchanged lines hidden (view full) ---

452 msg.namelen = 2;
453 msg.namelen = htobe(msg.namelen);
454 memcpy(msg.name, "M5", 2);
455
456 write(&msg);
457 curState = NormalPhase;
458}
459
468
460void
461VncServer::setPixelFormat()
462{
463 DPRINTF(VNC, "Received pixel format from client message\n");
464
465 PixelFormatMessage pfm;
466 read1((uint8_t*)&pfm, sizeof(PixelFormatMessage));
467

--- 126 unchanged lines hidden (view full) ---

594
595}
596
597
598void
599VncServer::sendFrameBufferUpdate()
600{
601
611 if (!clientRfb || dataFd <= 0 || curState != NormalPhase || !sendUpdate) {
602 if (!fbPtr || dataFd <= 0 || curState != NormalPhase || !sendUpdate) {
603 DPRINTF(VNC, "NOT sending framebuffer update\n");
604 return;
605 }
606
607 assert(vc);
608
609 // The client will request data constantly, unless we throttle it
610 sendUpdate = false;

--- 18 unchanged lines hidden (view full) ---

629 fbr.width = htobe(fbr.width);
630 fbr.height = htobe(fbr.height);
631 fbr.encoding = htobe(fbr.encoding);
632
633 // send headers to client
634 write(&fbu);
635 write(&fbr);
636
646 assert(clientRfb);
637 assert(fbPtr);
638
648 uint8_t *tmp = vc->convert(clientRfb);
639 uint8_t *tmp = vc->convert(fbPtr);
640 write(tmp, videoWidth() * videoHeight() * sizeof(uint32_t));
641 delete [] tmp;
642
643}
644
645void
646VncServer::sendFrameBufferResized()
647{
657 assert(clientRfb && dataFd > 0 && curState == NormalPhase);
648 assert(fbPtr && dataFd > 0 && curState == NormalPhase);
649 DPRINTF(VNC, "Sending framebuffer resize\n");
650
651 FrameBufferUpdate fbu;
652 FrameBufferRect fbr;
653
654 fbu.type = ServerFrameBufferUpdate;
655 fbu.num_rects = 1;
656 fbr.x = 0;

--- 13 unchanged lines hidden (view full) ---

670 // send headers to client
671 write(&fbu);
672 write(&fbr);
673
674 // No actual data is sent in this message
675}
676
677void
687VncServer::setFrameBufferParams(VideoConvert::Mode mode, int width, int height)
678VncServer::setFrameBufferParams(VideoConvert::Mode mode, uint16_t width,
679 uint16_t height)
680{
689 DPRINTF(VNC, "Updating video params: mode: %d width: %d height: %d\n", mode,
690 width, height);
681 VncInput::setFrameBufferParams(mode, width, height);
682
683 if (mode != videoMode || width != videoWidth() || height != videoHeight()) {
693 videoMode = mode;
694 _videoWidth = width;
695 _videoHeight = height;
696
697 if (vc)
698 delete vc;
699
700 vc = new VideoConvert(mode, VideoConvert::rgb8888, videoWidth(),
701 videoHeight());
702
703 if (captureEnabled) {
704 // create bitmap of the frame with new attributes
705 if (captureBitmap)
706 delete captureBitmap;
707
708 assert(clientRfb);
709 captureBitmap = new Bitmap(videoMode, width, height, clientRfb);
710 assert(captureBitmap);
711 }
712
713 if (dataFd > 0 && clientRfb && curState == NormalPhase) {
684 if (dataFd > 0 && fbPtr && curState == NormalPhase) {
685 if (supportsResizeEnc)
686 sendFrameBufferResized();
687 else
688 // The frame buffer changed size and we can't update the client
689 detach();
690 }
691 }
692}
693
694// create the VNC server object
695VncServer *
696VncServerParams::create()
697{
698 return new VncServer(this);
699}
700
730void
731VncServer::captureFrameBuffer()
732{
733 assert(captureBitmap);
734
735 // skip identical frames
736 uint64_t new_hash = captureBitmap->getHash();
737 if (captureLastHash == new_hash)
738 return;
739 captureLastHash = new_hash;
740
741 // get the filename for the current frame
742 char frameFilenameBuffer[64];
743 snprintf(frameFilenameBuffer, 64, "fb.%06d.%lld.bmp.gz",
744 captureCurrentFrame, static_cast<long long int>(curTick()));
745 const string frameFilename(frameFilenameBuffer);
746
747 // create the compressed framebuffer file
748 ostream *fb_out = simout.create(captureOutputDirectory + frameFilename,
749 true);
750 captureBitmap->write(fb_out);
751 simout.close(fb_out);
752
753 ++captureCurrentFrame;
754}