I have added pjsip lib through cocoapods from here https://github.com/chebur/pjsip.
No I'm trying to connect to sip server using this pjsip example.
Here is my code:
func startPjsip() {
var status: pj_status_t
// Create pjsua first
status = pjsua_create()
if status != Int32(PJ_SUCCESS.rawValue) {
pjsuaError("Error in pjsua_create()", status: status)
}
// Init Pjsua
var config = pjsua_config()
pjsua_config_default(&config)
// on reg state
config.cb.on_reg_state = { (accountId: pjsua_acc_id) in
p("on_reg_state", accountId)
}
// Init the logging config structure
var logConfig = pjsua_logging_config()
pjsua_logging_config_default(&logConfig)
logConfig.console_level = 4
// Init the pjsua
status = pjsua_init(&config, &logConfig, nil)
if status != Int32(PJ_SUCCESS.rawValue) {
pjsuaError("Error in pjsua_init()", status: status)
}
// Adding UDP transport
// Init transport config structure
var udpTransportConfig = pjsua_transport_config()
pjsua_transport_config_default(&udpTransportConfig)
udpTransportConfig.port = 5060
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpTransportConfig, nil)
if status != Int32(PJ_SUCCESS.rawValue) {
pjsuaError("Error in creating UDP transport", status: status)
}
// Initialization is done, now start pjsua
status = pjsua_start()
if status != Int32(PJ_SUCCESS.rawValue) {
pjsuaError("Error starting pjsua", status: status)
}
// Register the account on local sip server
var accountConfig = pjsua_acc_config()
pjsua_acc_config_default(&accountConfig)
// username
let username = "10001"
let domain = "voip01.interpreters.travel"
let userId = "sip:\(username)#\(domain)"
accountConfig.id = pj_str_t(ptr: stringToPointer(string: userId), slen: pj_ssize_t(userId.characters.count))
// uri
var uri = "sip:\(domain)"
accountConfig.reg_uri = pj_str_t(ptr: stringToPointer(string: uri), slen: pj_ssize_t(uri.characters.count))
accountConfig.cred_count = 1
accountConfig.cred_info.0.realm = pj_str_t(ptr: stringToPointer(string: "*"), slen: pj_ssize_t("*".characters.count))
let scheme = "digest"
accountConfig.cred_info.0.scheme = pj_str_t(ptr: stringToPointer(string: scheme), slen: pj_ssize_t(scheme.characters.count))
accountConfig.cred_info.0.data_type = Int32(PJSIP_CRED_DATA_PLAIN_PASSWD.rawValue)
let password = "10001"
accountConfig.cred_info.0.data = pj_str_t(ptr: stringToPointer(string: password), slen: pj_ssize_t(password.characters.count))
accountConfig.cred_info.0.username = pj_str_t(ptr: stringToPointer(string: username), slen: pj_ssize_t(username.characters.count))
var accountId = pjsua_acc_id()
status = pjsua_acc_add(&accountConfig, pj_bool_t(PJ_TRUE.rawValue), &accountId)
p(accountId)
if status != Int32(PJ_SUCCESS.rawValue) {
pjsuaError("Error adding account", status: status)
}
}
func pjsuaError(_ message: String, status: pj_status_t) {
let url = NSURL(fileURLWithPath: #file)
let fileName: String = url.lastPathComponent == nil ? #file : url.lastPathComponent!
pjsua_perror(fileName, message, status)
pjsua_destroy()
}
func stringToPointer(string: String) -> UnsafeMutablePointer<Int8> {
let cs = (string as NSString).utf8String
return UnsafeMutablePointer<Int8>(mutating: cs!)
}
When I run application I've got request sending to sip server, it returns 401 Unauthorized (log is here), which seems to be fine according to this doc.
After that pjsip send another request and sip server return 403 Forbidden, here is the log.
I've asked my server guy what is the problem and he said that he used the same credentials with JsSIP lib for browser client and everything works fine for him. Here is the log he gave to me.
I have looked at his log and see difference in these lines:
mine - Via: SIP/2.0/UDP
his - Via: SIP/2.0/WSS
So seems that I'm using wrong transport protocol. But I don't know how to set pjsip to use wss protocol.
Can someone help me if you have the same issues. Or what I need to read/try to achieve my goal.
UPDATE:
I have added Starscream, and got it working to connect to wss:// url. Here is the code:
var socket: WebSocket!
override func viewDidLoad() {
super.viewDidLoad()
socket = WebSocket(url: URL(string: "wss://voip01.interpreters.travel:4443")!)
socket.delegate = self
socket.pongDelegate = self
socket.headers["Sec-WebSocket-Protocol"] = "sip"
socket.connect()
}
func websocketDidConnect(socket: WebSocket) {
print("websocketDidConnect")
print(socket)
}
It says "websocketDidConnect". But now I need to send SIP REGISTER through this wss transport protocol. I can't find any information how to setup pjsip to use wss.
I have tried to change pjsua_transport_create with PJSIP_TRANSPORT_TCP or TLS but no success.
Please, can someone help me where to find information about pjsip + websocket support.
Related
I am developing app with video calling functionality and I am using Twilio Video for that.
Currently using TwilioVideo SDK v4.6.2 and iOS Version 14.x and Above
I am not able to connect to the TwilioVideo room
Below is my code:
func connect() {
guard let accessToken = self.accessToken, let roomName = self.roomName else {
return
}
prepareAudio()
prepareCamera()
let connectOptions = ConnectOptions(token: accessToken) { (builder) in
builder.isDominantSpeakerEnabled = true
builder.isNetworkQualityEnabled = true
if let localAudioTrack = self.localAudioTrack {
builder.audioTracks = [localAudioTrack]
}
if let localVideoTrack = self.localVideoTrack {
builder.videoTracks = [localVideoTrack]
}
if let preferredAudioCodec = TwiloVideoSettingsManager.shared.audioCodec {
builder.preferredAudioCodecs = [preferredAudioCodec]
}
if let preferredVideoCodec = TwiloVideoSettingsManager.shared.videoCodec {
builder.preferredVideoCodecs = [preferredVideoCodec]
}
if let encodingParameters = TwiloVideoSettingsManager.shared.getEncodingParameters() {
builder.encodingParameters = encodingParameters
}
builder.region = "gll"
builder.roomName = roomName
}
self.room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
UIApplication.shared.isIdleTimerDisabled = true
}
Response in not received from Twilio in either of the methods mentioned below
func didConnect(to room: Room) {
NSLog("Room: \(room.name) SID: \(room.sid)")
if (room.remoteParticipants.count > 0) {
self.remoteParticipant = room.remoteParticipants[0]
self.remoteParticipant.delegate = self
}
self.delegate.videoServiceManagerDidConnectToRoom(name:room.name)
}
func roomDidFailToConnect(room: Room, error: Error) {
NSLog("Failed to connect to a Room: \(error).")
self.delegate.videoServiceManagerFailToConnectRoom(error: error.localizedDescription)
self.leaveRoom()
}
I am not able connect to the room every time and sometimes I get the error mentioned below :
Failed to connect to a Room: Error Domain=com.twilio.video Code=53000 "Signaling connection error" UserInfo={NSLocalizedDescription=Signaling connection error, NSLocalizedFailureReason=SIP error 408}.
When I check the Twilio logs in debug mode I am not getting any error.
Please guide me to rectify if there is any mistake in my code
Twilio employee here. Error 53000 is somewhat vague and could occur due to different things: https://www.twilio.com/docs/api/errors/53000
I'd suggest the following next steps:
try reproducing this error using the iOS Quickstart app (https://github.com/twilio/video-quickstart-ios)
try running our Networktest on the problematic device: https://www.networktest.twilio.com
I'm trying GRPC-Swift for Client-Server application.
I'm using GRPC-Swift for both Client and Server
Client is an iPhone application, which I tried with iPhone Simulator.
I followed this link for Client-side streaming RPC.
When I send message to Server from Client, I got the following error message in the console from Server,
error io.grpc.server_channel_call : unable to determine http version
From the Server in the
HTTPProtocolSwitcher.swift
inside the function func channelRead(context: ChannelHandlerContext, data: NIOAny), it is checking for HTTPProtocolVersion, and it is missing.
How to send the HTTPVersion from the Client code?
Update:
Client Code
import GRPC
import NIO
class HTTPClient {
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
private var channel: ClientConnection?
private var client: ChatGuide_ChatGuideClient?
private var clientCall: ClientStreamingCall<ChatGuide_TextMessage, ChatGuide_TextMessage>?
func connect(host: String, port: Int) throws {
let channel = ClientConnection.secure(group: self.group)
.connect(host: host, port: port)
self.channel = channel
self.client = ChatGuide_ChatGuideClient(channel: channel)
}
func disconnect() {
do {
self.clientCall?.sendEnd(promise: nil)
_ = try self.clientCall?.status.wait()
try self.group.syncShutdownGracefully()
} catch let error {
print("\(type(of: self)): Could not shutdown gracefully -", error.localizedDescription)
}
}
func initiateClient() {
let timeAmount = TimeAmount.minutes(1)
let timeLimit = TimeLimit.timeout(timeAmount)
let options = CallOptions(timeLimit: timeLimit)
let call = self.client?.chat(callOptions: options)
call?.response.whenSuccess { (message) in
print("\(type(of: self)): Message from server -", message.text)
}
call?.response.whenFailure { (error) in
print("\(type(of: self)): Response error -", error.localizedDescription)
}
self.clientCall = call
}
func send(text: String) {
if self.clientCall == nil {
self.initiateClient()
}
let message = ChatGuide_TextMessage.with {
$0.text = text
}
self.clientCall?.sendMessage(message, promise: nil)
}
}
Hey Vignesh,
I am currently learning gRPC-Swift myself, so I hope I will be of service and not muck things further.
However, it looks to me that you are not configuring the HTTP/1.x layer in order to transfer Protobuf packets, if you take a look at the HTTP1ToGRPCServerCodec.swift file Here
I think you will have a much clearer idea of how to adjust your code, I am sorry I can't provide more details, however not being too sure myself without further testing and reviewing the codebase.
Best regards and keep me posted if indeed i was helpful,
cheers
From the Server I have initiated insecure Server as,
let server = Server.insecure(group: self.group)
From the Client I have initiated secure ClientConnection as,
let channel = ClientConnection.secure(group: self.group)
And I got this clarification from here
So I made the ClientConnection also insecure as,
let channel = ClientConnection.insecure(group: self.group)
And after this it is working now.
I have implemented the NEHotspotHelper so that I can perform authentication in the background for networks with a captive portal.
I need to perform a web request in the 'authenticating' state so that I can retrieve the Wispr and also access an API.
However, when I try to use URLSession to send a web request, the request fails. This is the error:
[594:88737] dnssd_clientstub read_all(7) DEFUNCT
[594:88783] TIC TCP Conn Failed [4:0x1c0177a00]: 12:8 Err(-65554)
[594:88783] Task <FFD0DAE6-4864-437D-94F2-C9ED5D5748E2>.<1> HTTP load failed (error code: -1003 [12:8])
[594:88783] Task <FFD0DAE6-4864-437D-94F2-C9ED5D5748E2>.<1> finished with error - code: -1003
See a snippet of my code:
let registered = NEHotspotHelper.register(options: options, queue: queue) { (cmd: NEHotspotHelperCommand) in
print("Received command: \(cmd.commandType.rawValue)")
if cmd.commandType == NEHotspotHelperCommandType.filterScanList {
//Get all available hotspots
print("filter scan list")
var list: [NEHotspotNetwork] = cmd.networkList!
var response: NEHotspotHelperResponse
for l in list {
if (l.ssid=="my-ssid") {
response = cmd.createResponse(NEHotspotHelperResult.success)
} else {
response = cmd.createResponse(NEHotspotHelperResult.failure)
}
response.setNetworkList([chosenNetwork])
response.deliver()
}
} else if cmd.commandType == NEHotspotHelperCommandType.evaluate {
if let network = cmd.network {
if (network.ssid=="my-ssid") {
network.setConfidence(NEHotspotHelperConfidence.high)
let response = cmd.createResponse(NEHotspotHelperResult.success)
response.setNetwork(network)
response.deliver() //Respond back
} else {
let response = cmd.createResponse(NEHotspotHelperResult.failure)
response.deliver()
}
}
} else if cmd.commandType == NEHotspotHelperCommandType.authenticate {
print("authenticate")
var response = cmd.createResponse(NEHotspotHelperResult.unsupportedNetwork)
if let network = cmd.network{
if network.ssid == "my-ssid"{
self.queryUrl()
response = cmd.createResponse(NEHotspotHelperResult.success)
}
}
response.deliver() //Respond back
}
}
func queryUrl(){
let config = URLSessionConfiguration.default
config.allowsCellularAccess = false;
let session = URLSession.init(configuration: config)
let url = URL(string: "https://172.217.20.35")
let semaphore = DispatchSemaphore(value: 0)
let task = session.dataTask(with: url!){(data, response, error) in
if data==nil {
print(data as Any)
}
else{
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue) as Any)
}
semaphore.signal()
}
task.resume()
_ = semaphore.wait(timeout: .distantFuture)
}
I was also facing the similar issue. However, I found that developer need to bind the request with the received command before making web request to the connected network. All you need to do is to make NSMutableURLRequest and then call hitTestURLRequest.bind(to: command) because bind function is defined in the category of NSMutableURLRequest.
Others have reported problem with name server resolution from NEHotspotHelper callback. Try using an IP address to make the call.
Also don't forget URLSession works asynchronously. You will need to call response.deliver() only after the web service calls finishes.
This is the just of it:
if cmd.commandType
filterScanList
- SetConfidence to each of your networks in cmd.networkList - High and add to a local list variable.
- create Response.Success
- set Response.NetworkList to your list of confident networks
----
- deliver Response
Evaluate or PresentUI
//If it's your network
- SetConfidence to cmd.network - High
- create Response.Success
- set Response.Network to cmd.network
//If it's not your network
- create Response.UnsupportedNetwork
----
- deliver Response
Authenticate or Maintain
//If it's your network
- SetConfidence to cmd.network - High
- create Response.Success
- set Response.Network to cmd.network
- TRY AUTHENTICATE HERE SYNCHRONOUSLY
//If it's not your network
- create Response.UnsupportedNetwork
----
- deliver Response
Logoff or None
- create Response.Success
----
- deliver Response
is it possible to read, write, ... to/from a MySQL-database hosted on a remote server? I.e. can I connect to the database via SSH and directly make CRUD operations?
Is SSH possible/allowed in iOS, e.g. copying over images to a remote server etc.?
You could use a framework like NMSSH - see it here on Github.
Here is an usage example taken from a project by cagnulein:
var host = "your-host.com"
var username = "user"
var password = "pass"
var session = NMSSHSession(host: host, andUsername: username)
session.connect()
if session.connected == true {
session.authenticateByPassword(password)
if session.authorized == true {
NSLog("Authentication succeeded")
}
var error = NSErrorPointer()
var response = session.channel.execute("ls", error: error)
NSLog("List of my files %#", response)
}
session.disconnect()
Swift 4 & latest NMSSH version
do {
let host = "example.com"
let username = "user"
let password = "pass"
let session = NMSSHSession(host: host, andUsername: username)
session?.connect()
if session?.isConnected ?? false {
session?.authenticate(byPassword: password)
if session?.isAuthorized ?? false {
print("Authentication succeeded")
}
let response = try session?.channel.execute("ls")
print("List of my files:", response)
}
session?.disconnect()
} catch {
print(error)
}
I'm using the MailCore2 at Swift in my iOS application to send message to email in the background without open built-in mail application, But when I'm running app on my device ( real device ) I have this problem:
My complete code for send button:
#IBAction func sendButton(sender: AnyObject) {
var smtpSession = MCOSMTPSession()
smtpSession.hostname = "smtp.gmail.com"
smtpSession.username = "from-email"
smtpSession.password = "password"
smtpSession.port = 465
smtpSession.authType = MCOAuthType.SASLPlain
smtpSession.connectionType = MCOConnectionType.TLS
smtpSession.connectionLogger = {(connectionID, type, data) in
if data != nil {
if let string = NSString(data: data, encoding: NSUTF8StringEncoding){
NSLog("Connectionlogger: \(string)")
}
}
}
var builder = MCOMessageBuilder()
builder.header.to = [MCOAddress(displayName: "AAA", mailbox: "to-email")]
builder.header.from = MCOAddress(displayName: "RRR", mailbox: "from-email")
builder.header.subject = messageTitleTextField.text
var message = messageTextView.text
builder.htmlBody = message
let rfc822Data = builder.data()
let sendOperation = smtpSession.sendOperationWithData(rfc822Data)
sendOperation.start { (error) -> Void in
if (error != nil) {
NSLog("Error sending email: \(error)")
} else {
NSLog("Sent successfully, Thanks!")
}
}
}
Error:
Optional(Error Domain=MCOErrorDomain Code=5 "Unable to authenticate with the current session's credentials." UserInfo={NSLocalizedDescription=Unable to authenticate with the current session's credentials.})
Already I change setting of unsecure app from gmail account but I solved the credentials problem by unlocking gmail account from this link
https://accounts.google.com/DisplayUnlockCaptcha
In my case I had to "Change account access for less secure apps"
https://support.google.com/accounts/answer/6010255?hl=en
If somebody has this problem its quite helpful to know that it is actually problem with security on google side and there it has to be handled...I will leave it because when this happened to me the error didn't say anything I had to search for problem to find out that you have to go to that link on google and find out how to setup it correctly, I wasted time , it will be helpful for others who wants to send mail by smtp with google account