|
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 |
}
|