예제 #1
0
static rfbBool resize(rfbClient* client) {
	static char first=TRUE;
#ifdef SDL_ASYNCBLIT
	int flags=SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
#else
	int flags=SDL_HWSURFACE|SDL_HWACCEL;
#endif
	int width=client->width,height=client->height,
		depth=client->format.bitsPerPixel;
	client->updateRect.x = client->updateRect.y = 0;
	client->updateRect.w = width; client->updateRect.h = height;
	rfbBool okay=SDL_VideoModeOK(width,height,depth,flags);
	if(!okay)
		for(depth=24;!okay && depth>4;depth/=2)
			okay=SDL_VideoModeOK(width,height,depth,flags);
	if(okay) {
		SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,flags);
		rfbClientSetClientData(client, SDL_Init, sdl);
		client->width = sdl->pitch / (depth / 8);
		client->frameBuffer=sdl->pixels;
		if(first || depth!=client->format.bitsPerPixel) {
			first=FALSE;
			client->format.bitsPerPixel=depth;
			client->format.redShift=sdl->format->Rshift;
			client->format.greenShift=sdl->format->Gshift;
			client->format.blueShift=sdl->format->Bshift;
			client->format.redMax=sdl->format->Rmask>>client->format.redShift;
			client->format.greenMax=sdl->format->Gmask>>client->format.greenShift;
			client->format.blueMax=sdl->format->Bmask>>client->format.blueShift;
			SetFormatAndEncodings(client);
		}
	} else {
예제 #2
0
/* Redraw the screen from the backing pixmap */
static gboolean expose_event (GtkWidget      *widget,
                              GdkEventExpose *event)
{
	static GdkImage *image = NULL;
	GdkCursor *cursor;
	GdkPixbuf *pixbuf;

	if (framebuffer_allocated == FALSE) {

		rfbClientSetClientData (cl, gtk_init, widget);

		image = gdk_drawable_get_image (widget->window, 0, 0,
		                                widget->allocation.width,
		                                widget->allocation.height);

		cl->frameBuffer= image->mem;

		cl->width  = widget->allocation.width;
		cl->height = widget->allocation.height;

		cl->format.bitsPerPixel = image->bits_per_pixel;
		cl->format.redShift     = image->visual->red_shift;
		cl->format.greenShift   = image->visual->green_shift;
		cl->format.blueShift    = image->visual->blue_shift;

		cl->format.redMax   = (1 << image->visual->red_prec) - 1;
		cl->format.greenMax = (1 << image->visual->green_prec) - 1;
		cl->format.blueMax  = (1 << image->visual->blue_prec) - 1;

#ifdef LIBVNCSERVER_CONFIG_LIBVA
		/* Allow libvncclient to use a more efficient way
		 * of putting the framebuffer on the screen when
		 * using the H.264 format.
		 */
		cl->outputWindow = GDK_WINDOW_XID(widget->window);
#endif

		SetFormatAndEncodings (cl);

		framebuffer_allocated = TRUE;

		/* Also disable local cursor */
                pixbuf = gdk_pixbuf_new_from_xpm_data(dot_cursor_xpm);
	        cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, dot_cursor_x_hot, dot_cursor_y_hot);
		g_object_unref(pixbuf);	
		gdk_window_set_cursor (gtk_widget_get_window(GTK_WIDGET(window)), cursor);
		gdk_cursor_unref(cursor);
	}

#ifndef LIBVNCSERVER_CONFIG_LIBVA
	gdk_draw_image (GDK_DRAWABLE (widget->window),
	                widget->style->fg_gc[gtk_widget_get_state(widget)],
	                image,
	                event->area.x, event->area.y,
	                event->area.x, event->area.y,
	                event->area.width, event->area.height);
#endif

	return FALSE;
}
예제 #3
0
static rfbBool handleBackChannelMessage(rfbClient* client,
	rfbServerToClientMsg* message)
{
	backChannelMsg msg;
	char* text;

	if(message->type != rfbBackChannel)
		return FALSE;

	rfbClientSetClientData(client, sendMessage, sendMessage);

	if(!ReadFromRFBServer(client, ((char*)&msg)+1, sizeof(msg)-1))
		return TRUE;
	msg.size = rfbClientSwap32IfLE(msg.size);
	text = malloc(msg.size);
	if(!ReadFromRFBServer(client, text, msg.size)) {
		free(text);
		return TRUE;
	}

	rfbClientLog("got back channel message: %s\n", text);
	free(text);

	return TRUE;
}
예제 #4
0
bool LibVncImage::connect(const std::string& hostname)
{
    if (hostname.empty()) return false;

    if (_client) close();

    _client = rfbGetClient(8,3,4);
    _client->canHandleNewFBSize = TRUE;
    _client->MallocFrameBuffer = resizeImage;
    _client->GotFrameBufferUpdate = updateImage;
    _client->HandleKeyboardLedState = 0;
    _client->HandleTextChat = 0;

    // provide the password if we have one assigned
    if (!_password.empty())  _client->GetPassword = getPassword;

    rfbClientSetClientData(_client, 0, this);

    size_t pos = hostname.find(":");
    if (pos == std::string::npos)
    {
        _client->serverHost = strdup(hostname.c_str());
    }
    else
    {
        _client->serverHost = strdup(hostname.substr(0, pos).c_str());
        _client->serverPort = atoi(hostname.substr(pos+1).c_str());
    }

    // _client->appData.qualityLevel = ;
    // _client->appData.encodings = ;
    // _client->appData.compressLevel = ;
    // _client->appData.scaleSetting = ;

    if(rfbInitConnection(_client))
    {
        _rfbThread = new RfbThread(_client, this);
        _rfbThread->startThread();

        return true;
    }
    else
    {
        close();

        return false;
    }
}
예제 #5
0
bool LibVncImage::connect(const std::string& hostname)
{
    if (hostname.empty()) return false;

    if (_client) close();

    _client = rfbGetClient(8,3,4);
    _client->canHandleNewFBSize = TRUE;
    _client->MallocFrameBuffer = resizeImage;
    _client->GotFrameBufferUpdate = updateImage;
    _client->HandleKeyboardLedState = 0;
    _client->HandleTextChat = 0;

    rfbClientSetClientData(_client, 0, this);
    
    _client->serverHost = strdup(hostname.c_str());

    // _client->serverPort = ;
    // _client->appData.qualityLevel = ;
    // _client->appData.encodings = ;
    // _client->appData.compressLevel = ;
    // _client->appData.scaleSetting = ;

    if(rfbInitConnection(_client))
    {
        _rfbThread = new RfbThread(_client, this);
        _rfbThread->startThread();
        
        return true;
    }
    else
    {
        close();
        
        return false;
    }
}
예제 #6
0
void VncClientThread::run()
{
    QMutexLocker locker(&mutex);

    while (!m_stopped) { // try to connect as long as the server allows
        locker.relock();
        m_passwordError = false;
        locker.unlock();

        rfbClientLog = outputHandler;
        rfbClientErr = outputHandler;
        //24bit color dept in 32 bits per pixel = default. Will change colordepth and bpp later if needed
        cl = rfbGetClient(8, 3, 4);
        setClientColorDepth(cl, this->colorDepth());
        cl->MallocFrameBuffer = newclient;
        cl->canHandleNewFBSize = true;
        cl->GetPassword = passwdHandler;
        cl->GetCredential = credentialHandler;
        cl->GotFrameBufferUpdate = updatefb;
        cl->GotXCutText = cuttext;
        rfbClientSetClientData(cl, 0, this);

        locker.relock();
        cl->serverHost = strdup(m_host.toUtf8().constData());

        if (m_port < 0 || !m_port) // port is invalid or empty...
            m_port = 5900; // fallback: try an often used VNC port

        if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1)
            m_port += 5900;
        cl->serverPort = m_port;
        locker.unlock();

        kDebug(5011) << "--------------------- trying init ---------------------";

        if (rfbInitClient(cl, 0, 0))
            break;
        else
            cl = 0;

        locker.relock();
        if (m_passwordError)
            continue;

        return;
    }

    locker.relock();
    kDebug(5011) << "--------------------- Starting main VNC event loop ---------------------";
    while (!m_stopped) {
        locker.unlock();
        const int i = WaitForMessage(cl, 500);
        if (m_stopped || i < 0) {
            break;
        }
        if (i) {
            if (!HandleRFBServerMessage(cl)) {
                break;
            }
        }

        locker.relock();
        while (!m_eventQueue.isEmpty()) {
            ClientEvent* clientEvent = m_eventQueue.dequeue();
            locker.unlock();
            clientEvent->fire(cl);
            delete clientEvent;
            locker.relock();
        }
    }

    m_stopped = true;
}
예제 #7
0
파일: vnc.c 프로젝트: mstorsjo/vlc
/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t      *p_demux = (demux_t*)p_this;
    demux_sys_t  *p_sys;

    if (p_demux->out == NULL)
        return VLC_EGENERIC;

    p_sys = vlc_obj_calloc( p_this, 1, sizeof(demux_sys_t) );
    if( !p_sys ) return VLC_ENOMEM;

    p_sys->f_fps = var_InheritFloat( p_demux, CFG_PREFIX "fps" );
    if ( p_sys->f_fps <= 0 ) p_sys->f_fps = 1.0;
    p_sys->i_frame_interval = vlc_tick_rate_duration( p_sys->f_fps );

    char *psz_chroma = var_InheritString( p_demux, CFG_PREFIX "chroma" );
    vlc_fourcc_t i_chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, psz_chroma );
    free( psz_chroma );
    if ( !i_chroma || vlc_fourcc_IsYUV( i_chroma ) )
    {
        msg_Err( p_demux, "Only RGB chroma are supported" );
        return VLC_EGENERIC;
    }

    const vlc_chroma_description_t *p_chroma_desc = vlc_fourcc_GetChromaDescription( i_chroma );
    if ( !p_chroma_desc )
    {
        msg_Err( p_demux, "Unable to get RGB chroma description" );
        return VLC_EGENERIC;
    }

