I am messing around with xmpp and I see that the connected delegate method never fires.
I have an openfire server running where I can login.
I also have Spark running where I can login.
Currently the delegate methods are firing in this order.
1. xmppStreamWillConnect
2. socketDidConnect
3. xmppStreamDidStartNegotiation
Nothing happens after this point.
Does anyone know why this happens?
Here is my connection..
let jId = XMPPJID(string: "admin#127.0.0.1")
ChatManager(jID: jId!, host: "127.0.0.1", password: "openfire")
Then inside the chat manager..
import Foundation
import XMPPFrameworkSwift
public final class ChatManager: NSObject {
var stream: XMPPStream!
var jID: XMPPJID
let host: String
let port: UInt16
let password: String
init(jID: XMPPJID, host: String, port: UInt16 = 32876, password: String) {
self.jID = jID
self.host = host
self.port = port
self.password = password
// Setup the XMPPStream
stream = XMPPStream()
stream.hostName = self.host
stream.hostPort = self.port
stream.myJID = self.jID
stream.startTLSPolicy = .allowed
super.init()
stream.addDelegate(self, delegateQueue: DispatchQueue.main)
connect()
}
private func connect(){
if !self.stream.isDisconnected {
}
let timeoutInterval: TimeInterval = 5.0
do {
try stream.connect(withTimeout: XMPPStreamTimeoutNone)
} catch {}
}
}
extension ChatManager: XMPPStreamDelegate {
public func xmppStreamDidSecure(_ sender: XMPPStream) {
print("Secured...")
}
public func xmppStreamDidStartNegotiation(_ sender: XMPPStream) {
print("Negotiation Started..")
}
public func xmppStream(_ sender: XMPPStream, willSecureWithSettings settings: NSMutableDictionary) {
print("Will secure...")
print("Settings: \(settings)")
}
public func xmppStream(_ sender: XMPPStream, didReceive trust: SecTrust, completionHandler: #escaping (Bool) -> Void) {
print("Recieved trust")
}
public func xmppStreamWillConnect(_ sender: XMPPStream) {
print("Attempting to connect...")
}
public func xmppStreamDidConnect(_ sender: XMPPStream) {
print("Connected")
try! stream.authenticate(withPassword: password)
}
public func xmppStreamConnectDidTimeout(_ sender: XMPPStream) {
print("Connection timeout")
}
public func xmppStreamWasTold(toAbortConnect sender: XMPPStream) {
print("Abortion connect")
}
public func xmppStreamDidAuthenticate(_ sender: XMPPStream) {
print("Stream: Authenticated")
}
public func xmppStream(_ sender: XMPPStream, didNotAuthenticate error: DDXMLElement) {
print("Stream: Not Authenticated")
}
public func xmppStream(_ sender: XMPPStream, socketDidConnect socket: GCDAsyncSocket) {
print("Connected socket")
}
}
Console Output
Related
I am beginner in XMPP. I want to implement chat application with OpenFire server. I am able to make the proper connection with the server, but when I want to send any message to another Jabberid, I am receiving an error
SEND: <iq type="error" to="DOMAINMANE" id="348-5581"><query xmlns="jabber:iq:version"/><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>
Here is the code,which I tried
extension AppDelegate{
private func setupStream() {
//xmppRoster = XMPPRoster(rosterStorage: xmppRosterStorage)
xmppRoster.activate(xmppStream)
self.xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
self.xmppRoster.addDelegate(self, delegateQueue: DispatchQueue.main)
}
func connect() -> Bool {
if !xmppStream.isConnected {
let jabberID = GlobleConstants.senderJID
if !xmppStream.isDisconnected {
return true
}
xmppStream.myJID = XMPPJID(string: jabberID)
do {
try xmppStream.connect(withTimeout: XMPPStreamTimeoutNone)
self.xmppMessageDeliveryRecipts.autoSendMessageDeliveryReceipts = true
self.xmppMessageDeliveryRecipts.autoSendMessageDeliveryRequests = true
self.xmppMessageDeliveryRecipts.activate(self.xmppStream)
print("Connection success")
return true
} catch {
print("Something went wrong!")
return false
}
} else {
return true
}
}
func disconnect() {
goOffline()
xmppStream.disconnect()
}
private func goOnline() {
let presence = XMPPPresence()
let domain = xmppStream.myJID?.domain
if domain == GlobleConstants.XMPPHOSTNAME || domain == "gmail.com" || domain == "gtalk.com" ||
domain == "talk.google.com" {
let priority = DDXMLElement.element(withName: "priority", stringValue: "24") as! DDXMLElement
presence.addChild(priority)
}
xmppStream.send(presence)
}
private func goOffline() {
let presence = XMPPPresence(type: "unavailable")
xmppStream.send(presence)
}
}
extension AppDelegate : XMPPStreamDelegate{
func xmppStreamDidConnect(_ sender: XMPPStream) {
do {
try xmppStream.authenticate(withPassword: GlobleConstants.sPassword)
} catch {
print("Could not authenticate")
}
}
func xmppStreamDidAuthenticate(_ sender: XMPPStream) {
goOnline()
}
func xmppStream(_ sender: XMPPStream, didReceive iq: XMPPIQ) -> Bool {
print("Did receive IQ")
return false
}
func xmppStream(_ sender: XMPPStream, didReceive message: XMPPMessage) {
print("Did send message \(message)")
}
func xmppStream(_ sender: XMPPStream, didReceive presence: XMPPPresence) {
print("IN APPDELEGATE -----> ", presence)
let presenceType = presence.presenceType?.rawValue
let myUsername = sender.myJID?.user
let presenceFromUser = presence.from?.user
print("MY USERNAME ",myUsername)
print("OTHER USER NAME ",presenceFromUser)
print("PRESNET ",presenceType)
**//HERE ALSO NOT GETTING ANOTHER ONLINE USER, SO THAT I CAN ADD INTO ONLINE BUDDIES LIST**
/*if presenceFromUser != myUsername {
print("Did receive presence from \(presenceFromUser)")
if presenceType == "available" {
delegate.buddyWentOnline(name: "\(presenceFromUser)#\(GlobleConstants.XMPPHOSTNAME)")
} else if presenceType == "unavailable" {
delegate.buddyWentOffline(name: "\(presenceFromUser)#\(GlobleConstants.XMPPHOSTNAME)")
}
}*/
}
}
extension AppDelegate : XMPPRosterDelegate{
func xmppRoster(_ sender: XMPPRoster, didReceiveRosterItem item: DDXMLElement) {
print("Did receive Roster item")
}
}
And now inside of the controller, I am trying to fetch online buddies by
func setupUI(){
appDelegate.delegate = self
if appDelegate.connect() {
self.title = appDelegate.xmppStream.myJID?.user
appDelegate.xmppRoster.fetch()
}
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
But getting the same error. Anyone having solution for the same?
You are not getting an error, you are sending one. After your client connects, Openfire queries it for its software version. Your client does not support that request, and sends back an error to Openfire ("feature not implemented"). This is perfectly reasonable, and no cause for concern.
If you want to get rid of the error, you can make your client respond to queries as defined in the protocol at https://xmpp.org/extensions/xep-0092.html
I'm using the Startscream Websocket framework. Everything works fine as long as I keep all of the code in a UIViewController as seen here. But as soon as a create a wrapper class for Startscream all of the delegated functions stop working. Also my local websocket server is not getting a connection.
How can I get the code working inside a wrapper class?
MyService.swift:
import Starscream
public class MyService: WebSocketDelegate {
var socket = WebSocket(url: URL(string: "ws://localhost:3900/websocket")!)
func connect() {
socket.delegate = self
socket.connect()
print("Connecting")
}
// MARK: Websocket Delegate Methods.
public func websocketDidConnect(socket: WebSocket) {
print("websocket is connected")
}
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
print("Received text: \(text)")
}
public func websocketDidReceiveData(socket: WebSocket, data: Data) {
print("Received data: \(data.count)")
}
// MARK: Write Text Action
#IBAction func writeText(_ sender: UIBarButtonItem) {
socket.write(string: "hello there!")
}
// MARK: Disconnect Action
#IBAction func disconnect(_ sender: UIBarButtonItem) {
if socket.isConnected {
sender.title = "Connect"
socket.disconnect()
} else {
sender.title = "Disconnect"
socket.connect()
}
}
}
ViewController.swift:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let service = MyService()
service.connect()
}
}
The reference to Service in ViewController was not stored anywhere so as soon as the function was run it was cleaned up. This is how I fixed it:
class ViewController: UIViewController {
var service = MyService()
override func viewDidLoad() {
super.viewDidLoad()
service.connect()
}
...
I'm not sure what is wrong with your code, it can be an endpoint issue, or WS is not allocated somehow. I have same code with Starscream working in Swift 3, here is the main part of my class.
class ConnectionManager {
private var savedSocket: WebSocket?
fileprivate var socket: WebSocket {
if let saved = savedSocket {
return saved
}
let wsURL = URL(string: UserDefaultsManager.wsURLString)!
savedSocket = WebSocket(url: wsURL)
return savedSocket!
}
func startSession() {
if (socket.isConnected) { return }
socket.headers = headers
socket.delegate = self
socket.connect()
}
func endSession() {
if (socket.isConnected) {
socket.disconnect()
}
}
}
extension ConnectionManager: WebSocketDelegate {
func websocketDidConnect(socket: WebSocket) {
}
func websocketDidDisconnect(socket: WebSocket, error: NSError?){
if let e = error {
log.error("websocket is disconnected with ERROR: \(e.localizedDescription)")
} else {
log.error("websocket disconnected")
}
}
func websocketDidReceiveMessage(socket: WebSocket, text: String){
}
func websocketDidReceiveData(socket: WebSocket, data: Data){
}
}
My code is not a best practise for sure, but it works without any problem. Try to use my version, maybe it will work for you.
I try to migrate delegate of DifficultyViewDelegate to observable. This is my DifficultyViewDelegate :
#objc protocol DifficultyViewDelegate: class {
func levelDidIncrease()
func levelDidDecrease()
}
And my DifficultyView :
weak var delegate: DifficultyViewDelegate?
#IBAction func decreaseLevel(_ sender: Any) {
delegate?.levelDidDecrease()
}
#IBAction func increaseLevel(_ sender: Any) {
delegate?.levelDidIncrease()
}
And this is my RxDifficultyViewDelegateProxy
class RxDifficultyViewDelegateProxy: DelegateProxy, DelegateProxyType {
static func currentDelegateFor(_ object: AnyObject) -> AnyObject? {
let difficultyView: DifficultyView = object as! DifficultyView
return difficultyView.delegate
}
static func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) {
let difficultyView: DifficultyView = object as! DifficultyView
difficultyView.delegate = delegate as? DifficultyViewDelegate
}
}
I also added an extension on my DifficultyView :
extension DifficultyView {
public var rx_delegate: RxDifficultyViewDelegateProxy {
return RxDifficultyViewDelegateProxy.proxyForObject(RxDifficultyViewDelegateProxy.self)
}
public var rx_levelDidIncrease: Observable<Void> {
return rx_delegate.methodInvoked(#selector(DifficultyViewDelegate.levelDidIncrease)).map { _ in return }
}
}
But it seems that when I do :
difficultyView.rx_levelDidIncrease.asObservable().subscribe(onNext: {
print("did increase")
}).addDisposableTo(disposeBag)
It's never called. Someone has any pointers ?
Try use PublishSubject:
DifficultyView:
class DifficultyView: UIView {
var levelDidIncrease = PublishSubject<Void>()
var levelDidDecrease = PublishSubject<Void>()
#IBAction func decreaseLevel(_ sender: Any) {
levelDidDecrease.onNext()
}
#IBAction func increaseLevel(_ sender: Any) {
levelDidIncrease.onNext()
}
}
And then:
var difficultyView = DifficultyView()
difficultyView.levelDidDecrease.asObservable()
.subscribe(onNext: {
print("did decrease")
})
.addDisposableTo(disposeBag)
difficultyView.decreaseLevel(theSender) // <- THIS line performs the side effect
currently i am making chat application using Web Socket.
My question is How to Call Web Service in Web Socket ?
In iOS using swift you can use two Cocoapods Library which makes your work hassle free and
1) Starscream
2) RocketSocket
With reference to Starscream follow are very handy example:
import UIKit
import Starscream
class ViewController: UIViewController, WebSocketDelegate {
var socket: WebSocket!
override func viewDidLoad() {
super.viewDidLoad()
var request = URLRequest(url: URL(string: "http://localhost:8080")!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
// MARK: Websocket Delegate Methods.
func websocketDidConnect(socket: WebSocketClient) {
print("websocket is connected")
}
func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
if let e = error as? WSError {
print("websocket is disconnected: \(e.message)")
} else if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
print("Received text: \(text)")
}
func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
print("Received data: \(data.count)")
}
// MARK: Write Text Action
#IBAction func writeText(_ sender: UIBarButtonItem) {
socket.write(string: "hello there!")
}
// MARK: Disconnect Action
#IBAction func disconnect(_ sender: UIBarButtonItem) {
if socket.isConnected {
sender.title = "Connect"
socket.disconnect()
} else {
sender.title = "Disconnect"
socket.connect()
}
}
}
BACKGROUND:
I want to be able to send and receive UDP packets between my iOS app and a server.
The server echoes back every incoming message to the client the app. The server is tested and confirmed working. I have a StartViewController which starting up two classes that implements GCDAsyncUdpSocketDelegate, one for sending and one for receiving. The "sending socket" is working, the server receives the messages.
PROBLEM:
The app never get the incoming message back after it been sent. Something with the listening socket setup is probably wrong since didReceiveData never get called.
Have I done this completely wrong?
Start:
class StartViewController: UIViewController {
var inSocket : InSocket!
var outSocket : OutSocket!
override func viewDidLoad() {
super.viewDidLoad()
inSocket = InSocket()
outSocket = OutSocket()
}
#IBAction func goButton(sender: UIButton) {
outSocket.send("This is a message!")
}
}
Receive:
class InSocket: NSObject, GCDAsyncUdpSocketDelegate {
let IP = "255.255.255.255"
let PORT:UInt16 = 5556
var socket:GCDAsyncUdpSocket!
override init(){
super.init()
setupConnection()
}
func setupConnection(){
var error : NSError?
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
socket.bindToPort(PORT, error: &error)
socket.enableBroadcast(true, error: &error)
socket.joinMulticastGroup(IP, error: &error)
socket.beginReceiving(&error)
}
func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) {
println("incoming message: \(data)");
}
}
Send:
class OutSocket: NSObject, GCDAsyncUdpSocketDelegate {
let IP = "90.112.76.180"
let PORT:UInt16 = 5556
var socket:GCDAsyncUdpSocket!
override init(){
super.init()
setupConnection()
}
func setupConnection(){
var error : NSError?
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
socket.connectToHost(IP, onPort: PORT, error: &error)
}
func send(message:String){
let data = message.dataUsingEncoding(NSUTF8StringEncoding)
socket.sendData(data, withTimeout: 2, tag: 0)
}
func udpSocket(sock: GCDAsyncUdpSocket!, didConnectToAddress address: NSData!) {
println("didConnectToAddress");
}
func udpSocket(sock: GCDAsyncUdpSocket!, didNotConnect error: NSError!) {
println("didNotConnect \(error)")
}
func udpSocket(sock: GCDAsyncUdpSocket!, didSendDataWithTag tag: Int) {
println("didSendDataWithTag")
}
func udpSocket(sock: GCDAsyncUdpSocket!, didNotSendDataWithTag tag: Int, dueToError error: NSError!) {
println("didNotSendDataWithTag")
}
}
Edit:
Added forgotten code line.
I finally got it to work with this socket setup:
func setupConnection(){
var error : NSError?
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
socket.bindToPort(PORT, error: &error)
socket.connectToHost(SERVER_IP, onPort: PORT, error: &error)
socket.beginReceiving(&error)
send("ping")
}
func send(message:String){
let data = message.dataUsingEncoding(NSUTF8StringEncoding)
socket.sendData(data, withTimeout: 2, tag: 0)
}
Apple Swift version 4.2.1 Well Tested UDP Example:-
STEP 1 :- pod 'CocoaAsyncSocket'
STEP 2 :- import CocoaAsyncSocket in your UIViewController.
STEP 3 :- UIViewController
import UIKit
import CocoaAsyncSocket
class ViewController: UIViewController {
#IBOutlet weak var btnOnOff: LightButton!
#IBOutlet weak var lblStatus: UILabel!
var inSocket : InSocket!
var outSocket : OutSocket!
override func viewDidLoad() {
super.viewDidLoad()
lblStatus.isHidden = true
inSocket = InSocket()
outSocket = OutSocket()
outSocket.setupConnection {
self.lblStatus.isHidden = false
}
}
#IBAction func btnLight(_ sender: Any) {
let signal:Signal = Signal()
self.outSocket.send(signal: signal)
}
}
STEP 4 :- Reciving Socket
//Reciving End...
class InSocket: NSObject, GCDAsyncUdpSocketDelegate {
//let IP = "10.123.45.2"
let IP = "127.0.0.1"
let PORT:UInt16 = 5001
var socket:GCDAsyncUdpSocket!
override init(){
super.init()
setupConnection()
}
func setupConnection(){
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue:DispatchQueue.main)
do { try socket.bind(toPort: PORT)} catch { print("")}
do { try socket.enableBroadcast(true)} catch { print("not able to brad cast")}
do { try socket.joinMulticastGroup(IP)} catch { print("joinMulticastGroup not proceed")}
do { try socket.beginReceiving()} catch { print("beginReceiving not proceed")}
}
//MARK:-GCDAsyncUdpSocketDelegate
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
print("incoming message: \(data)");
let signal:Signal = Signal.unarchive(d: data)
print("signal information : \n first \(signal.firstSignal) , second \(signal.secondSignal) \n third \(signal.thirdSignal) , fourth \(signal.fourthSignal)")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
}
func udpSocketDidClose(_ sock: GCDAsyncUdpSocket, withError error: Error?) {
}
}
STEP 5 :- Sending Socket..
//Sending End...
class OutSocket: NSObject, GCDAsyncUdpSocketDelegate {
// let IP = "10.123.45.1"
let IP = "127.0.0.1"
let PORT:UInt16 = 5001
var socket:GCDAsyncUdpSocket!
override init(){
super.init()
}
func setupConnection(success:(()->())){
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue:DispatchQueue.main)
do { try socket.bind(toPort: PORT)} catch { print("")}
do { try socket.connect(toHost:IP, onPort: PORT)} catch { print("joinMulticastGroup not proceed")}
do { try socket.beginReceiving()} catch { print("beginReceiving not proceed")}
success()
}
func send(signal:Signal){
let signalData = Signal.archive(w: signal)
socket.send(signalData, withTimeout: 2, tag: 0)
}
//MARK:- GCDAsyncUdpSocketDelegate
func udpSocket(_ sock: GCDAsyncUdpSocket, didConnectToAddress address: Data) {
print("didConnectToAddress");
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
if let _error = error {
print("didNotConnect \(_error )")
}
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didNotSendDataWithTag tag: Int, dueToError error: Error?) {
print("didNotSendDataWithTag")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didSendDataWithTag tag: Int) {
print("didSendDataWithTag")
}
}
STEP 6 :- Your Signal Data which you will Send/Recieve
import Foundation
struct Signal {
var firstSignal:UInt16 = 20
var secondSignal:UInt16 = 30
var thirdSignal: UInt16 = 40
var fourthSignal: UInt16 = 50
static func archive(w:Signal) -> Data {
var fw = w
return Data(bytes: &fw, count: MemoryLayout<Signal>.stride)
}
static func unarchive(d:Data) -> Signal {
guard d.count == MemoryLayout<Signal>.stride else {
fatalError("BOOM!")
}
var s:Signal?
d.withUnsafeBytes({(bytes: UnsafePointer<Signal>)->Void in
s = UnsafePointer<Signal>(bytes).pointee
})
return s!
}
}