librdesktop development + request to join as developer

Vic Lee <[email protected]>
Newsgroups gmane.network.rdesktop.devel
Message-ID <[email protected]>
Hi rdesktop project managers,

I am working on converting librdesktop into a library and I am already
about 80% done.

Although there's still some work to do before it's fully functional, I
think it's quite ready for experimental or reviewing purpose. I would
like to request to become a developer in advanced so that I can commit
changes as a separated sub-project "librdesktop".

My sourceforge.net user name is "llyzs".

I attached the current include file for the library, and a working GTK+
example for your preview. And also a draft README for general
information.

Thanks,

Vic

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july

_______________________________________________
rdesktop-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rdesktop-devel
rdesktop.h (text/x-chdr, 5.2 KB)
/* -*- c-basic-offset: 8 -*-
   librdesktop: A Remote Desktop Protocol client library.
   Copyright (C) Vic Lee 2009

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __LIBRDESKTOP_RDESKTOP_H__
#define __LIBRDESKTOP_RDESKTOP_H__

#ifdef __cplusplus
extern "C" {
#endif

/* A definition of the main object, hiding all private implementations */
typedef struct _RDesktopClientStruct RDesktopClientStruct;
typedef RDesktopClientStruct* RDesktopClient;

typedef enum
{
	RDESKTOP_OPTION_SERVER, /* string */
	RDESKTOP_OPTION_PORT, /* int */
	RDESKTOP_OPTION_USERNAME, /* string */
	RDESKTOP_OPTION_PASSWORD, /* string */
	RDESKTOP_OPTION_DOMAIN, /* string */
	RDESKTOP_OPTION_SHELL, /* string */
	RDESKTOP_OPTION_DIRECTORY, /* string */
	RDESKTOP_OPTION_CLIENT_HOSTNAME, /* string */
	RDESKTOP_OPTION_CODEPAGE, /* string */
	RDESKTOP_OPTION_WIDTH, /* int */
	RDESKTOP_OPTION_HEIGHT, /* int */
	RDESKTOP_OPTION_COLOR_DEPTH, /* int */
	RDESKTOP_OPTION_BITMAP_CACHE, /* bool */
	RDESKTOP_OPTION_BITMAP_CACHE_PERSIST, /* bool */
	RDESKTOP_OPTION_ENCRYPTION, /* bool */
	RDESKTOP_OPTION_PACKET_ENCRYPTION, /* bool */
	RDESKTOP_OPTION_NUMLOCK_SYNC, /* bool */
	RDESKTOP_OPTION_COMPRESSION, /* bool */
	RDESKTOP_OPTION_RDP5_NO_WALLPAPER, /* bool */
	RDESKTOP_OPTION_RDP5_NO_FULLWINDOWDRAG, /* bool */
	RDESKTOP_OPTION_RDP5_NO_MENUANIMATIONS, /* bool */
	RDESKTOP_OPTION_RDP5_NO_THEMING, /* bool */
	RDESKTOP_OPTION_RDP5_NO_CURSOR_SHADOW, /* bool */
	RDESKTOP_OPTION_RDP5_NO_CURSORSETTINGS, /* bool */
	RDESKTOP_OPTION_SOUND_REMOTE, /* bool */
	RDESKTOP_OPTION_SOUND_LOCAL, /* string */
	RDESKTOP_OPTION_LSPCI_ENABLED, /* bool */
	RDESKTOP_OPTION_CONSOLE_SESSION, /* bool */
	RDESKTOP_OPTION_RDP_VERSION, /* int */
	RDESKTOP_OPTION_LOG_LEVEL, /* RDesktopLogType */
} RDesktopOptionType;

typedef void* RDesktopOptionValue;
#define RDESKTOP_OPTION_VALUE(v) ((RDesktopOptionValue)v)

typedef enum
{
	RDESKTOP_DEVICE_TYPE_SERIAL,
	RDESKTOP_DEVICE_TYPE_PARALLEL,
	RDESKTOP_DEVICE_TYPE_PRINTER,
	RDESKTOP_DEVICE_TYPE_DISK,
	RDESKTOP_DEVICE_TYPE_SCARD
} RDesktopDeviceType;

typedef enum
{
	RDESKTOP_LOG_SILENT = 0,
	RDESKTOP_LOG_ERROR = 1,
	RDESKTOP_LOG_WARNING = 2,
	RDESKTOP_LOG_INFO = 3,
	RDESKTOP_LOG_DEBUG = 4
} RDesktopLogType;

typedef enum
{
	RDESKTOP_CALLBACK_LOG,
	RDESKTOP_CALLBACK_BITMAP
} RDesktopCallbackType;