#ifdef NDEBUG
    rfbEnableClientLogging = FALSE;
#endif

    p_sys->p_client = rfbGetClient( p_chroma_desc->pixel_bits / 3, // bitsPerSample
                                    3, // samplesPerPixel
                                    p_chroma_desc->pixel_size ); // bytesPerPixel
    if ( ! p_sys->p_client )
    {
        msg_Dbg( p_demux, "Unable to set up client for %s",
                 vlc_fourcc_GetDescription( VIDEO_ES, i_chroma ) );
        return VLC_EGENERIC;
    }

    msg_Dbg( p_demux, "set up client for %s %d %d %d",
             vlc_fourcc_GetDescription( VIDEO_ES, i_chroma ),
             p_chroma_desc->pixel_bits / 3, 3, p_chroma_desc->pixel_size );

    p_sys->p_client->MallocFrameBuffer = mallocFrameBufferHandler;
    p_sys->p_client->canHandleNewFBSize = TRUE;
    p_sys->p_client->GetCredential = getCredentialHandler;
    p_sys->p_client->GetPassword = getPasswordHandler; /* VNC simple auth */

    /* Set compression and quality levels */
    p_sys->p_client->appData.compressLevel =
            var_InheritInteger( p_demux, CFG_PREFIX "compress-level" );
    p_sys->p_client->appData.qualityLevel =
            var_InheritInteger( p_demux, CFG_PREFIX "quality-level" );

    /* Parse uri params */
    vlc_url_t url;
    vlc_UrlParse( &url, p_demux->psz_location );

    if ( !EMPTY_STR(url.psz_host) )
        p_sys->p_client->serverHost = strdup( url.psz_host );
    else
        p_sys->p_client->serverHost = strdup( "localhost" );

    p_sys->p_client->appData.viewOnly = TRUE;
    p_sys->p_client->serverPort = ( url.i_port > 0 ) ? url.i_port : 5900;

    msg_Dbg( p_demux, "VNC init %s host=%s port=%d",
             p_demux->psz_location,
             p_sys->p_client->serverHost,
             p_sys->p_client->serverPort );

    vlc_UrlClean( &url );

    /* make demux available for callback handlers */
    rfbClientSetClientData( p_sys->p_client, DemuxThread, p_demux );
    p_demux->p_sys = p_sys;

    if( !rfbInitClient( p_sys->p_client, NULL, NULL ) )
    {
        msg_Err( p_demux, "can't connect to RFB server" );
        return VLC_EGENERIC;
    }

    p_sys->i_starttime = vlc_tick_now();

    if ( vlc_clone( &p_sys->thread, DemuxThread, p_demux, VLC_THREAD_PRIORITY_INPUT ) != VLC_SUCCESS )
    {
        msg_Err( p_demux, "can't spawn thread" );
        return VLC_EGENERIC;
    }

    p_demux->pf_demux = NULL;
    p_demux->pf_control = Control;

    return VLC_SUCCESS;
}
예제 #8
0
/**
 * Allocates a new rfbClient instance given the parameters stored within the
 * client, returning NULL on failure.
 */
