Skip to content

added possibility to configure turn server for ios #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions ios/RTCPjSip/PjSipAccount.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,36 @@ - (id)initWithConfig:(NSDictionary *)config {
}
}
}
// TURN settings
NSDictionary *turnConfiguration = config[@"turn"];
if (turnConfiguration) {
NSString *turnServer = turnConfiguration[@"server"];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!
Is it possible to split the code to avoid copy-paste for pjsua_turn_config struct creation ?

NSString *transportType = turnConfiguration[@"tp_type"];
NSString *realm = turnConfiguration[@"realm"];
NSString *username = turnConfiguration[@"username"];
NSString *passwordDataType = turnConfiguration[@"password_data_type"];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we will have the same structures as in pjsip, I mean

const turnConfiguration = {
  server: "XXX",
  connectionType: "UDP", // TCP , TLS
  authentication: {
    realm: "XXX",
    username: "XXX",
    dataType: "PLAIN", // "HASHED"
    data: "XXX"
  }

NSString *passwordData = turnConfiguration[@"data"];

pjsua_turn_config turnConfig;
turnConfig.enable_turn = PJ_TRUE;
NSAssert(turnServer, @"TURN server is required");
turnConfig.turn_server = pj_str((char *)turnServer.UTF8String);

if (transportType != nil && [transportType isEqualToString:@"TP_TCP"]) {
turnConfig.turn_conn_type = PJ_TURN_TP_TCP;
}
NSAssert(realm, @"realm is required");
turnConfig.turn_auth_cred.data.static_cred.realm = pj_str((char *)realm.UTF8String);
NSAssert(username, @"username is required");
turnConfig.turn_auth_cred.data.static_cred.username = pj_str((char *)username.UTF8String);
NSAssert(passwordData, @"passwordData is required");
turnConfig.turn_auth_cred.data.static_cred.data = pj_str((char *)passwordData.UTF8String);

bool isHashed = passwordDataType != nil && [passwordDataType isEqualToString:@"HASHED"];
turnConfig.turn_auth_cred.data.static_cred.data_type = isHashed ? PJ_STUN_PASSWD_HASHED : PJ_STUN_PASSWD_PLAIN;
cfg.turn_cfg = turnConfig;
cfg.turn_cfg_use = PJSUA_TURN_CONFIG_USE_CUSTOM;
}

pjsua_acc_id account_id;

Expand Down
32 changes: 31 additions & 1 deletion ios/RTCPjSip/PjSipEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

@property NSMutableDictionary* accounts;
@property NSMutableDictionary* calls;
@property(nonatomic, strong) RCTBridge *bridge;
@property (nonatomic, strong) RCTBridge *bridge;
@property (nonatomic, strong) NSArray *stunServerList;
@property (nonatomic, strong) NSDictionary *turnServerConfig;

@property pjsua_transport_id tcpTransportId;
@property pjsua_transport_id udpTransportId;
Expand All @@ -22,6 +24,34 @@

-(void) updateStunServers: (int) accountId stunServerList:(NSArray *)stunServerList;

/**
* @brief TURN configuration
* @discussion This method accepts a key-value object with TURN server configuration.
*
* Usage:
* <b>server</b> - Specify TURN domain name or host name in "DOMAIN:PORT" or "HOST:PORT" format.
* value type: string
*
* <b>tp_type</b> - TURN transport type.
* value type: string
* value: "TP_UDP" or "TP_TCP".
*
* <b>realm</b> - If not-empty, it indicates that this is a long term credential.
* value type: string
*
* <b>username</b> - The username of the credential.
* value type: string
*
* <b>password_data_type</b> - Data type to indicate the type of password in the \a data field.
* value type: string
* value: "PLAIN" or "HASHED".
*
* <b>data</b> - The data, which depends depends on the value of \a data_type
* field. When \a data_type is zero, this field will contain the
* plaintext password.
*/
-(void) updateTurnSever: (int) accountId configuration: (NSDictionary*) turnConfiguration;

-(PjSipAccount *)createAccount:(NSDictionary*) config;
-(void) deleteAccount:(int) accountId;
-(PjSipAccount *)findAccount:(int)accountId;
Expand Down
65 changes: 60 additions & 5 deletions ios/RTCPjSip/PjSipEndpoint.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,25 @@ - (NSDictionary *)start: (NSDictionary *)config {
[callsResult addObject:[call toJsonDictionary:self.isSpeaker]];
}

if ([accountsResult count] > 0 && config[@"service"] && config[@"service"][@"stun"]) {
for (NSDictionary *account in accountsResult) {
int accountId = account[@"_data"][@"id"];
[[PjSipEndpoint instance] updateStunServers:accountId stunServerList:config[@"service"][@"stun"]];
NSArray *stunServerList = config[@"service"][@"stun"];
if (stunServerList) {
self.stunServerList = stunServerList;
if ([accountsResult count] > 0) {
for (NSDictionary *account in accountsResult) {
int accountId = (int)account[@"_data"][@"id"];
[[PjSipEndpoint instance] updateStunServers:accountId stunServerList:stunServerList];

}
}
}
NSDictionary *turnServerConfiguration = config[@"service"][@"turn"];
if (turnServerConfiguration) {
self.turnServerConfig = turnServerConfiguration;
if ([accountsResult count] > 0) {
for (NSDictionary *account in accountsResult) {
int accountId = (int)account[@"_data"][@"id"];
[[PjSipEndpoint instance] updateTurnSever: accountId configuration: turnServerConfiguration];
}
}
}

Expand All @@ -190,10 +205,50 @@ - (void)updateStunServers:(int)accountId stunServerList:(NSArray *)stunServerLis
pjsua_acc_modify(accountId, &cfg_update);
}

-(void) updateTurnSever: (int) accountId configuration: (NSDictionary*) turnConfiguration {
pjsua_acc_config cfg_update;
pj_pool_t *pool = pjsua_pool_create("tmp-pjsua", 1000, 1000);
pjsua_acc_config_default(&cfg_update);
pjsua_acc_get_config(accountId, pool, &cfg_update);

pjsua_acc_modify(accountId, &cfg_update);
NSString *turnServer = turnConfiguration[@"server"];
NSString *transportType = turnConfiguration[@"tp_type"];
NSString *realm = turnConfiguration[@"realm"];
NSString *username = turnConfiguration[@"username"];
NSString *passwordDataType = turnConfiguration[@"password_data_type"];
NSString *passwordData = turnConfiguration[@"data"];

pjsua_turn_config turnConfig;
turnConfig.enable_turn = PJ_TRUE;
NSAssert(turnServer, @"TURN server is required");
turnConfig.turn_server = pj_str((char *)turnServer.UTF8String);

if (transportType != nil && [transportType isEqualToString:@"TP_TCP"]) {
turnConfig.turn_conn_type = PJ_TURN_TP_TCP;
}
NSAssert(realm, @"realm is required");
turnConfig.turn_auth_cred.data.static_cred.realm = pj_str((char *)realm.UTF8String);
NSAssert(username, @"username is required");
turnConfig.turn_auth_cred.data.static_cred.username = pj_str((char *)username.UTF8String);
NSAssert(passwordData, @"passwordData is required");
turnConfig.turn_auth_cred.data.static_cred.data = pj_str((char *)passwordData.UTF8String);
bool isHashed = passwordDataType != nil && [passwordDataType isEqualToString:@"HASHED"];
turnConfig.turn_auth_cred.data.static_cred.data_type = isHashed ? PJ_STUN_PASSWD_HASHED : PJ_STUN_PASSWD_PLAIN;
cfg_update.turn_cfg = turnConfig;
pjsua_acc_modify(accountId, &cfg_update);
pj_pool_release(pool);
}

- (PjSipAccount *)createAccount:(NSDictionary *)config {
PjSipAccount *account = [PjSipAccount itemConfig:config];
self.accounts[@(account.id)] = account;

if (self.stunServerList) {
[[PjSipEndpoint instance] updateStunServers:account.id stunServerList:self.stunServerList];
}
if (self.turnServerConfig) {
[[PjSipEndpoint instance] updateTurnSever:account.id configuration:self.turnServerConfig];
}
return account;
}

Expand Down