typedef void (*RDesktopCallback)(void);
#define RDESKTOP_CALLBACK(v) ((RDesktopCallback)v)

typedef void (*RDesktopCallbackLog)(RDesktopClient rdc, RDesktopLogType t, const char *fmt, ...);
typedef void (*RDesktopCallbackBitmap)(RDesktopClient rdc, int x, int y, int width, int height, int rowstride, const unsigned char *data);

/* Create a new RDesktopClient object */
RDesktopClient librdesktop_new(void);

/* Set an RDesktopClient option */
void librdesktop_set_option(RDesktopClient rdc, RDesktopOptionType t, RDesktopOptionValue val);

/* Set an RDesktopClient callback function */
void librdesktop_set_callback(RDesktopClient rdc, RDesktopCallbackType t, RDesktopCallback func);

/* Add a device to be shared */
void librdesktop_add_device(RDesktopClient rdc, RDesktopDeviceType t, const char *name, const char *val);

/* Initialize the connection. Call after setting all options and devices */
void librdesktop_init(RDesktopClient rdc);

/* Start the connection. Returns 0 if succeed */
int librdesktop_connect(RDesktopClient rdc);

/* The main process function. Returns 0 if the connection is still active. Application should put it in a loop. */
int librdesktop_process_events(RDesktopClient rdc);

/* Free all resources associated with the RDesktopClient object */
void librdesktop_free(RDesktopClient rdc);

/* Set the user data */
void librdesktop_set_user_data(RDesktopClient rdc, void *user_data);

/* Get the user data */
void * librdesktop_get_user_data(RDesktopClient rdc);

/* Get the server width */
int librdesktop_get_width(RDesktopClient rdc);

/* Get the server height */
int librdesktop_get_height(RDesktopClient rdc);

/* Get the server depth */
int librdesktop_get_depth(RDesktopClient rdc);

/* Get the frame buffer */
const unsigned char * librdesktop_get_frame_buffer(RDesktopClient rdc, int x, int y);

/* Get the rowstride value */
int librdesktop_get_rowstride(RDesktopClient rdc);

/* Send mouse motion event */
void librdesktop_send_motion(RDesktopClient rdc, int x, int y);

/* Send mouse button event */
void librdesktop_send_button(RDesktopClient rdc, int button, int down, int x, int y);

/* Send keyboard scancode event */
void librdesktop_send_scancode(RDesktopClient rdc, int scancode, int down);

/* Send keyboard unicode event */
void librdesktop_send_unicode(RDesktopClient rdc, int unicode);

#ifdef __cplusplus
}
#endif

#endif /* __LIBRDESKTOP_RDESKTOP_H__ */
test-gtk.c (text/x-csrc, 5.4 KB)
/* -*- c-basic-offset: 8 -*-
   librdesktop: A Remote Desktop Protocol client library.

   Copyright (C) Vic Lee 2009

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <pthread.h>
#include "rdesktop/rdesktop.h"

static void
print_usage(const char *prog)
{
	printf("Usage: %s [-u username] [-p password] [-d domain] [-a depth] server\n", prog);
}

static void
update_rect(RDesktopClient rdc, int x, int y, int width, int height, int rowstride, const unsigned char *data)
{
	GtkWidget *drawing_area;

	drawing_area = GTK_WIDGET(librdesktop_get_user_data(rdc));

	gdk_threads_enter();
    gdk_draw_rgb_image (drawing_area->window, drawing_area->style->white_gc,
        x, y,
        width, height,
        GDK_RGB_DITHER_MAX,
        data,
        rowstride);
	gdk_threads_leave();
}

static gpointer
rdp_thread (gpointer data)
{
	RDesktopClient rdc = (RDesktopClient) data;

	if (librdesktop_connect(rdc) == 0)
	{
		while (librdesktop_process_events(rdc) == 0)
		{
		}
	}

	gdk_threads_enter();
	gtk_main_quit();
	gdk_threads_leave();

	librdesktop_free(rdc);
	return NULL;
}

static gboolean
on_expose (GtkWidget *drawing_area, GdkEventExpose *event, RDesktopClient rdc)
{
	const unsigned char *data;
	int rowstride;

	data = librdesktop_get_frame_buffer(rdc, event->area.x, event->area.y);
	rowstride = librdesktop_get_rowstride(rdc);
    gdk_draw_rgb_image (drawing_area->window, drawing_area->style->white_gc,
        event->area.x, event->area.y,
        event->area.width, event->area.height,
        GDK_RGB_DITHER_MAX,
        data,
        rowstride);
	return TRUE;
}

static gboolean
on_motion (GtkWidget *widget, GdkEventMotion *event, RDesktopClient rdc)
{
	librdesktop_send_motion(rdc, event->x, event->y);
    return TRUE;
}

static gboolean
on_button (GtkWidget *widget, GdkEventButton *event, RDesktopClient rdc)
{
	librdesktop_send_button(rdc, event->button, (event->type == GDK_BUTTON_PRESS ? 1 : 0), event->x, event->y);
    return TRUE;
}

static gboolean
on_key (GtkWidget *widget, GdkEventKey *event, RDesktopClient rdc)
{
	/* TODO */
    return TRUE;
}

