summaryrefslogtreecommitdiffstats
path: root/gst/librfb/rfbdecoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/librfb/rfbdecoder.c')
-rw-r--r--gst/librfb/rfbdecoder.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/gst/librfb/rfbdecoder.c b/gst/librfb/rfbdecoder.c
new file mode 100644
index 00000000..e8de9b06
--- /dev/null
+++ b/gst/librfb/rfbdecoder.c
@@ -0,0 +1,397 @@
+
+#include <rfb.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+
+#if 0
+struct _RfbSocketPrivate
+{
+ int fd;
+ sockaddr sa;
+}
+#endif
+
+
+static RfbBuffer *
+rfb_socket_get_buffer (int length, gpointer user_data)
+{
+ RfbBuffer *buffer;
+ int fd = (int) user_data;
+ int ret;
+
+ buffer = rfb_buffer_new ();
+
+ buffer->data = g_malloc (length);
+ buffer->free_data = (void *) g_free;
+
+ g_print ("calling read(%d, %p, %d)\n", fd, buffer->data, length);
+ ret = read (fd, buffer->data, length);
+ if (ret <= 0) {
+ g_critical ("read: %s", strerror (errno));
+ rfb_buffer_free (buffer);
+ return NULL;
+ }
+
+ buffer->length = ret;
+
+ return buffer;
+}
+
+static int
+rfb_socket_send_buffer (guint8 * buffer, int length, gpointer user_data)
+{
+ int fd = (int) user_data;
+ int ret;
+
+ g_print ("calling write(%d, %p, %d)\n", fd, buffer, length);
+ ret = write (fd, buffer, length);
+ if (ret < 0) {
+ g_critical ("write: %s", strerror (errno));
+ return 0;
+ }
+
+ g_assert (ret == length);
+
+ return ret;
+}
+
+
+RfbDecoder *
+rfb_decoder_new (void)
+{
+ RfbDecoder *decoder = g_new0 (RfbDecoder, 1);
+
+ decoder->bytestream = rfb_bytestream_new ();
+
+ return decoder;
+}
+
+void
+rfb_decoder_use_file_descriptor (RfbDecoder * decoder, int fd)
+{
+ g_return_if_fail (decoder != NULL);
+ g_return_if_fail (!decoder->inited);
+ g_return_if_fail (fd >= 0);
+
+ decoder->bytestream->get_buffer = rfb_socket_get_buffer;
+ decoder->bytestream->user_data = (void *) fd;
+
+ decoder->send_data = rfb_socket_send_buffer;
+ decoder->buffer_handler_data = (void *) fd;
+}
+
+void
+rfb_decoder_connect_tcp (RfbDecoder * decoder, char *addr, unsigned int port)
+{
+ int fd;
+ struct sockaddr_in sa;
+
+ fd = socket (PF_INET, SOCK_STREAM, 0);
+
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (port);
+ inet_pton (AF_INET, addr, &sa.sin_addr);
+ connect (fd, (struct sockaddr *) &sa, sizeof (struct sockaddr));
+
+ rfb_decoder_use_file_descriptor (decoder, fd);
+}
+
+
+static gboolean rfb_decoder_state_wait_for_protocol_version (RfbDecoder *
+ decoder);
+static gboolean rfb_decoder_state_wait_for_security (RfbDecoder * decoder);
+static gboolean rfb_decoder_state_send_client_initialisation (RfbDecoder *
+ decoder);
+static gboolean rfb_decoder_state_wait_for_server_initialisation (RfbDecoder *
+ decoder);
+static gboolean rfb_decoder_state_normal (RfbDecoder * decoder);
+static gboolean rfb_decoder_state_framebuffer_update (RfbDecoder * decoder);
+static gboolean rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder *
+ decoder);
+static gboolean rfb_decoder_state_set_colour_map_entries (RfbDecoder * decoder);
+static gboolean rfb_decoder_state_server_cut_text (RfbDecoder * decoder);
+
+gboolean
+rfb_decoder_iterate (RfbDecoder * decoder)
+{
+ g_return_val_if_fail (decoder != NULL, FALSE);
+
+ if (decoder->state == NULL) {
+ decoder->state = rfb_decoder_state_wait_for_protocol_version;
+ }
+
+ g_print ("iterating...\n");
+
+ return decoder->state (decoder);
+}
+
+#define RFB_GET_UINT32(ptr) GUINT32_FROM_BE (*(guint32 *)(ptr))
+#define RFB_GET_UINT16(ptr) GUINT16_FROM_BE (*(guint16 *)(ptr))
+#define RFB_GET_UINT8(ptr) (*(guint8 *)(ptr))
+
+#define RFB_SET_UINT32(ptr, val) (*(guint32 *)(ptr) = GUINT32_TO_BE (val))
+#define RFB_SET_UINT16(ptr, val) (*(guint16 *)(ptr) = GUINT16_TO_BE (val))
+#define RFB_SET_UINT8(ptr, val) (*(guint8 *)(ptr) = val)
+
+static gboolean
+rfb_decoder_state_wait_for_protocol_version (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ guint8 *data;
+ int ret;
+
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, 12);
+ if (ret < 12)
+ return FALSE;
+
+ data = buffer->data;
+
+ g_assert (memcmp (buffer->data, "RFB 003.00", 10) == 0);
+ g_print ("\"%.11s\"\n", buffer->data);
+ rfb_buffer_free (buffer);
+
+ rfb_decoder_send (decoder, "RFB 003.003\n", 12);
+
+ decoder->state = rfb_decoder_state_wait_for_security;
+
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_wait_for_security (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ int ret;
+
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, 4);
+ if (ret < 4)
+ return FALSE;
+
+ decoder->security_type = RFB_GET_UINT32 (buffer->data);
+ g_print ("security = %d\n", decoder->security_type);
+
+ rfb_buffer_free (buffer);
+
+ decoder->state = rfb_decoder_state_send_client_initialisation;
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_send_client_initialisation (RfbDecoder * decoder)
+{
+ guint8 shared_flag;
+
+ shared_flag = decoder->shared_flag;
+ rfb_decoder_send (decoder, &shared_flag, 1);
+
+ decoder->state = rfb_decoder_state_wait_for_server_initialisation;
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_wait_for_server_initialisation (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ guint8 *data;
+ int ret;
+ guint32 name_length;
+
+ ret = rfb_bytestream_peek (decoder->bytestream, &buffer, 24);
+ if (ret < 24)
+ return FALSE;
+
+ data = buffer->data;
+
+ decoder->width = RFB_GET_UINT16 (data + 0);
+ decoder->height = RFB_GET_UINT16 (data + 2);
+ decoder->bpp = RFB_GET_UINT8 (data + 4);
+ decoder->depth = RFB_GET_UINT8 (data + 5);
+ decoder->big_endian = RFB_GET_UINT8 (data + 6);
+ decoder->true_colour = RFB_GET_UINT8 (data + 7);
+ decoder->red_max = RFB_GET_UINT16 (data + 8);
+ decoder->green_max = RFB_GET_UINT16 (data + 10);
+ decoder->blue_max = RFB_GET_UINT16 (data + 12);
+ decoder->red_shift = RFB_GET_UINT8 (data + 14);
+ decoder->green_shift = RFB_GET_UINT8 (data + 15);
+ decoder->blue_shift = RFB_GET_UINT8 (data + 16);
+
+ g_print ("width: %d\n", decoder->width);
+ g_print ("height: %d\n", decoder->height);
+
+ name_length = RFB_GET_UINT32 (data + 20);
+ rfb_buffer_free (buffer);
+
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, 24 + name_length);
+ if (ret < 24 + name_length)
+ return FALSE;
+
+ decoder->name = g_strndup ((char *) (buffer->data) + 24, name_length);
+ g_print ("name: %s\n", decoder->name);
+ rfb_buffer_free (buffer);
+
+ decoder->state = rfb_decoder_state_normal;
+ decoder->inited = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_normal (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ int ret;
+ int message_type;
+
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, 1);
+ message_type = RFB_GET_UINT8 (buffer->data);
+
+ switch (message_type) {
+ case 0:
+ decoder->state = rfb_decoder_state_framebuffer_update;
+ break;
+ case 1:
+ decoder->state = rfb_decoder_state_set_colour_map_entries;
+ break;
+ case 2:
+ /* bell, ignored */
+ decoder->state = rfb_decoder_state_normal;
+ break;
+ case 3:
+ decoder->state = rfb_decoder_state_server_cut_text;
+ break;
+ default:
+ g_critical ("unknown message type %d", message_type);
+ }
+
+ rfb_buffer_free (buffer);
+
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_framebuffer_update (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ int ret;
+
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, 3);
+
+ decoder->n_rects = RFB_GET_UINT16 (buffer->data + 1);
+ decoder->state = rfb_decoder_state_framebuffer_update_rectangle;
+
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder)
+{
+ RfbBuffer *buffer;
+ int ret;
+ int x, y, w, h;
+ int encoding;
+ int size;
+
+ ret = rfb_bytestream_peek (decoder->bytestream, &buffer, 12);
+ if (ret < 12)
+ return FALSE;
+
+ x = RFB_GET_UINT16 (buffer->data + 0);
+ y = RFB_GET_UINT16 (buffer->data + 2);
+ w = RFB_GET_UINT16 (buffer->data + 4);
+ h = RFB_GET_UINT16 (buffer->data + 6);
+ encoding = RFB_GET_UINT32 (buffer->data + 8);
+
+ if (encoding != 0)
+ g_critical ("unimplemented encoding\n");
+
+ rfb_buffer_free (buffer);
+
+ size = w * h;
+ ret = rfb_bytestream_read (decoder->bytestream, &buffer, size + 12);
+ if (ret < size)
+ return FALSE;
+
+ if (decoder->paint_rect) {
+ decoder->paint_rect (decoder, x, y, w, h, buffer->data + 12);
+ }
+
+ rfb_buffer_free (buffer);
+
+ decoder->n_rects--;
+ if (decoder->n_rects == 0) {
+ decoder->state = rfb_decoder_state_normal;
+ }
+ return TRUE;
+}
+
+static gboolean
+rfb_decoder_state_set_colour_map_entries (RfbDecoder * decoder)
+{
+ g_critical ("not implemented");
+
+ return FALSE;
+}
+
+static gboolean
+rfb_decoder_state_server_cut_text (RfbDecoder * decoder)
+{
+ g_critical ("not implemented");
+
+ return FALSE;
+}
+
+
+void
+rfb_decoder_send_update_request (RfbDecoder * decoder,
+ gboolean incremental, int x, int y, int width, int height)
+{
+ guint8 data[10];
+
+ data[0] = 3;
+ data[1] = incremental;
+ RFB_SET_UINT16 (data + 2, x);
+ RFB_SET_UINT16 (data + 4, y);
+ RFB_SET_UINT16 (data + 6, width);
+ RFB_SET_UINT16 (data + 8, height);
+
+ rfb_decoder_send (decoder, data, 10);
+}
+
+void
+rfb_decoder_send_key_event (RfbDecoder * decoder, unsigned int key,
+ gboolean down_flag)
+{
+ guint8 data[8];
+
+ data[0] = 4;
+ data[1] = down_flag;
+ RFB_SET_UINT16 (data + 2, 0);
+ RFB_SET_UINT32 (data + 4, key);
+
+ rfb_decoder_send (decoder, data, 8);
+}
+
+void
+rfb_decoder_send_pointer_event (RfbDecoder * decoder,
+ int button_mask, int x, int y)
+{
+ guint8 data[6];
+
+ data[0] = 5;
+ data[1] = button_mask;
+ RFB_SET_UINT16 (data + 2, x);
+ RFB_SET_UINT16 (data + 4, y);
+
+ rfb_decoder_send (decoder, data, 6);
+}
+
+int
+rfb_decoder_send (RfbDecoder * decoder, guint8 * buffer, int len)
+{
+ return decoder->send_data (buffer, len, decoder->buffer_handler_data);
+}