vncserver.cc (8871:136328e218f2) vncserver.cc (9330:4a3269a11230)
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
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
69/**
70 * Poll event for the listen socket
71 */
72VncServer::ListenEvent::ListenEvent(VncServer *vs, int fd, int e)
73 : PollEvent(fd, e), vncserver(vs)
74{
75}
76

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

96 else if (revent & POLLNVAL)
97 vncserver->detach();
98}
99
100/**
101 * VncServer
102 */
103VncServer::VncServer(const Params *p)
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)
109{
110 if (p->port)
111 listen(p->port);
112
113 curState = WaitForProtocolVersion;
114
115 // currently we only support this one pixel format
116 // unpacked 32bit rgb (rgb888 + 8 bits of nothing/alpha)

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

122 pixelFormat.truecolor = 1;
123 pixelFormat.redmax = 0xff;
124 pixelFormat.greenmax = 0xff;
125 pixelFormat.bluemax = 0xff;
126 pixelFormat.redshift = 16;
127 pixelFormat.greenshift = 8;
128 pixelFormat.blueshift = 0;
129
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
139 DPRINTF(VNC, "Vnc server created at port %d\n", p->port);
140}
141
142VncServer::~VncServer()
143{
144 if (dataFd != -1)
145 ::close(dataFd);
146

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

460 msg.namelen = 2;
461 msg.namelen = htobe(msg.namelen);
462 memcpy(msg.name, "M5", 2);
463
464 write(&msg);
465 curState = NormalPhase;
466}
467
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
469void
470VncServer::setPixelFormat()
471{
472 DPRINTF(VNC, "Received pixel format from client message\n");
473
474 PixelFormatMessage pfm;
475 read1((uint8_t*)&pfm, sizeof(PixelFormatMessage));
476

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

603
604}
605
606
607void
608VncServer::sendFrameBufferUpdate()
609{
610
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) {
612 DPRINTF(VNC, "NOT sending framebuffer update\n");
613 return;
614 }
615
616 assert(vc);
617
618 // The client will request data constantly, unless we throttle it
619 sendUpdate = false;

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

638 fbr.width = htobe(fbr.width);
639 fbr.height = htobe(fbr.height);
640 fbr.encoding = htobe(fbr.encoding);
641
642 // send headers to client
643 write(&fbu);
644 write(&fbr);
645
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);
647
638
648 uint8_t *tmp = vc->convert(clientRfb);
639 uint8_t *tmp = vc->convert(fbPtr);
649 write(tmp, videoWidth() * videoHeight() * sizeof(uint32_t));
650 delete [] tmp;
651
652}
653
654void
655VncServer::sendFrameBufferResized()
656{
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);
658 DPRINTF(VNC, "Sending framebuffer resize\n");
659
660 FrameBufferUpdate fbu;
661 FrameBufferRect fbr;
662
663 fbu.type = ServerFrameBufferUpdate;
664 fbu.num_rects = 1;
665 fbr.x = 0;

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

679 // send headers to client
680 write(&fbu);
681 write(&fbr);
682
683 // No actual data is sent in this message
684}
685
686void
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)
688{
680{
689 DPRINTF(VNC, "Updating video params: mode: %d width: %d height: %d\n", mode,
690 width, height);
681 VncInput::setFrameBufferParams(mode, width, height);
691
692 if (mode != videoMode || width != videoWidth() || height != videoHeight()) {
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) {
714 if (supportsResizeEnc)
715 sendFrameBufferResized();
716 else
717 // The frame buffer changed size and we can't update the client
718 detach();
719 }
720 }
721}
722
723// create the VNC server object
724VncServer *
725VncServerParams::create()
726{
727 return new VncServer(this);
728}
729
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}