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)sessionWillReconnect;
35- (void)sessionDidReconnect;
36- (void)sessionBitmapContextWillChange;
37- (void)sessionBitmapContextDidChange;
42@synthesize delegate = _delegate, params = _params, toolbarVisible = _toolbar_visible,
43 uiRequestCompleted = _ui_request_completed, bookmark = _bookmark;
50static BOOL addArgument(
int *argc,
char ***argv,
const char *fmt, ...)
52 va_list ap = WINPR_C_ARRAY_INIT;
54 char **tmp = realloc(*argv, (*argc + 1) *
sizeof(
char *));
62 const BOOL rc = vasprintf(&arg, fmt, ap) >= 0;
64 (*argv)[*argc - 1] = arg;
68static BOOL addFlag(
int *argc,
char ***argv,
const char *str, BOOL flag)
70 return addArgument(argc, argv,
"%s%s", flag ?
"+" :
"-", str);
73static void freeArguments(
int argc,
char **argv)
75 for (
int i = 0; i < argc; i++)
85 char **argv =
nullptr;
88 if (!(
self = [super init]))
92 [NSException raise:NSInvalidArgumentException
93 format:@"%s: params may not be nil.", __func__];
95 _bookmark = [bookmark retain];
96 _params = [[bookmark params] copy];
97 _name = [[bookmark label] retain];
99 _toolbar_visible = YES;
100 _freerdp = ios_freerdp_new();
101 _ui_request_completed = [[NSCondition alloc] init];
102 BOOL connected_via_3g = ![bookmark conntectedViaWLAN];
104 if (!addArgument(&argc, &argv,
"iFreeRDP"))
107 if (!addArgument(&argc, &argv,
"/gdi:sw"))
110 if (!addArgument(&argc, &argv,
"/relax-order-checks"))
116 if ([_params hasValueForKey:
@"colors"])
117 if (!addArgument(&argc, &argv,
"/bpp:%d",
118 [_params intForKey:
@"colors" with3GEnabled:connected_via_3g]))
121 if ([_params hasValueForKey:
@"port"])
122 if (!addArgument(&argc, &argv,
"/port:%d", [_params intForKey:
@"port"]))
125 if ([_params boolForKey:
@"console"])
126 if (!addArgument(&argc, &argv,
"/admin"))
129 if (!addArgument(&argc, &argv,
"/v:%s", [_params UTF8StringForKey:
@"hostname"]))
133 if ([[_params StringForKey:
@"username"] length])
135 if (!addArgument(&argc, &argv,
"/u:%s", [_params UTF8StringForKey:
@"username"]))
139 if ([[_params StringForKey:
@"password"] length])
141 if (!addArgument(&argc, &argv,
"/p:%s", [_params UTF8StringForKey:
@"password"]))
145 if ([[_params StringForKey:
@"domain"] length])
147 if (!addArgument(&argc, &argv,
"/d:%s", [_params UTF8StringForKey:
@"domain"]))
151 if ([[_params StringForKey:
@"working_directory"] length])
153 if (!addArgument(&argc, &argv,
"/shell-dir:%s",
154 [_params UTF8StringForKey:
@"working_directory"]))
158 if ([[_params StringForKey:
@"remote_program"] length])
160 if (!addArgument(&argc, &argv,
"/shell:%s", [_params UTF8StringForKey:
@"remote_program"]))
165 if ([_params boolForKey:
@"perf_remotefx" with3GEnabled:connected_via_3g])
166 if (!addArgument(&argc, &argv,
"/rfx"))
169 if ([_params boolForKey:
@"perf_gfx" with3GEnabled:connected_via_3g])
170 if (!addArgument(&argc, &argv,
"/gfx"))
173 if ([_params boolForKey:
@"perf_h264" with3GEnabled:connected_via_3g])
174 if (!addArgument(&argc, &argv,
"/gfx:AVC444"))
177 if (![_params boolForKey:
@"perf_remotefx" with3GEnabled:connected_via_3g] &&
178 ![_params boolForKey:
@"perf_gfx" with3GEnabled:connected_via_3g] &&
179 ![_params boolForKey:
@"perf_h264" with3GEnabled:connected_via_3g])
180 if (!addArgument(&argc, &argv,
"/nsc"))
183 if (!addArgument(&argc, &argv,
"/cache:bitmap:on,glyph:on"))
186 if (!addFlag(&argc, &argv,
"wallpaper",
187 [_params boolForKey:
@"perf_show_desktop" with3GEnabled:connected_via_3g]))
190 if (!addFlag(&argc, &argv,
"window-drag",
191 [_params boolForKey:
@"perf_window_dragging" with3GEnabled:connected_via_3g]))
194 if (!addFlag(&argc, &argv,
"menu-anims",
195 [_params boolForKey:
@"perf_menu_animation" with3GEnabled:connected_via_3g]))
198 if (!addFlag(&argc, &argv,
"themes",
199 [_params boolForKey:
@"perf_windows_themes" with3GEnabled:connected_via_3g]))
202 if (!addFlag(&argc, &argv,
"fonts",
203 [_params boolForKey:
@"perf_font_smoothing" with3GEnabled:connected_via_3g]))
206 if (!addFlag(&argc, &argv,
"aero",
207 [_params boolForKey:
@"perf_desktop_composition" with3GEnabled:connected_via_3g]))
210 if ([_params hasValueForKey:
@"width"])
211 if (!addArgument(&argc, &argv,
"/w:%d", [_params intForKey:
@"width"]))
214 if ([_params hasValueForKey:
@"height"])
215 if (!addArgument(&argc, &argv,
"/h:%d", [_params intForKey:
@"height"]))
219 switch ([_params intForKey:
@"security"])
221 case TSXProtocolSecurityNLA:
222 if (!addArgument(&argc, &argv,
"/sec:NLA"))
227 case TSXProtocolSecurityTLS:
228 if (!addArgument(&argc, &argv,
"/sec:TLS"))
233 case TSXProtocolSecurityRDP:
234 if (!addArgument(&argc, &argv,
"/sec:RDP"))
244 if ([_params boolForKey:
@"enable_tsg_settings"])
246 if (!addArgument(&argc, &argv,
"/gateway:g:%s:%d,u:%s,d:%s,p:%s",
247 [_params UTF8StringForKey:
@"tsg_hostname"],
248 [_params intForKey:
@"tsg_port"],
249 [_params UTF8StringForKey:
@"tsg_username"],
250 [_params UTF8StringForKey:
@"tsg_domain"],
251 [_params UTF8StringForKey:
@"tsg_password"]))
256 if (!addArgument(&argc, &argv,
"/kbd:layout:%d", 0x409))
260 if (!addArgument(&argc, &argv,
"/kbd:unicode:on"))
263 if (!addArgument(&argc, &argv,
"/auto-reconnect"))
267 freerdp_client_settings_parse_command_line(_freerdp->context->settings, argc, argv, FALSE);
272 freeArguments(argc, argv);
273 [
self mfi]->session =
self;
276 freeArguments(argc, argv);
283 [
self setDelegate:nil];
287 [_ui_request_completed release];
288 ios_freerdp_free(_freerdp);
292- (CGContextRef)bitmapContext
294 return [
self mfi]->bitmap_context;
298#pragma mark Connecting and disconnecting
303 rdpSettings *settings = _freerdp->context->settings;
308 CGSize size = CGSizeZero;
310 if ([[
self delegate] respondsToSelector:@selector(sizeForFitScreenForSession:)])
311 size = [[self delegate] sizeForFitScreenForSession:self];
313 if (!CGSizeEqualToSize(CGSizeZero, size))
315 [_params setInt:size.width forKey:@"width"];
316 [_params setInt:size.height forKey:@"height"];
331 [
self performSelectorInBackground:@selector(runSession) withObject:nil];
336 mfInfo *mfi = [
self mfi];
337 ios_events_send(mfi, [NSDictionary dictionaryWithObject:
@"disconnect" forKey:
@"type"]);
339 if (mfi->connection_state == TSXConnectionConnecting)
344 freerdp_abort_connect_context(_freerdp->context);
345 [
self sessionDidDisconnect];
350- (TSXConnectionState)connectionState
352 return [
self mfi]->connection_state;
389#pragma mark Input events
391- (void)sendInputEvent:(NSDictionary *)eventDescriptor
393 if ([
self mfi]->connection_state == TSXConnectionConnected)
394 ios_events_send([
self mfi], eventDescriptor);
397- (void)sendClipboardHasText:(BOOL)hasText
401 ios_events_send([
self mfi],
402 [NSDictionary dictionaryWithObjectsAndKeys:
@"clipboard",
@"type",
403 [NSNumber numberWithBool:hasText],
408#pragma mark Server events (main thread)
410- (void)setNeedsDisplayInRectAsValue:(NSValue *)rect_value
412 if ([[
self delegate] respondsToSelector:@selector(session:needsRedrawInRect:)])
413 [[self delegate] session:self needsRedrawInRect:[rect_value CGRectValue]];
416- (void)setRemoteCursor:(
RDPCursor *)cursor
418 if ([[
self delegate] respondsToSelector:@selector(session:didSetRemoteCursor:)])
419 [[self delegate] session:self didSetRemoteCursor:cursor];
422- (void)setRemoteCursorPositionValue:(NSValue *)positionValue
424 if ([[
self delegate] respondsToSelector:@selector(session:didMoveRemoteCursor:)])
425 [[self delegate] session:self didMoveRemoteCursor:[positionValue CGPointValue]];
428- (void)hideRemoteCursor
430 if ([[
self delegate] respondsToSelector:@selector(sessionDidHideRemoteCursor:)])
431 [[self delegate] sessionDidHideRemoteCursor:self];
434- (void)setDefaultRemoteCursor
436 if ([[
self delegate] respondsToSelector:@selector(sessionDidSetDefaultRemoteCursor:)])
437 [[self delegate] sessionDidSetDefaultRemoteCursor:self];
440- (void)setRemoteClipboardText:(NSString *)text
442 if ([[
self delegate] respondsToSelector:@selector(session:didChangeRemoteClipboardText:)])
443 [[self delegate] session:self didChangeRemoteClipboardText:text];
447#pragma mark interface functions
449- (UIImage *)getScreenshotWithSize:(CGSize)size
451 NSAssert([
self mfi]->bitmap_context != nil,
452 @"Screenshot requested while having no valid RDP drawing context");
453 CGImageRef cgImage = CGBitmapContextCreateImage([
self mfi]->bitmap_context);
454 UIGraphicsBeginImageContext(size);
455 CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, size.height);
456 CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
457 CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height),
459 UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
460 UIGraphicsEndImageContext();
461 CGImageRelease(cgImage);
465- (rdpSettings *)getSessionParams
467 return _freerdp->context->settings;
470- (NSString *)sessionName
478@implementation RDPSession (Private)
482 return MFI_FROM_INSTANCE(_freerdp);
488 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
490 [
self performSelectorOnMainThread:@selector(sessionWillConnect)
493 int result_code = ios_run_freerdp(_freerdp);
494 [
self mfi]->connection_state = TSXConnectionDisconnected;
495 [
self performSelectorOnMainThread:@selector(runSessionFinished:)
496 withObject:[NSNumber numberWithInt:result_code]
502- (void)runSessionFinished:(NSNumber *)result
504 int result_code = [result intValue];
508 case MF_EXIT_CONN_CANCELED:
509 [
self sessionDidDisconnect];
512 case MF_EXIT_LOGON_TIMEOUT:
513 case MF_EXIT_CONN_FAILED:
514 [
self sessionDidFailToConnect:result_code];
517 case MF_EXIT_SUCCESS:
519 [
self sessionDidDisconnect];
525#pragma mark Session management (main thread)
527- (void)sessionWillConnect
529 if ([[
self delegate] respondsToSelector:@selector(sessionWillConnect:)])
530 [[self delegate] sessionWillConnect:self];
533- (void)sessionWillReconnect
535 if ([[
self delegate] respondsToSelector:@selector(sessionWillReconnect:)])
536 [[self delegate] sessionWillReconnect:self];
539- (void)sessionDidReconnect
541 if ([[
self delegate] respondsToSelector:@selector(sessionDidReconnect:)])
542 [[self delegate] sessionDidReconnect:self];
545- (void)sessionDidConnect
547 if ([[
self delegate] respondsToSelector:@selector(sessionDidConnect:)])
548 [[self delegate] sessionDidConnect:self];
551- (void)sessionDidFailToConnect:(
int)reason
553 [[NSNotificationCenter defaultCenter]
554 postNotificationName:TSXSessionDidFailToConnectNotification
557 if ([[
self delegate] respondsToSelector:@selector(session:didFailToConnect:)])
558 [[self delegate] session:self didFailToConnect:reason];
561- (void)sessionDidDisconnect
563 [[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidDisconnectNotification
566 if ([[
self delegate] respondsToSelector:@selector(sessionDidDisconnect:)])
567 [[self delegate] sessionDidDisconnect:self];
570- (void)sessionBitmapContextWillChange
572 if ([[
self delegate] respondsToSelector:@selector(sessionBitmapContextWillChange:)])
573 [[self delegate] sessionBitmapContextWillChange:self];
576- (void)sessionBitmapContextDidChange
578 if ([[
self delegate] respondsToSelector:@selector(sessionBitmapContextDidChange:)])
579 [[self delegate] sessionBitmapContextDidChange:self];
582- (void)sessionRequestsAuthenticationWithParams:(NSMutableDictionary *)params
584 if ([[
self delegate] respondsToSelector:@selector(session:requestsAuthenticationWithParams:)])
585 [[self delegate] session:self requestsAuthenticationWithParams:params];
588- (void)sessionVerifyCertificateWithParams:(NSMutableDictionary *)params
590 if ([[
self delegate] respondsToSelector:@selector(session:verifyCertificateWithParams:)])
591 [[self delegate] session:self verifyCertificateWithParams:params];
594- (void)sessionRequestsClipboardTextWithParams:(NSMutableDictionary *)params
596 if ([[
self delegate] respondsToSelector:@selector(session:requestsClipboardTextWithParams:)])
597 [[self delegate] session:self requestsClipboardTextWithParams: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.