static rfbClient* __guac_vnc_get_client(guac_client* client) {

    rfbClient* rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */
    vnc_guac_client_data* guac_client_data =
        (vnc_guac_client_data*) client->data;

    /* Store Guac client in rfb client */
    rfbClientSetClientData(rfb_client, __GUAC_CLIENT, client);

    /* Framebuffer update handler */
    rfb_client->GotFrameBufferUpdate = guac_vnc_update;
    rfb_client->GotCopyRect = guac_vnc_copyrect;

    /* Do not handle clipboard and local cursor if read-only */
    if (guac_client_data->read_only == 0) {

        /* Clipboard */
        rfb_client->GotXCutText = guac_vnc_cut_text;

        /* Set remote cursor */
        if (guac_client_data->remote_cursor)
            rfb_client->appData.useRemoteCursor = FALSE;

        else {
            /* Enable client-side cursor */
            rfb_client->appData.useRemoteCursor = TRUE;
            rfb_client->GotCursorShape = guac_vnc_cursor;
        }
    }

    /* Password */
    rfb_client->GetPassword = guac_vnc_get_password;

    /* Depth */
    guac_vnc_set_pixel_format(rfb_client, guac_client_data->color_depth);

    /* Hook into allocation so we can handle resize. */
    guac_client_data->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer;
    rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer;
    rfb_client->canHandleNewFBSize = 1;

    /* Set hostname and port */
    rfb_client->serverHost = strdup(guac_client_data->hostname);
    rfb_client->serverPort = guac_client_data->port;

#ifdef ENABLE_VNC_REPEATER
    /* Set repeater parameters if specified */
    if (guac_client_data->dest_host) {
        rfb_client->destHost = strdup(guac_client_data->dest_host);
        rfb_client->destPort = guac_client_data->dest_port;
    }
#endif

#ifdef ENABLE_VNC_LISTEN
    /* If reverse connection enabled, start listening */
    if (guac_client_data->reverse_connect) {

        guac_client_log_info(client, "Listening for connections on port %i",
                guac_client_data->port);

        /* Listen for connection from server */
        rfb_client->listenPort = guac_client_data->port;
        if (listenForIncomingConnectionsNoFork(rfb_client,
                    guac_client_data->listen_timeout*1000) <= 0)
            return NULL;

    }
#endif

    /* Set encodings if provided */
    if (guac_client_data->encodings)
        rfb_client->appData.encodingsString =
            strdup(guac_client_data->encodings);

    /* Connect */
    if (rfbInitClient(rfb_client, NULL, NULL))
        return rfb_client;

    /* If connection fails, return NULL */
    return NULL;

}
예제 #9
0
void ItalcVncConnection::doConnection()
{
	QMutex sleeperMutex;

	while( !m_stopped && m_state != Connected ) // try to connect as long as the server allows
	{
		m_cl = rfbGetClient( 8, 3, 4 );
		m_cl->MallocFrameBuffer = hookNewClient;
		m_cl->canHandleNewFBSize = true;
		m_cl->GotFrameBufferUpdate = hookUpdateFB;
		m_cl->FinishedFrameBufferUpdate = hookFinishFrameBufferUpdate;
		m_cl->HandleCursorPos = hookHandleCursorPos;
		m_cl->GotCursorShape = hookCursorShape;
		m_cl->GotXCutText = hookCutText;
		rfbClientSetClientData( m_cl, 0, this );

		m_mutex.lock();

		if( m_port < 0 ) // port is invalid or empty...
		{
			m_port = PortOffsetVncServer;
		}

		if( m_port >= 0 && m_port < 100 )
		{
			 // the user most likely used the short form (e.g. :1)
			m_port += PortOffsetVncServer;
		}

		free( m_cl->serverHost );
		m_cl->serverHost = strdup( m_host.toUtf8().constData() );
		m_cl->serverPort = m_port;

		m_mutex.unlock();

		emit newClient( m_cl );

		int argc;
		if( rfbInitClient( m_cl, &argc, NULL ) )
		{
			emit connected();

			m_state = Connected;
			if( m_framebufferUpdateInterval < 0 )
			{
				rfbClientSetClientData( m_cl, (void *) 0x555, (void *) 1 );
			}
		}
		else
		{
			// guess reason why connection failed based on the state,
			// libvncclient left the rfbClient structure
			if( argc < 0 )
			{
				m_state = HostUnreachable;
			}
			else if( argc > 0 )
			{
				m_state = AuthenticationFailed;
			}
			else
			{
				// failed for an unknown reason
				m_state = ConnectionFailed;
			}

			// do not sleep when already requested to stop
			if( m_stopped )
			{
				break;
			}

			// wait a bit until next connect
			sleeperMutex.lock();
			if( m_framebufferUpdateInterval > 0 )
			{
				m_updateIntervalSleeper.wait( &sleeperMutex,
												m_framebufferUpdateInterval );
			}
			else
			{
				// default: retry every second
				m_updateIntervalSleeper.wait( &sleeperMutex, 1000 );
			}
			sleeperMutex.unlock();
		}
	}

	QTime lastFullUpdate = QTime::currentTime();

	// Main VNC event loop
	while( !m_stopped )
	{
		int timeout = 500;
		if( m_framebufferUpdateInterval < 0 )
		{
			timeout = 100*1000;	// 100 ms
		}
		const int i = WaitForMessage( m_cl, timeout );
		if( i < 0 )
		{
			break;
		}
		else if( i )
		{
			// read and process remaining messages many messages as available
			bool handledOkay = true;
			while( WaitForMessage( m_cl, 0 ) && handledOkay )
			{
				handledOkay = HandleRFBServerMessage( m_cl );
			}
			if( handledOkay == false )
			{
				break;
			}
		}
		else
		{
		/*	// work around a bug in UltraVNC on Win7 where it does not handle
			// incremental updates correctly
			int msecs = lastFullUpdate.msecsTo( QTime::currentTime() );
			if( ( m_framebufferUpdateInterval > 0 &&
					msecs > 10*m_framebufferUpdateInterval ) ||
				( m_framebufferUpdateInterval == 0 && msecs > 1000 ) )
			{
				SendFramebufferUpdateRequest( m_cl, 0, 0,
						framebufferSize().width(), framebufferSize().height(),
						false );
				lastFullUpdate = QTime::currentTime();
			}*/
		}

		m_mutex.lock();

		while( !m_eventQueue.isEmpty() )
		{
			ClientEvent * clientEvent = m_eventQueue.dequeue();

			// unlock the queue mutex during the runtime of ClientEvent::fire()
			m_mutex.unlock();

			clientEvent->fire( m_cl );
			delete clientEvent;

			// and lock it again
			m_mutex.lock();
		}

		m_mutex.unlock();

		if( m_framebufferUpdateInterval > 0 && m_stopped == false )
		{
			sleeperMutex.lock();
			m_updateIntervalSleeper.wait( &sleeperMutex,
												m_framebufferUpdateInterval );
			sleeperMutex.unlock();
		}
	}

	if( m_state == Connected && m_cl )
	{
		rfbClientCleanup( m_cl );
	}

	m_state = Disconnected;
}
예제 #10
0
void VncClientThread::run()
{
    QMutexLocker locker(&m_mutex);

    int passwd_failures = 0;
    while (!m_stopped) { // try to connect as long as the server allows
        m_passwordError = false;
        outputErrorMessageString.clear(); //don't deliver error messages of old instances...

        rfbClientLog = outputHandler;
        rfbClientErr = outputHandler;
        m_cl = rfbGetClient(8, 3, 4); // bitsPerSample, samplesPerPixel, bytesPerPixel
        m_cl->MallocFrameBuffer = newclient;
        m_cl->canHandleNewFBSize = true;
        m_cl->GetPassword = passwdHandler;
        m_cl->GotFrameBufferUpdate = updatefb;
        m_cl->GotXCutText = cuttext;
        rfbClientSetClientData(m_cl, 0, this);

        m_cl->serverHost = strdup(m_host.toUtf8().constData());

        if (m_port < 0 || !m_port) // port is invalid or empty...
            m_port = 5900; // fallback: try an often used VNC port

        if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1)
            m_port += 5900;
        m_cl->serverPort = m_port;

        m_cl->listenSpecified = rfbBool(m_listen_port > 0);
        m_cl->listenPort = m_listen_port;

        kDebug(5011) << "--------------------- trying init ---------------------";

        if (rfbInitClient(m_cl, 0, 0))
            break;

        //init failed...
        if (m_passwordError) {
            passwd_failures++;
            if(passwd_failures < 3)
                continue; //that's ok, try again
        }

        //stop connecting
        m_stopped = true;
        return; //no cleanup necessary, m_cl was free()d by rfbInitClient()
    }

    locker.unlock();

    // Main VNC event loop
    while (!m_stopped) {
        const int i = WaitForMessage(m_cl, 500);
        if(m_stopped or i < 0)
            break;

        if (i)
            if (!HandleRFBServerMessage(m_cl))
                break;

        locker.relock();

        while (!m_eventQueue.isEmpty()) {
            ClientEvent* clientEvent = m_eventQueue.dequeue();
            clientEvent->fire(m_cl);
            delete clientEvent;
        }

        locker.unlock();
    }

    // Cleanup allocated resources
    locker.relock();
    rfbClientCleanup(m_cl);
    m_stopped = true;
}
예제 #11
0
void VeyonCoreConnection::initNewClient( rfbClient *cl )
{
	rfbClientSetClientData( cl, VeyonCoreConnectionTag, this );
}
예제 #12
0
void VncClientThread::run()
{
    QMutexLocker locker(&mutex);

    while (!m_stopped) { // try to connect as long as the server allows
        m_passwordError = false;

        rfbClientLog = outputHandler;
        rfbClientErr = outputHandler;
        cl = rfbGetClient(8, 3, 4);
        cl->MallocFrameBuffer = newclient;
        cl->canHandleNewFBSize = true;
        cl->GetPassword = passwdHandler;
        cl->GotFrameBufferUpdate = updatefb;
        cl->GotXCutText = cuttext;
        rfbClientSetClientData(cl, 0, this);

        cl->serverHost = strdup(m_host.toUtf8().constData());

        if (m_port < 0 || !m_port) // port is invalid or empty...
            m_port = 5900; // fallback: try an often used VNC port

        if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1)
            m_port += 5900;
        cl->serverPort = m_port;

        kDebug(5011) << "--------------------- trying init ---------------------";

        if (rfbInitClient(cl, 0, 0))
            break;

        if (m_passwordError)
            continue;

        return;
    }

    locker.unlock();

    // Main VNC event loop
    while (!m_stopped) {
        const int i = WaitForMessage(cl, 500);
        if (i < 0)
            break;
        if (i)
            if (!HandleRFBServerMessage(cl))
                break;

        locker.relock();

        while (!m_eventQueue.isEmpty()) {
            ClientEvent* clientEvent = m_eventQueue.dequeue();
            clientEvent->fire(cl);
            delete clientEvent;
        }

        locker.unlock();
    }

    // Cleanup allocated resources
    locker.relock();
    rfbClientCleanup(cl);
    m_stopped = true;
}
예제 #13
0
int guac_client_init(guac_client* client, int argc, char** argv) {

    rfbClient* rfb_client;

    vnc_guac_client_data* guac_client_data;

    int read_only;

    /* Set up libvncclient logging */
    rfbClientLog = guac_vnc_client_log_info;
    rfbClientErr = guac_vnc_client_log_error;

    /*** PARSE ARGUMENTS ***/

    if (argc != VNC_ARGS_COUNT) {
        guac_protocol_send_error(client->socket, "Wrong argument count received.");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Alloc client data */
    guac_client_data = malloc(sizeof(vnc_guac_client_data));
    client->data = guac_client_data;

    /* Set read-only flag */
    read_only = (strcmp(argv[IDX_READ_ONLY], "true") == 0);

    /* Set red/blue swap flag */
    guac_client_data->swap_red_blue = (strcmp(argv[IDX_SWAP_RED_BLUE], "true") == 0);

    /* Freed after use by libvncclient */
    guac_client_data->password = strdup(argv[IDX_PASSWORD]);

    /*** INIT RFB CLIENT ***/

    rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */

    /* Store Guac client in rfb client */
    rfbClientSetClientData(rfb_client, __GUAC_CLIENT, client);

    /* Framebuffer update handler */
    rfb_client->GotFrameBufferUpdate = guac_vnc_update;
    rfb_client->GotCopyRect = guac_vnc_copyrect;

    /* Do not handle clipboard and local cursor if read-only */
    if (read_only == 0) {
        /* Enable client-side cursor */
        rfb_client->GotCursorShape = guac_vnc_cursor;
        rfb_client->appData.useRemoteCursor = TRUE;

        /* Clipboard */
        rfb_client->GotXCutText = guac_vnc_cut_text;
    }

    /* Password */
    rfb_client->GetPassword = guac_vnc_get_password;

    /* Depth */
    guac_vnc_set_pixel_format(rfb_client, atoi(argv[IDX_COLOR_DEPTH]));

#ifdef ENABLE_PULSE
    guac_client_data->audio_enabled =
        (strcmp(argv[IDX_ENABLE_AUDIO], "true") == 0);

    /* If an encoding is available, load an audio stream */
    if (guac_client_data->audio_enabled) {    

        guac_client_data->audio = guac_audio_stream_alloc(client, NULL);

        /* Load servername if specified */
        if (argv[IDX_AUDIO_SERVERNAME][0] != '\0')
            guac_client_data->pa_servername =
                strdup(argv[IDX_AUDIO_SERVERNAME]);
        else
            guac_client_data->pa_servername = NULL;

        /* If successful, init audio system */
        if (guac_client_data->audio != NULL) {
            
            guac_client_log_info(client,
                    "Audio will be encoded as %s",
                    guac_client_data->audio->encoder->mimetype);

            /* Require threadsafe sockets if audio enabled */
            guac_socket_require_threadsafe(client->socket);

            /* Start audio stream */
            guac_pa_start_stream(client);
            
        }

        /* Otherwise, audio loading failed */
        else
            guac_client_log_info(client,
                    "No available audio encoding. Sound disabled.");

    } /* end if audio enabled */
#endif

    /* Hook into allocation so we can handle resize. */
    guac_client_data->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer;
    rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer;
    rfb_client->canHandleNewFBSize = 1;

    /* Set hostname and port */
    rfb_client->serverHost = strdup(argv[0]);
    rfb_client->serverPort = atoi(argv[1]);

#ifdef ENABLE_VNC_REPEATER
    /* Set repeater parameters if specified */
    if(argv[IDX_DEST_HOST][0] != '\0')
        rfb_client->destHost = strdup(argv[IDX_DEST_HOST]);

    if(argv[IDX_DEST_PORT][0] != '\0')
        rfb_client->destPort = atoi(argv[IDX_DEST_PORT]);
#endif

    /* Set encodings if specified */
    if (argv[IDX_ENCODINGS][0] != '\0')
        rfb_client->appData.encodingsString = guac_client_data->encodings
            = strdup(argv[IDX_ENCODINGS]);
    else
        guac_client_data->encodings = NULL;

    /* Connect */

    if (!rfbInitClient(rfb_client, NULL, NULL)) {
        guac_protocol_send_error(client->socket, "Error initializing VNC client");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Set remaining client data */
    guac_client_data->rfb_client = rfb_client;
    guac_client_data->copy_rect_used = 0;
    guac_client_data->cursor = guac_client_alloc_buffer(client);

    /* Set handlers */
    client->handle_messages = vnc_guac_client_handle_messages;
    client->free_handler = vnc_guac_client_free_handler;
    if (read_only == 0) {
        /* Do not handle mouse/keyboard/clipboard if read-only */
        client->mouse_handler = vnc_guac_client_mouse_handler;
        client->key_handler = vnc_guac_client_key_handler;
        client->clipboard_handler = vnc_guac_client_clipboard_handler;
    }

    /* Send name */
    guac_protocol_send_name(client->socket, rfb_client->desktopName);

    /* Send size */
    guac_protocol_send_size(client->socket,
            GUAC_DEFAULT_LAYER, rfb_client->width, rfb_client->height);

    return 0;

}
예제 #14
0
int guac_client_init(guac_client* client, int argc, char** argv) {

    rfbClient* rfb_client;

    vnc_guac_client_data* guac_client_data;

    int read_only;

    /* Set up libvncclient logging */
    rfbClientLog = guac_vnc_client_log_info;
    rfbClientErr = guac_vnc_client_log_error;

    /*** PARSE ARGUMENTS ***/

    if (argc < 7) {
        guac_protocol_send_error(client->socket, "Wrong argument count received.");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Alloc client data */
    guac_client_data = malloc(sizeof(vnc_guac_client_data));
    client->data = guac_client_data;

    /* Set read-only flag */
    read_only = (strcmp(argv[2], "true") == 0);

    /* Set red/blue swap flag */
    guac_client_data->swap_red_blue = (strcmp(argv[5], "true") == 0);

    /* Freed after use by libvncclient */
    guac_client_data->password = strdup(argv[4]);

    /*** INIT RFB CLIENT ***/

    rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */

    /* Store Guac client in rfb client */
    rfbClientSetClientData(rfb_client, __GUAC_CLIENT, client);

    /* Framebuffer update handler */
    rfb_client->GotFrameBufferUpdate = guac_vnc_update;
    rfb_client->GotCopyRect = guac_vnc_copyrect;

    /* Do not handle clipboard and local cursor if read-only */
    if (read_only == 0) {
        /* Enable client-side cursor */
        rfb_client->GotCursorShape = guac_vnc_cursor;
        rfb_client->appData.useRemoteCursor = TRUE;

        /* Clipboard */
        rfb_client->GotXCutText = guac_vnc_cut_text;
    }

    /* Password */
    rfb_client->GetPassword = guac_vnc_get_password;

    /* Depth */
    guac_vnc_set_pixel_format(rfb_client, atoi(argv[6]));

    /* Hook into allocation so we can handle resize. */
    guac_client_data->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer;
    rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer;
    rfb_client->canHandleNewFBSize = 1;

    /* Set hostname and port */
    rfb_client->serverHost = strdup(argv[0]);
    rfb_client->serverPort = atoi(argv[1]);

    /* Set encodings if specified */
    if (argv[3][0] != '\0')
        rfb_client->appData.encodingsString = guac_client_data->encodings = strdup(argv[3]);
    else
        guac_client_data->encodings = NULL;

    /* Connect */
    if (!rfbInitClient(rfb_client, NULL, NULL)) {
        guac_protocol_send_error(client->socket, "Error initializing VNC client");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Set remaining client data */
    guac_client_data->rfb_client = rfb_client;
    guac_client_data->copy_rect_used = 0;
    guac_client_data->cursor = guac_client_alloc_buffer(client);

    /* Set handlers */
    client->handle_messages = vnc_guac_client_handle_messages;
    client->free_handler = vnc_guac_client_free_handler;
    if (read_only == 0) {
        /* Do not handle mouse/keyboard/clipboard if read-only */
        client->mouse_handler = vnc_guac_client_mouse_handler;
        client->key_handler = vnc_guac_client_key_handler;
        client->clipboard_handler = vnc_guac_client_clipboard_handler;
    }

    /* Send name */
    guac_protocol_send_name(client->socket, rfb_client->desktopName);

    /* Send size */
    guac_protocol_send_size(client->socket,
                            GUAC_DEFAULT_LAYER, rfb_client->width, rfb_client->height);

    return 0;

}