FreeRDP
Loading...
Searching...
No Matches
ios_freerdp_events.m
1/*
2 RDP event queuing
3
4 Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
5
6 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7 If a copy of the MPL was not distributed with this file, You can obtain one at
8 http://mozilla.org/MPL/2.0/.
9 */
10
11#include <winpr/assert.h>
12
13#include "ios_freerdp_events.h"
14
15#pragma mark -
16#pragma mark Sending compacted input events (from main thread)
17
18// While this function may be called from any thread that has an autorelease pool allocated, it is
19// not threadsafe: caller is responsible for synchronization
20BOOL ios_events_send(mfInfo *mfi, NSDictionary *event_description)
21{
22 NSData *encoded_description = [NSKeyedArchiver archivedDataWithRootObject:event_description];
23
24 WINPR_ASSERT(mfi);
25
26 if ([encoded_description length] > 32000 || (mfi->event_pipe_producer == -1))
27 return FALSE;
28
29 uint32_t archived_data_len = (uint32_t)[encoded_description length];
30
31 // NSLog(@"writing %d bytes to input event pipe", archived_data_len);
32
33 if (write(mfi->event_pipe_producer, &archived_data_len, 4) == -1)
34 {
35 NSLog(@"%s: Failed to write length descriptor to pipe.", __func__);
36 return FALSE;
37 }
38
39 if (write(mfi->event_pipe_producer, [encoded_description bytes], archived_data_len) == -1)
40 {
41 NSLog(@"%s: Failed to write %d bytes into the event queue (event type: %@).", __func__,
42 (int)[encoded_description length], [event_description objectForKey:@"type"]);
43 return FALSE;
44 }
45
46 return TRUE;
47}
48
49#pragma mark -
50#pragma mark Processing compacted input events (from connection thread runloop)
51
52static BOOL ios_events_handle_event(mfInfo *mfi, NSDictionary *event_description)
53{
54 NSString *event_type = [event_description objectForKey:@"type"];
55 BOOL should_continue = TRUE;
56 rdpInput *input;
57
58 WINPR_ASSERT(mfi);
59
60 freerdp *instance = mfi->instance;
61 WINPR_ASSERT(instance);
62 WINPR_ASSERT(instance->context);
63
64 input = instance->context->input;
65 WINPR_ASSERT(input);
66
67 if ([event_type isEqualToString:@"mouse"])
68 {
69 if (!input->MouseEvent(input,
70 [[event_description objectForKey:@"flags"] unsignedShortValue],
71 [[event_description objectForKey:@"coord_x"] unsignedShortValue],
72 [[event_description objectForKey:@"coord_y"] unsignedShortValue]))
73 {
74 // Returning an error here can terminate the connection.
75 NSLog(@"%s: MouseEvent failed.", __func__);
76 }
77 }
78 else if ([event_type isEqualToString:@"keyboard"])
79 {
80 if ([[event_description objectForKey:@"subtype"] isEqualToString:@"scancode"])
81 freerdp_input_send_keyboard_event(
82 input, [[event_description objectForKey:@"flags"] unsignedShortValue],
83 [[event_description objectForKey:@"scancode"] unsignedShortValue]);
84 else if ([[event_description objectForKey:@"subtype"] isEqualToString:@"unicode"])
85 freerdp_input_send_unicode_keyboard_event(
86 input, [[event_description objectForKey:@"flags"] unsignedShortValue],
87 [[event_description objectForKey:@"unicode_char"] unsignedShortValue]);
88 else
89 NSLog(@"%s: doesn't know how to send keyboard input with subtype %@", __func__,
90 [event_description objectForKey:@"subtype"]);
91 }
92 else if ([event_type isEqualToString:@"disconnect"])
93 should_continue = FALSE;
94 else
95 NSLog(@"%s: unrecognized event type: %@", __func__, event_type);
96
97 return should_continue;
98}
99
100BOOL ios_events_check_handle(mfInfo *mfi)
101{
102 WINPR_ASSERT(mfi);
103
104 if (WaitForSingleObject(mfi->handle, 0) != WAIT_OBJECT_0)
105 return TRUE;
106
107 if (mfi->event_pipe_consumer == -1)
108 return TRUE;
109
110 uint32_t archived_data_length = 0;
111 ssize_t bytes_read;
112
113 // First, read the length of the blob
114 bytes_read = read(mfi->event_pipe_consumer, &archived_data_length, 4);
115
116 if (bytes_read == -1 || archived_data_length < 1 || archived_data_length > 32000)
117 {
118 NSLog(@"%s: just read length descriptor. bytes_read=%ld, archived_data_length=%u", __func__,
119 bytes_read, archived_data_length);
120 return FALSE;
121 }
122
123 // NSLog(@"reading %d bytes from input event pipe", archived_data_length);
124
125 NSMutableData *archived_object_data =
126 [[NSMutableData alloc] initWithLength:archived_data_length];
127 bytes_read =
128 read(mfi->event_pipe_consumer, [archived_object_data mutableBytes], archived_data_length);
129
130 if (bytes_read != archived_data_length)
131 {
132 NSLog(@"%s: attempted to read data; read %ld bytes but wanted %d bytes.", __func__,
133 bytes_read, archived_data_length);
134 [archived_object_data release];
135 return FALSE;
136 }
137
138 id unarchived_object_data = [NSKeyedUnarchiver unarchiveObjectWithData:archived_object_data];
139 [archived_object_data release];
140
141 return ios_events_handle_event(mfi, unarchived_object_data);
142}
143
144HANDLE ios_events_get_handle(mfInfo *mfi)
145{
146 WINPR_ASSERT(mfi);
147 return mfi->handle;
148}
149
150// Sets up the event pipe
151BOOL ios_events_create_pipe(mfInfo *mfi)
152{
153 int pipe_fds[2];
154
155 WINPR_ASSERT(mfi);
156
157 if (pipe(pipe_fds) == -1)
158 {
159 NSLog(@"%s: pipe failed.", __func__);
160 return FALSE;
161 }
162
163 mfi->event_pipe_consumer = pipe_fds[0];
164 mfi->event_pipe_producer = pipe_fds[1];
165 mfi->handle = CreateFileDescriptorEvent(nullptr, FALSE, FALSE, mfi->event_pipe_consumer,
166 WINPR_FD_READ | WINPR_FD_WRITE);
167 return TRUE;
168}
169
170void ios_events_free_pipe(mfInfo *mfi)
171{
172 WINPR_ASSERT(mfi);
173 int consumer_fd = mfi->event_pipe_consumer, producer_fd = mfi->event_pipe_producer;
174
175 mfi->event_pipe_consumer = mfi->event_pipe_producer = -1;
176 close(producer_fd);
177 close(consumer_fd);
178 (void)CloseHandle(mfi->handle);
179}