Blame client/iOS/FreeRDP/ios_freerdp_events.m

Packit 1fb8d4
/*
Packit 1fb8d4
 RDP event queuing 
Packit 1fb8d4
 
Packit 1fb8d4
 Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
Packit 1fb8d4
 
Packit 1fb8d4
 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 
Packit 1fb8d4
 If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#include "ios_freerdp_events.h"
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Sending compacted input events (from main thread)
Packit 1fb8d4
Packit 1fb8d4
// While this function may be called from any thread that has an autorelease pool allocated, it is not threadsafe: caller is responsible for synchronization
Packit 1fb8d4
BOOL ios_events_send(mfInfo* mfi, NSDictionary * event_description)
Packit 1fb8d4
{		
Packit 1fb8d4
	NSData * encoded_description = [NSKeyedArchiver archivedDataWithRootObject:event_description];
Packit 1fb8d4
	
Packit 1fb8d4
	if ([encoded_description length] > 32000 || (mfi->event_pipe_producer == -1) )
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	
Packit 1fb8d4
	uint32_t archived_data_len = (uint32_t)[encoded_description length];
Packit 1fb8d4
	
Packit 1fb8d4
	//NSLog(@"writing %d bytes to input event pipe", archived_data_len);
Packit 1fb8d4
	
Packit 1fb8d4
	if (write(mfi->event_pipe_producer, &archived_data_len, 4) == -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: Failed to write length descriptor to pipe.", __func__);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	if (write(mfi->event_pipe_producer, [encoded_description bytes], archived_data_len) == -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: Failed to write %d bytes into the event queue (event type: %@).", __func__, (int)[encoded_description length], [event_description objectForKey:@"type"]);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	return TRUE;	
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Processing compacted input events (from connection thread runloop)
Packit 1fb8d4
Packit 1fb8d4
static BOOL ios_events_handle_event(mfInfo* mfi, NSDictionary * event_description)
Packit 1fb8d4
{
Packit 1fb8d4
	NSString * event_type = [event_description objectForKey:@"type"];
Packit 1fb8d4
	BOOL should_continue = TRUE;
Packit 1fb8d4
	freerdp* instance = mfi->instance;
Packit 1fb8d4
	
Packit 1fb8d4
	if ([event_type isEqualToString:@"mouse"])
Packit 1fb8d4
	{        
Packit 1fb8d4
		instance->input->MouseEvent(instance->input, 
Packit 1fb8d4
                                    [[event_description objectForKey:@"flags"] unsignedShortValue],
Packit 1fb8d4
                                    [[event_description objectForKey:@"coord_x"] unsignedShortValue],
Packit 1fb8d4
                                    [[event_description objectForKey:@"coord_y"] unsignedShortValue]);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if ([event_type isEqualToString:@"keyboard"])
Packit 1fb8d4
	{
Packit 1fb8d4
		if ([[event_description objectForKey:@"subtype"] isEqualToString:@"scancode"])
Packit 1fb8d4
			instance->input->KeyboardEvent(instance->input, 
Packit 1fb8d4
                                           [[event_description objectForKey:@"flags"] unsignedShortValue],
Packit 1fb8d4
                                           [[event_description objectForKey:@"scancode"] unsignedShortValue]);
Packit 1fb8d4
		else if ([[event_description objectForKey:@"subtype"] isEqualToString:@"unicode"])
Packit 1fb8d4
			instance->input->UnicodeKeyboardEvent(instance->input,
Packit 1fb8d4
                                                  [[event_description objectForKey:@"flags"] unsignedShortValue],
Packit 1fb8d4
                                                  [[event_description objectForKey:@"unicode_char"] unsignedShortValue]);
Packit 1fb8d4
		else
Packit 1fb8d4
			NSLog(@"%s: doesn't know how to send keyboard input with subtype %@", __func__, [event_description objectForKey:@"subtype"]);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if ([event_type isEqualToString:@"disconnect"])
Packit 1fb8d4
		should_continue = FALSE;
Packit 1fb8d4
	else
Packit 1fb8d4
		NSLog(@"%s: unrecognized event type: %@", __func__, event_type);
Packit 1fb8d4
	
Packit 1fb8d4
	return should_continue;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ios_events_check_fds(mfInfo* mfi, fd_set* rfds)
Packit 1fb8d4
{	
Packit 1fb8d4
	if ( (mfi->event_pipe_consumer == -1) || !FD_ISSET(mfi->event_pipe_consumer, rfds))
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	
Packit 1fb8d4
	uint32_t archived_data_length = 0;
Packit 1fb8d4
	ssize_t bytes_read;
Packit 1fb8d4
	
Packit 1fb8d4
	// First, read the length of the blob
Packit 1fb8d4
	bytes_read = read(mfi->event_pipe_consumer, &archived_data_length, 4);
Packit 1fb8d4
	
Packit 1fb8d4
	if (bytes_read == -1 || archived_data_length < 1 || archived_data_length > 32000)
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: just read length descriptor. bytes_read=%ld, archived_data_length=%u", __func__, bytes_read, archived_data_length);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	//NSLog(@"reading %d bytes from input event pipe", archived_data_length);
Packit 1fb8d4
	
Packit 1fb8d4
	NSMutableData * archived_object_data = [[NSMutableData alloc] initWithLength:archived_data_length];
Packit 1fb8d4
	bytes_read = read(mfi->event_pipe_consumer, [archived_object_data mutableBytes], archived_data_length);
Packit 1fb8d4
	
Packit 1fb8d4
	if (bytes_read != archived_data_length)
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: attempted to read data; read %ld bytes but wanted %d bytes.", __func__, bytes_read, archived_data_length);
Packit 1fb8d4
		[archived_object_data release];
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	id unarchived_object_data = [NSKeyedUnarchiver unarchiveObjectWithData:archived_object_data];
Packit 1fb8d4
	[archived_object_data release];
Packit 1fb8d4
	
Packit 1fb8d4
	return ios_events_handle_event(mfi, unarchived_object_data);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ios_events_get_fds(mfInfo* mfi, void ** read_fds, int * read_count, void ** write_fds, int * write_count)
Packit 1fb8d4
{
Packit 1fb8d4
	read_fds[*read_count] = (void *)(long)(mfi->event_pipe_consumer);
Packit 1fb8d4
	(*read_count)++;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// Sets up the event pipe
Packit 1fb8d4
BOOL ios_events_create_pipe(mfInfo* mfi)
Packit 1fb8d4
{
Packit 1fb8d4
	int pipe_fds[2];
Packit 1fb8d4
	
Packit 1fb8d4
	if (pipe(pipe_fds) == -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: pipe failed.", __func__);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	mfi->event_pipe_consumer = pipe_fds[0];
Packit 1fb8d4
	mfi->event_pipe_producer = pipe_fds[1];
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void ios_events_free_pipe(mfInfo* mfi)
Packit 1fb8d4
{
Packit 1fb8d4
	int consumer_fd = mfi->event_pipe_consumer, producer_fd = mfi->event_pipe_producer;
Packit 1fb8d4
	
Packit 1fb8d4
	mfi->event_pipe_consumer = mfi->event_pipe_producer = -1;
Packit 1fb8d4
	close(producer_fd);
Packit 1fb8d4
	close(consumer_fd);	
Packit 1fb8d4
}