11#import "ios_freerdp.h"
12#import "ios_freerdp_ui.h"
13#import "ios_freerdp_events.h"
19#import "ConnectionParams.h"
21NSString *TSXSessionDidDisconnectNotification =
@"TSXSessionDidDisconnect";
22NSString *TSXSessionDidFailToConnectNotification =
@"TSXSessionDidFailToConnect";
24@interface RDPSession (Private)
26- (void)runSessionFinished:(NSNumber *)result;
30- (void)sessionWillConnect;
31- (void)sessionDidConnect;
32- (void)sessionDidDisconnect;
33- (void)sessionDidFailToConnect:(
int)reason;
34- (void)sessionBitmapContextWillChange;
35- (void)sessionBitmapContextDidChange;
40@synthesize delegate = _delegate, params = _params, toolbarVisible = _toolbar_visible,
41 uiRequestCompleted = _ui_request_completed, bookmark = _bookmark;
48static BOOL addArgument(
int *argc,
char ***argv,
const char *fmt, ...)
50 va_list ap = WINPR_C_ARRAY_INIT;
52 char **tmp = realloc(*argv, (*argc + 1) *
sizeof(
char *));
60 vasprintf(&arg, fmt, ap);
62 (*argv)[*argc - 1] = arg;
66static BOOL addFlag(
int *argc,
char ***argv,
const char *str, BOOL flag)
68 return addArgument(argc, argv,
"%s%s", flag ?
"+" :
"-", str);
71static void freeArguments(
int argc,
char **argv)
73 for (
int i = 0; i < argc; i++)
83 char **argv =
nullptr;
86 if (!(
self = [super init]))
90 [NSException raise:NSInvalidArgumentException
91 format:@"%s: params may not be nil.", __func__];
93 _bookmark = [bookmark retain];
94 _params = [[bookmark params] copy];
95 _name = [[bookmark label] retain];
97 _toolbar_visible = YES;
98 _freerdp = ios_freerdp_new();
99 _ui_request_completed = [[NSCondition alloc] init];
100 BOOL connected_via_3g = ![bookmark conntectedViaWLAN];
102 if (!addArgument(&argc, &argv,
"iFreeRDP"))
105 if (!addArgument(&argc, &argv,
"/gdi:sw"))
108 if (!addArgument(&argc, &argv,
"/relax-order-checks"))
114 if ([_params hasValueForKey:
@"colors"])
115 if (!addArgument(&argc, &argv,
"/bpp:%d",
116 [_params intForKey:
@"colors" with3GEnabled:connected_via_3g]))
119 if ([_params hasValueForKey:
@"port"])
120 if (!addArgument(&argc, &argv,
"/port:%d", [_params intForKey:
@"port"]))
123 if ([_params boolForKey:
@"console"])
124 if (!addArgument(&argc, &argv,
"/admin"))
127 if (!addArgument(&argc, &argv,
"/v:%s", [_params UTF8StringForKey:
@"hostname"]))
131 if ([[_params StringForKey:
@"username"] length])
133 if (!addArgument(&argc, &argv,
"/u:%s", [_params UTF8StringForKey:
@"username"]))
137 if ([[_params StringForKey:
@"password"] length])
139 if (!addArgument(&argc, &argv,
"/p:%s", [_params UTF8StringForKey:
@"password"]))
143 if ([[_params StringForKey:
@"domain"] length])
145 if (!addArgument(&argc, &argv,
"/d:%s", [_params UTF8StringForKey:
@"domain"]))
149 if ([[_params StringForKey:
@"working_directory"] length])
151 if (!addArgument(&argc, &argv,
"/shell-dir:%s",
152 [_params UTF8StringForKey:
@"working_directory"]))
156 if ([[_params StringForKey:
@"remote_program"] length])
158 if (!addArgument(&argc, &argv,
"/shell:%s", [_params UTF8StringForKey:
@"remote_program"]))
163 if ([_params boolForKey:
@"perf_remotefx" with3GEnabled:connected_via_3g])
164 if (!addArgument(&argc, &argv,
"/rfx"))
167 if ([_params boolForKey:
@"perf_gfx" with3GEnabled:connected_via_3g])
168 if (!addArgument(&argc, &argv,
"/gfx"))
171 if ([_params boolForKey:
@"perf_h264" with3GEnabled:connected_via_3g])
172 if (!addArgument(&argc, &argv,
"/gfx:AVC444"))
175 if (![_params boolForKey:
@"perf_remotefx" with3GEnabled:connected_via_3g] &&
176 ![_params boolForKey:
@"perf_gfx" with3GEnabled:connected_via_3g] &&
177 ![_params boolForKey:
@"perf_h264" with3GEnabled:connected_via_3g])
178 if (!addArgument(&argc, &argv,
"/nsc"))
181 if (!addArgument(&argc, &argv,
"/cache:bitmap:on,glyph:on"))
184 if (!addFlag(&argc, &argv,
"wallpaper",
185 [_params boolForKey:
@"perf_show_desktop" with3GEnabled:connected_via_3g]))
188 if (!addFlag(&argc, &argv,
"window-drag",
189 [_params boolForKey:
@"perf_window_dragging" with3GEnabled:connected_via_3g]))
192 if (!addFlag(&argc, &argv,
"menu-anims",
193 [_params boolForKey:
@"perf_menu_animation" with3GEnabled:connected_via_3g]))
196 if (!addFlag(&argc, &argv,
"themes",
197 [_params boolForKey:
@"perf_windows_themes" with3GEnabled:connected_via_3g]))
200 if (!addFlag(&argc, &argv,
"fonts",
201 [_params boolForKey:
@"perf_font_smoothing" with3GEnabled:connected_via_3g]))
204 if (!addFlag(&argc, &argv,
"aero",
205 [_params boolForKey:
@"perf_desktop_composition" with3GEnabled:connected_via_3g]))
208 if ([_params hasValueForKey:
@"width"])
209 if (!addArgument(&argc, &argv,
"/w:%d", [_params intForKey:
@"width"]))
212 if ([_params hasValueForKey:
@"height"])
213 if (!addArgument(&argc, &argv,
"/h:%d", [_params intForKey:
@"height"]))
217 switch ([_params intForKey:
@"security"])
219 case TSXProtocolSecurityNLA:
220 if (!addArgument(&argc, &argv,
"/sec:NLA"))
225 case TSXProtocolSecurityTLS:
226 if (!addArgument(&argc, &argv,
"/sec:TLS"))
231 case TSXProtocolSecurityRDP:
232 if (!addArgument(&argc, &argv,
"/sec:RDP"))
242 if ([_params boolForKey:
@"enable_tsg_settings"])
244 if (!addArgument(&argc, &argv,
"/gateway:g:%s:%d,u:%s,d:%s,p:%s",
245 [_params UTF8StringForKey:
@"tsg_hostname"],
246 [_params intForKey:
@"tsg_port"],
247 [_params UTF8StringForKey:
@"tsg_username"],
248 [_params UTF8StringForKey:
@"tsg_domain"],
249 [_params UTF8StringForKey:
@"tsg_password"]))
254 if (!addArgument(&argc, &argv,
"/kbd:layout:%d", 0x409))
258 freerdp_client_settings_parse_command_line(_freerdp->context->settings, argc, argv, FALSE);
263 freeArguments(argc, argv);
264 [
self mfi]->session =
self;
267 freeArguments(argc, argv);
274 [
self setDelegate:nil];
278 [_ui_request_completed release];
279 ios_freerdp_free(_freerdp);
283- (CGContextRef)bitmapContext
285 return [
self mfi]->bitmap_context;
289#pragma mark Connecting and disconnecting
294 rdpSettings *settings = _freerdp->context->settings;
299 CGSize size = CGSizeZero;
301 if ([[
self delegate] respondsToSelector:@selector(sizeForFitScreenForSession:)])
302 size = [[self delegate] sizeForFitScreenForSession:self];
304 if (!CGSizeEqualToSize(CGSizeZero, size))
306 [_params setInt:size.width forKey:@"width"];
307 [_params setInt:size.height forKey:@"height"];
322 [
self performSelectorInBackground:@selector(runSession) withObject:nil];
327 mfInfo *mfi = [
self mfi];
328 ios_events_send(mfi, [NSDictionary dictionaryWithObject:
@"disconnect" forKey:
@"type"]);
330 if (mfi->connection_state == TSXConnectionConnecting)
333 [
self sessionDidDisconnect];
338- (TSXConnectionState)connectionState
340 return [
self mfi]->connection_state;
377#pragma mark Input events
379- (void)sendInputEvent:(NSDictionary *)eventDescriptor
381 if ([
self mfi]->connection_state == TSXConnectionConnected)
382 ios_events_send([
self mfi], eventDescriptor);
386#pragma mark Server events (main thread)
388- (void)setNeedsDisplayInRectAsValue:(NSValue *)rect_value
390 if ([[
self delegate] respondsToSelector:@selector(session:needsRedrawInRect:)])
391 [[self delegate] session:self needsRedrawInRect:[rect_value CGRectValue]];
394- (void)setRemoteCursor:(
RDPCursor *)cursor
396 if ([[
self delegate] respondsToSelector:@selector(session:didSetRemoteCursor:)])
397 [[self delegate] session:self didSetRemoteCursor:cursor];
400- (void)setRemoteCursorPositionValue:(NSValue *)positionValue
402 if ([[
self delegate] respondsToSelector:@selector(session:didMoveRemoteCursor:)])
403 [[self delegate] session:self didMoveRemoteCursor:[positionValue CGPointValue]];
406- (void)hideRemoteCursor
408 if ([[
self delegate] respondsToSelector:@selector(sessionDidHideRemoteCursor:)])
409 [[self delegate] sessionDidHideRemoteCursor:self];
412- (void)setDefaultRemoteCursor
414 if ([[
self delegate] respondsToSelector:@selector(sessionDidSetDefaultRemoteCursor:)])
415 [[self delegate] sessionDidSetDefaultRemoteCursor:self];
419#pragma mark interface functions
421- (UIImage *)getScreenshotWithSize:(CGSize)size
423 NSAssert([
self mfi]->bitmap_context != nil,
424 @"Screenshot requested while having no valid RDP drawing context");
425 CGImageRef cgImage = CGBitmapContextCreateImage([
self mfi]->bitmap_context);
426 UIGraphicsBeginImageContext(size);
427 CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, size.height);
428 CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
429 CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height),
431 UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
432 UIGraphicsEndImageContext();
433 CGImageRelease(cgImage);
437- (rdpSettings *)getSessionParams
439 return _freerdp->context->settings;
442- (NSString *)sessionName
450@implementation RDPSession (Private)
454 return MFI_FROM_INSTANCE(_freerdp);
460 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
462 [
self performSelectorOnMainThread:@selector(sessionWillConnect)
465 int result_code = ios_run_freerdp(_freerdp);
466 [
self mfi]->connection_state = TSXConnectionDisconnected;
467 [
self performSelectorOnMainThread:@selector(runSessionFinished:)
468 withObject:[NSNumber numberWithInt:result_code]
474- (void)runSessionFinished:(NSNumber *)result
476 int result_code = [result intValue];
480 case MF_EXIT_CONN_CANCELED:
481 [
self sessionDidDisconnect];
484 case MF_EXIT_LOGON_TIMEOUT:
485 case MF_EXIT_CONN_FAILED:
486 [
self sessionDidFailToConnect:result_code];
489 case MF_EXIT_SUCCESS:
491 [
self sessionDidDisconnect];
497#pragma mark Session management (main thread)
499- (void)sessionWillConnect
501 if ([[
self delegate] respondsToSelector:@selector(sessionWillConnect:)])
502 [[self delegate] sessionWillConnect:self];
505- (void)sessionDidConnect
507 if ([[
self delegate] respondsToSelector:@selector(sessionDidConnect:)])
508 [[self delegate] sessionDidConnect:self];
511- (void)sessionDidFailToConnect:(
int)reason
513 [[NSNotificationCenter defaultCenter]
514 postNotificationName:TSXSessionDidFailToConnectNotification
517 if ([[
self delegate] respondsToSelector:@selector(session:didFailToConnect:)])
518 [[self delegate] session:self didFailToConnect:reason];
521- (void)sessionDidDisconnect
523 [[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidDisconnectNotification
526 if ([[
self delegate] respondsToSelector:@selector(sessionDidDisconnect:)])
527 [[self delegate] sessionDidDisconnect:self];
530- (void)sessionBitmapContextWillChange
532 if ([[
self delegate] respondsToSelector:@selector(sessionBitmapContextWillChange:)])
533 [[self delegate] sessionBitmapContextWillChange:self];
536- (void)sessionBitmapContextDidChange
538 if ([[
self delegate] respondsToSelector:@selector(sessionBitmapContextDidChange:)])
539 [[self delegate] sessionBitmapContextDidChange:self];
542- (void)sessionRequestsAuthenticationWithParams:(NSMutableDictionary *)params
544 if ([[
self delegate] respondsToSelector:@selector(session:requestsAuthenticationWithParams:)])
545 [[self delegate] session:self requestsAuthenticationWithParams:params];
548- (void)sessionVerifyCertificateWithParams:(NSMutableDictionary *)params
550 if ([[
self delegate] respondsToSelector:@selector(session:verifyCertificateWithParams:)])
551 [[self delegate] session:self verifyCertificateWithParams:params];
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.