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