// // MGMSIPAccount.m // VoiceBase // // Created by Mr. Gecko on 9/10/10. // Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // // Permission to use, copy, modify, and/or distribute this software for any purpose // with or without fee is hereby granted, provided that the above copyright notice // and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, // OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, // DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS // ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // #if MGMSIPENABLED #import "MGMSIPAccount.h" #import "MGMSIP.h" #import "MGMSIPCall.h" #import "MGMSIPURL.h" #import "MGMAddons.h" NSString * const MGMSIPAccountFullName = @"MGMSIPAccountFullName"; NSString * const MGMSIPAccountUserName = @"MGMSIPAccountUserName"; NSString * const MGMSIPAccountDomain = @"MGMSIPAccountDomain"; NSString * const MGMSIPAccountRegistrar = @"MGMSIPAccountRegistrar"; NSString * const MGMSIPAccountSIPAddress = @"MGMSIPAccountSIPAddress"; NSString * const MGMSIPAccountProxy = @"MGMSIPAccountProxy"; NSString * const MGMSIPAccountProxyPort = @"MGMSIPAccountProxyPort"; NSString * const MGMSIPAccountRegisterTimeout = @"MGMSIPAccountRegisterTimeout"; NSString * const MGMSIPAccountTransport = @"MGMSIPAccountTransport"; NSString * const MGMSIPAccountDTMFToneType = @"MGMSIPAccountDTMFToneType"; const int MGMSIPAccountDefaultProxyPort = 5060; const int MGMSIPAccountReregisterTimeoutMin = 60; const int MGMSIPAccountReregisterTimeoutMax = 3600; const int MGMSIPAccountReregisterTimeoutDefault = 300; @implementation MGMSIPAccount - (id)initWithSettings:(NSDictionary *)theSettings { if ((self = [self init])) { if ([theSettings objectForKey:MGMSIPAccountUserName]==nil || [[theSettings objectForKey:MGMSIPAccountUserName] isEqual:@""] || [theSettings objectForKey:MGMSIPAccountDomain]==nil || [[theSettings objectForKey:MGMSIPAccountDomain] isEqual:@""]) { [self release]; self = nil; } else { if ([theSettings objectForKey:MGMSIPAccountFullName]!=nil && ![[theSettings objectForKey:MGMSIPAccountFullName] isEqual:@""]) fullName = [[theSettings objectForKey:MGMSIPAccountFullName] copy]; userName = [[theSettings objectForKey:MGMSIPAccountUserName] copy]; domain = [[theSettings objectForKey:MGMSIPAccountDomain] copy]; if ([theSettings objectForKey:MGMSIPAccountRegistrar]!=nil && ![[theSettings objectForKey:MGMSIPAccountRegistrar] isEqual:@""]) registrar = [[theSettings objectForKey:MGMSIPAccountRegistrar] copy]; if ([theSettings objectForKey:MGMSIPAccountSIPAddress]!=nil && ![[theSettings objectForKey:MGMSIPAccountSIPAddress] isEqual:@""]) SIPAddress = [[theSettings objectForKey:MGMSIPAccountSIPAddress] copy]; if ([theSettings objectForKey:MGMSIPAccountProxy]!=nil && ![[theSettings objectForKey:MGMSIPAccountProxy] isEqual:@""]) proxy = [[theSettings objectForKey:MGMSIPAccountProxy] copy]; if ([theSettings objectForKey:MGMSIPAccountProxyPort]!=nil && [[theSettings objectForKey:MGMSIPAccountProxyPort] intValue]!=0) proxyPort = [[theSettings objectForKey:MGMSIPAccountProxyPort] intValue]; else proxyPort = 0; if ([theSettings objectForKey:MGMSIPAccountRegisterTimeout]!=nil && [[theSettings objectForKey:MGMSIPAccountRegisterTimeout] intValue]!=0) reregisterTimeout = [[theSettings objectForKey:MGMSIPAccountRegisterTimeout] intValue]; if ([theSettings objectForKey:MGMSIPAccountTransport]!=nil) transport = [[theSettings objectForKey:MGMSIPAccountTransport] intValue]; #if TARGET_OS_IPHONE else transport = 1; #endif if ([theSettings objectForKey:MGMSIPAccountDTMFToneType]!=nil) dtmfToneType = [[theSettings objectForKey:MGMSIPAccountDTMFToneType] intValue]; } } return self; } - (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain { return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:nil]; } - (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress { return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:theSIPAddress registrar:nil]; } - (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress registrar:(NSString *)theRegistrar { if (theUserName==nil || theDomain==nil) return nil; NSMutableDictionary *settings = [NSMutableDictionary dictionary]; if (theFullName!=nil) [settings setObject:theFullName forKey:MGMSIPAccountFullName]; [settings setObject:theUserName forKey:MGMSIPAccountUserName]; [settings setObject:theDomain forKey:MGMSIPAccountDomain]; if (theSIPAddress!=nil) [settings setObject:theSIPAddress forKey:MGMSIPAccountSIPAddress]; if (theRegistrar!=nil) [settings setObject:theRegistrar forKey:MGMSIPAccountRegistrar]; return [self initWithSettings:settings]; } - (id)init { if ((self = [super init])) { reregisterTimeout = MGMSIPAccountReregisterTimeoutDefault; identifier = PJSUA_INVALID_ID; registered = NO; calls = [NSMutableArray new]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkConnected:) name:MGMNetworkConnectedNotification object:nil]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [calls release]; [fullName release]; [userName release]; [domain release]; [registrar release]; [SIPAddress release]; [proxy release]; [super dealloc]; } - (BOOL)informationComplete { return ((delegate!=nil && [delegate respondsToSelector:@selector(password)]) && userName!=nil && (domain!=nil || [self SIPAddress]!=nil)); } - (NSString *)description { return [NSString stringWithFormat:@"%@ %@", [super description], [self SIPAddress]]; } - (id)delegate { return delegate; } - (void)setDelegate:(id)theDelegate { delegate = theDelegate; } - (NSString *)fullName { return fullName; } - (void)setFullName:(NSString *)theFullName { [fullName release]; fullName = [theFullName copy]; } - (NSString *)userName { return userName; } - (void)setUserName:(NSString *)theUserName { if (theUserName==nil || [theUserName isEqual:@""]) return; [userName release]; userName = [theUserName copy]; } - (NSString *)domain { return domain; } - (void)setDomain:(NSString *)theDomain { [domain release]; domain = [theDomain copy]; } - (NSString *)registrar { if (registrar==nil && domain!=nil) return domain; return registrar; } - (void)setRegistrar:(NSString *)theRegistrar { [registrar release]; registrar = [theRegistrar copy]; } - (NSString *)SIPAddress { if (SIPAddress==nil && domain!=nil && userName!=nil) return [NSString stringWithFormat:@"%@@%@", userName, domain]; return SIPAddress; } - (void)setSIPAddress:(NSString *)theSIPAddress { [SIPAddress release]; SIPAddress = [theSIPAddress copy]; } - (NSString *)proxy { return proxy; } - (void)setProxy:(NSString *)theProxy { [proxy release]; proxy = [theProxy copy]; } - (int)proxyPort { if (proxyPort==0) return MGMSIPAccountDefaultProxyPort; return proxyPort; } - (void)setProxyPort:(int)theProxyPort { proxyPort = theProxyPort; } - (int)reregisterTimeout { return reregisterTimeout; } - (void)setReregisterTimeout:(int)theReregisterTimeout { if (theReregisterTimeout==0) reregisterTimeout = MGMSIPAccountReregisterTimeoutDefault; else if (theReregisterTimeout < MGMSIPAccountReregisterTimeoutMin) reregisterTimeout = MGMSIPAccountReregisterTimeoutMin; else if (theReregisterTimeout > MGMSIPAccountReregisterTimeoutMax) reregisterTimeout = MGMSIPAccountReregisterTimeoutMax; else reregisterTimeout = theReregisterTimeout; } - (int)transport { return transport; } - (void)setTransport:(int)theTransport { transport = theTransport; } - (int)dtmfToneType { return dtmfToneType; } - (void)setDTMFToneType:(int)theType { dtmfToneType = theType; } - (pjsua_acc_id)identifier { return identifier; } - (void)setIdentifier:(pjsua_acc_id)theIdentifier { identifier = theIdentifier; } - (NSString *)password { NSString *password = nil; if (delegate!=nil && [delegate respondsToSelector:@selector(password)]) password = [delegate password]; return password; } - (NSDictionary *)settings { NSMutableDictionary *settings = [NSMutableDictionary dictionary]; if (fullName!=nil) [settings setObject:fullName forKey:MGMSIPAccountFullName]; if (userName!=nil) [settings setObject:userName forKey:MGMSIPAccountUserName]; if (domain!=nil) [settings setObject:domain forKey:MGMSIPAccountDomain]; if (registrar!=nil) [settings setObject:registrar forKey:MGMSIPAccountRegistrar]; if (SIPAddress!=nil) [settings setObject:SIPAddress forKey:MGMSIPAccountSIPAddress]; if (proxy!=nil) [settings setObject:proxy forKey:MGMSIPAccountProxy]; if (proxyPort!=0) [settings setObject:[NSNumber numberWithInt:proxyPort] forKey:MGMSIPAccountProxyPort]; if (reregisterTimeout!=0) [settings setObject:[NSNumber numberWithInt:reregisterTimeout] forKey:MGMSIPAccountRegisterTimeout]; [settings setObject:[NSNumber numberWithInt:transport] forKey:MGMSIPAccountTransport]; [settings setObject:[NSNumber numberWithInt:dtmfToneType] forKey:MGMSIPAccountDTMFToneType]; return settings; } - (void)setLastError:(NSString *)theError { [lastError release]; lastError = [theError copy]; } - (NSString *)lastError { return (lastError!=nil ? lastError : @""); } - (BOOL)isLoggedIn { return (identifier!=PJSUA_INVALID_ID); } - (void)login { [[MGMSIP sharedSIP] loginToAccount:self]; } - (void)loginErrored { if (delegate!=nil && [delegate respondsToSelector:@selector(loginErrored)]) [delegate loginErrored]; } - (void)logout { [[MGMSIP sharedSIP] logoutOfAccount:self]; } - (void)logoutErrored { if (delegate!=nil && [delegate respondsToSelector:@selector(logoutErrored)]) [delegate logoutErrored]; } - (void)registrationStateChanged { registered = (([self registrationStatus]/100)==2 && [self registrationExpireTime]>0); } - (BOOL)isRegistered { return registered; } - (void)reregister { [self setRegistered:YES]; } - (void)setRegistered:(BOOL)isRegistered { if (identifier==PJSUA_INVALID_ID) return; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_set_registration(identifier, (isRegistered ? PJ_TRUE : PJ_FALSE)); [self setOnline:isRegistered]; bzero(&PJThreadDesc, sizeof(pj_thread_desc)); } - (void)networkConnected:(NSNotification *)theNotification { if ([self isLoggedIn]) [self performSelector:@selector(reregister) withObject:nil afterDelay:1.0]; } - (int)registrationStatus { if (identifier==PJSUA_INVALID_ID) return 0; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_info accountInfo; pj_status_t status = pjsua_acc_get_info(identifier, &accountInfo); bzero(&PJThreadDesc, sizeof(pj_thread_desc)); if (status!=PJ_SUCCESS) return 0; return accountInfo.status; } - (NSString *)registrationStatusText { if (identifier==PJSUA_INVALID_ID) return nil; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_info accountInfo; pj_status_t status = pjsua_acc_get_info(identifier, &accountInfo); bzero(&PJThreadDesc, sizeof(pj_thread_desc)); if (status!=PJ_SUCCESS) return nil; return [NSString stringWithPJString:accountInfo.status_text]; } - (int)registrationExpireTime { if (identifier==PJSUA_INVALID_ID) return -1; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_info accountInfo; pj_status_t status = pjsua_acc_get_info(identifier, &accountInfo); bzero(&PJThreadDesc, sizeof(pj_thread_desc)); if (status!=PJ_SUCCESS) return -1; return accountInfo.expires; } - (BOOL)isOnline { if (identifier==PJSUA_INVALID_ID) return NO; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_info accountInfo; pj_status_t status = pjsua_acc_get_info(identifier, &accountInfo); bzero(&PJThreadDesc, sizeof(pj_thread_desc)); if (status!=PJ_SUCCESS) return NO; return (accountInfo.online_status==PJ_TRUE); } - (void)setOnline:(BOOL)isOnline { if ([self identifier]==PJSUA_INVALID_ID) return; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pj_status_t status = pjsua_acc_set_online_status(identifier, (isOnline ? PJ_TRUE : PJ_FALSE)); if (status==PJ_SUCCESS) { [reregisterTimer invalidate]; [reregisterTimer release]; reregisterTimer = nil; if (isOnline) reregisterTimer = [[NSTimer scheduledTimerWithTimeInterval:(float)reregisterTimeout target:self selector:@selector(reregister) userInfo:nil repeats:YES] retain]; } bzero(&PJThreadDesc, sizeof(pj_thread_desc)); } - (NSString *)onlineStatusText { if (identifier==PJSUA_INVALID_ID) return nil; pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_acc_info accountInfo; pj_status_t status = pjsua_acc_get_info(identifier, &accountInfo); bzero(&PJThreadDesc, sizeof(pj_thread_desc)); if (status!=PJ_SUCCESS) return nil; return [NSString stringWithPJString:accountInfo.online_status_text]; } - (MGMSIPCall *)addCallWithIdentifier:(int)theIndentifier { MGMSIPCall *call = [[[MGMSIPCall alloc] initWithIdentifier:theIndentifier account:self] autorelease]; [calls addObject:call]; return call; } - (MGMSIPCall *)makeCallToNumber:(NSString *)theNumber { MGMSIPURL *SIPURL = [MGMSIPURL URLWithSIPAddress:theNumber]; if ([[SIPURL host] isEqual:theNumber]) { [SIPURL setHost:domain]; [SIPURL setUserName:theNumber]; } return [self makeCallToSIPURL:SIPURL]; } - (MGMSIPCall *)makeCallToSIPURL:(MGMSIPURL *)theURL { pj_thread_desc PJThreadDesc; [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; pjsua_call_id callIdentifier; pj_str_t url = [[theURL SIPID] PJString]; pj_status_t status = pjsua_call_make_call(identifier, &url, 0, NULL, NULL, &callIdentifier); MGMSIPCall *call = nil; if (status!=PJ_SUCCESS) { NSLog(@"Unable to make call to %@ with account %@", theURL, self); } else { call = [self callWithIdentifier:callIdentifier]; } bzero(&PJThreadDesc, sizeof(pj_thread_desc)); return call; } - (NSArray *)calls { return calls; } - (MGMSIPCall *)callWithIdentifier:(int)theIdentifier { for (int i=0; i<[calls count]; i++) { if ([(MGMSIPCall *)[calls objectAtIndex:i] identifier]==theIdentifier) return [calls objectAtIndex:i]; } return nil; } - (void)removeCall:(MGMSIPCall *)theCall { [calls removeObject:theCall]; } @end #endif