int
main(int argc, char *argv[])
{
	RDesktopClient rdc;
	int c;
	char *prog;
	GtkWidget *window;
	GtkWidget *drawing_area;
	pthread_t thread;

	prog = argv[0];

	/* Initialize GTK+ */
    g_thread_init (NULL);
    gdk_threads_init ();
    gtk_init (&argc, &argv);

	/* Initialize the RDesktopClient object */
	rdc = librdesktop_new();

	while ((c = getopt(argc, argv, "a:d:p:u:")) != -1)
	{
		switch (c)
		{
		case 'a':
			librdesktop_set_option(rdc, RDESKTOP_OPTION_COLOR_DEPTH, RDESKTOP_OPTION_VALUE(atoi(optarg)));
			break;
		case 'd':
			librdesktop_set_option(rdc, RDESKTOP_OPTION_DOMAIN, RDESKTOP_OPTION_VALUE(optarg));
			break;
		case 'p':
			librdesktop_set_option(rdc, RDESKTOP_OPTION_PASSWORD, RDESKTOP_OPTION_VALUE(optarg));
			break;
		case 'u':
			librdesktop_set_option(rdc, RDESKTOP_OPTION_USERNAME, RDESKTOP_OPTION_VALUE(optarg));
			break;
		}
	}
	if (optind >= argc)
	{
		librdesktop_free(rdc);
		print_usage(prog);
		return -1;
	}
	librdesktop_set_option(rdc, RDESKTOP_OPTION_SERVER, RDESKTOP_OPTION_VALUE(argv[optind]));
	librdesktop_set_option(rdc, RDESKTOP_OPTION_LOG_LEVEL, RDESKTOP_OPTION_VALUE(RDESKTOP_LOG_DEBUG));

	librdesktop_set_callback(rdc, RDESKTOP_CALLBACK_BITMAP, RDESKTOP_CALLBACK(update_rect));

	/* Create the GTK+ widgets */
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	drawing_area = gtk_drawing_area_new();
	gtk_widget_set_size_request(drawing_area, librdesktop_get_width(rdc), librdesktop_get_height(rdc));
	gtk_container_add(GTK_CONTAINER(window), drawing_area);

    gtk_widget_add_events (drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
        | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
    GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);

	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
	g_signal_connect(G_OBJECT(drawing_area), "expose_event", G_CALLBACK(on_expose), rdc);
	g_signal_connect(G_OBJECT(drawing_area), "motion-notify-event", G_CALLBACK(on_motion), rdc);
	g_signal_connect(G_OBJECT(drawing_area), "button-press-event", G_CALLBACK(on_button), rdc);
	g_signal_connect(G_OBJECT(drawing_area), "button-release-event", G_CALLBACK(on_button), rdc);
	g_signal_connect(G_OBJECT(drawing_area), "key-press-event", G_CALLBACK(on_key), rdc);
	g_signal_connect(G_OBJECT(drawing_area), "key-release-event", G_CALLBACK(on_key), rdc);

	gtk_widget_show_all(window);

	/* Create the relationship between librdesktop and the GTK+ drawing area widget */
	librdesktop_set_user_data(rdc, drawing_area);

	librdesktop_init(rdc);

    if (pthread_create(&thread, NULL, rdp_thread, rdc))
    {
		fprintf(stderr, "Error creating pthread.\n");
	}

	gdk_threads_enter();
	gtk_main();
	gdk_threads_leave();

	return 0;
}
README (text/x-readme, 941 B)
librdesktop is ripped out from the original rdesktop project to provide a simple RDP client API.

1. What librdesktop is intended to be
o Binary-compatibility across versions
o Multi-threaded application supportibility
o Simplicity
o Portability

2. What librdesktop won't support
o X11: It works as a general frame buffer library. It should not, and will not depend on X11, or any other windowing systems or UI toolkits.
o RDP2VNC: It seems pointless for an RDP client library
o Seamless: It seems pointless as well

3. What librdesktop does not yet support
o Smartcard

4. Library function naming convention:
o librdesktop_*: API functions that will be used directly by applications.
o _librdesktop_*: internal library functions.
Library functions always takes RDesktopClient reference as the first argument. Most original rdesktop functions have been converted to use a prefix, with only small amount of utility functions as exceptions.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.