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 NSError *error = nil;
23 NSData *encoded_description = [NSKeyedArchiver archivedDataWithRootObject:event_description
24 requiringSecureCoding:YES
25 error:&error];
26
27 if (!encoded_description)
28 {
29 NSLog(@"%s: Failed to archive event (type: %@): %@", __func__,
30 [event_description objectForKey:@"type"], error);
31 return FALSE;
32 }
33
34 WINPR_ASSERT(mfi);
35
36 if ([encoded_description length] > 32000 || (mfi->event_pipe_producer == -1))
37 return FALSE;
38
39 uint32_t archived_data_len = (uint32_t)[encoded_description length];
40
41 // NSLog(@"writing %d bytes to input event pipe", archived_data_len);
42
43 if (write(mfi->event_pipe_producer, &archived_data_len, 4) == -1)
44 {
45 NSLog(@"%s: Failed to write length descriptor to pipe.", __func__);
46 return FALSE;
47 }
48
49 if (write(mfi->event_pipe_producer, [encoded_description bytes], archived_data_len) == -1)
50 {
51 NSLog(@"%s: Failed to write %d bytes into the event queue (event type: %@).", __func__,
52 (int)[encoded_description length], [event_description objectForKey:@"type"]);
53 return FALSE;
54 }
55
56 return TRUE;
57}
58
59#pragma mark -
60#pragma mark Processing compacted input events (from connection thread runloop)
61
62static BOOL ios_events_handle_event(mfInfo *mfi, NSDictionary *event_description)
63{
64 NSString *event_type = [event_description objectForKey:@"type"];
65 BOOL should_continue = TRUE;
66 rdpInput *input;
67
68 WINPR_ASSERT(mfi);
69
70 freerdp *instance = mfi->instance;
71 WINPR_ASSERT(instance);
72 WINPR_ASSERT(instance->context);
73
74 input = instance->context->input;
75 WINPR_ASSERT(input);
76
77 if ([event_type isEqualToString:@"mouse"])
78 {
79 if (!input->MouseEvent(input,
80 [[event_description objectForKey:@"flags"] unsignedShortValue],
81 [[event_description objectForKey:@"coord_x"] unsignedShortValue],
82 [[event_description objectForKey:@"coord_y"] unsignedShortValue]))
83 {
84 // Returning an error here can terminate the connection.
85 NSLog(@"%s: MouseEvent failed.", __func__);
86 }
87 }
88 else if ([event_type isEqualToString:@"keyboard"])
89 {
90 if ([[event_description objectForKey:@"subtype"] isEqualToString:@"scancode"])
91 freerdp_input_send_keyboard_event(
92 input, [[event_description objectForKey:@"flags"] unsignedShortValue],
93 [[event_description objectForKey:@"scancode"] unsignedShortValue]);
94 else if ([[event_description objectForKey:@"subtype"] isEqualToString:@"unicode"])
95 freerdp_input_send_unicode_keyboard_event(
96 input, [[event_description objectForKey:@"flags"] unsignedShortValue],
97 [[event_description objectForKey:@"unicode_char"] unsignedShortValue]);
98 else
99 NSLog(@"%s: doesn't know how to send keyboard input with subtype %@", __func__,
100 [event_description objectForKey:@"subtype"]);
101 }
102 else if ([event_type isEqualToString:@"disconnect"])
103 should_continue = FALSE;
104 else
105 NSLog(@"%s: unrecognized event type: %@", __func__, event_type);
106
107 return should_continue;
108}
109
110BOOL ios_events_check_handle(mfInfo *mfi)
111{
112 WINPR_ASSERT(mfi);
113
114 if (WaitForSingleObject(mfi->handle, 0) != WAIT_OBJECT_0)
115 return TRUE;
116
117 if (mfi->event_pipe_consumer == -1)
118 return TRUE;
119
120 uint32_t archived_data_length = 0;
121 ssize_t bytes_read;
122
123 // First, read the length of the blob
124 bytes_read = read(mfi->event_pipe_consumer, &archived_data_length, 4);
125
126 if (bytes_read == -1 || archived_data_length < 1 || archived_data_length > 32000)
127 {
128 NSLog(@"%s: just read length descriptor. bytes_read=%ld, archived_data_length=%u", __func__,
129 bytes_read, archived_data_length);
130 return FALSE;
131 }
132
133 // NSLog(@"reading %d bytes from input event pipe", archived_data_length);
134
135 NSMutableData *archived_object_data =
136 [[NSMutableData alloc] initWithLength:archived_data_length];
137 bytes_read =
138 read(mfi->event_pipe_consumer, [archived_object_data mutableBytes], archived_data_length);
139
140 if (bytes_read != archived_data_length)
141 {
142 NSLog(@"%s: attempted to read data; read %ld bytes but wanted %d bytes.", __func__,
143 bytes_read, archived_data_length);
144 [archived_object_data release];
145 return FALSE;
146 }
147
148 NSError *error = nil;
149 NSDictionary *unarchived_object_data = [NSKeyedUnarchiver
150 unarchivedObjectOfClasses:[NSSet setWithObjects:[NSDictionary class], [NSString class],
151 [NSNumber class], nil]
152 fromData:archived_object_data
153 error:&error];
154 [archived_object_data release];
155
156 if (!unarchived_object_data)
157 {
158 // just return TRUE and ignore data. (if return FALSE, sesison can be terminated)
159 NSLog(@"%s: Failed to unarchive input event: %@", __func__, error);
160 return TRUE;
161 }
162
163 return ios_events_handle_event(mfi, unarchived_object_data);
164}
165
166HANDLE ios_events_get_handle(mfInfo *mfi)
167{
168 WINPR_ASSERT(mfi);
169 return mfi->handle;
170}
171
172// Sets up the event pipe
173BOOL ios_events_create_pipe(mfInfo *mfi)
174{
175 int pipe_fds[2];
176
177 WINPR_ASSERT(mfi);
178
179 if (pipe(pipe_fds) == -1)
180 {
181 NSLog(@"%s: pipe failed.", __func__);
182 return FALSE;
183 }
184
185 mfi->event_pipe_consumer = pipe_fds[0];
186 mfi->event_pipe_producer = pipe_fds[1];
187 mfi->handle = CreateFileDescriptorEvent(nullptr, FALSE, FALSE, mfi->event_pipe_consumer,
188 WINPR_FD_READ | WINPR_FD_WRITE);
189 return TRUE;
190}
191
192void ios_events_free_pipe(mfInfo *mfi)
193{
194 WINPR_ASSERT(mfi);
195 int consumer_fd = mfi->event_pipe_consumer, producer_fd = mfi->event_pipe_producer;
196
197 mfi->event_pipe_consumer = mfi->event_pipe_producer = -1;
198 close(producer_fd);
199 close(consumer_fd);
200 (void)CloseHandle(mfi->handle);
201}