Send message using XMPP openfire in swift 3.0 - swift3

I want to send message using xmpp to openFire everything works perfect even i can receive message. but not able to send i don't know why? i tried this code:
#IBAction func SendMessageClicked(_ sender: AnyObject) {
let message = messageTextField.text
var clientJid: XMPPJID!
clientJid = XMPPJID.init(string: "Bure#ip-772-99-99-99.ec3.internal")
let senderJID = clientJid
let msg = XMPPMessage(type: "chat", to: senderJID)
msg?.addBody(message)
stream?.send(msg)
}
As it doesnot throw any error but message does not send.
Plese help.

let xMessage = XMPPMessage(type: "chat", to: XMPPJID(string: clientJid))
xMessage.addBody(message)
xMessage.addOriginId(stream.generateUUID)
stream.send(xMessage)

I had the same problem and I just found the issue. Make sure the connection is established and authentication is done completely before trying to send messages. To do that you can use these XMPPStreamDelegate functions:
func xmppStreamDidConnect(_ stream: XMPPStream!) {
//Connection is now established
}
func xmppStreamDidAuthenticate(_ sender: XMPPStream!) {
//Athentication is done. Now you can send messages.
}

Related

Data is not reaching to the websocket clients in AWS API Gateway websocket

I have created an lambda function to which I am not able to send the data to the web socket clients. However there is NO error is coming.
Till yesterday code was working. Dont know what happend now it stopped working.
public string FunctionHandler(string input, ILambdaContext context)
{
try
{
string SK = "xxxxxx";
string AK = "xxxx";
var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(input));
var apiClient = new AmazonApiGatewayManagementApiClient(AK,SK,new AmazonApiGatewayManagementApiConfig
{ ServiceURL = $"https://xxxxxx.execute-api.us-east-1.amazonaws.com/Test" });
apiClient.PostToConnectionAsync(new Amazon.ApiGatewayManagementApi.Model.PostToConnectionRequest
{
ConnectionId = "​fdCqPfd0oAMCJmg=",
Data = stream
});
return input.ToUpper();
}
catch(Exception ex)
{
return ex.ToString();
}
}
I gather you're using .NET AmazonApiGatewayManagementApiClient. You're missing the await keyword for apiClient.PostToConnectionAsync():
await apiClient.PostToConnectionAsync(...);
Otherwise you're calling PostToConnectionAsync() without waiting for completion and your Lambda might complete and exit before your request is run and you'll never know about it. (See asynchronous concepts for details)
Alternatively, don't use async method:
apiClient.PostToConnection(...);

How to work with messages from WTelegramClient updates? (get chat/user infos)

I'm new to the WTelegramClient C# Library and was used to TLSharp (not working anymore)
I'm trying to understand how I get User info after update is received,
I have the example code that listen to updates and write them in console
but I can't understand how I can respond to the user that sent the message (new update)
I think I need the user id/access_hash to send message to the sender but I can't understand how
Here is how I get the new messages but it can get only username or name/id
private static void DisplayMessage(MessageBase messageBase, bool edit = false)
{
if (edit) Console.Write("(Edit): ");
switch (messageBase)
{
case Message m: Console.WriteLine($"{Peer(m.from_id) ?? m.post_author} in {Peer(m.peer_id)}> {m.message}"); break;
case MessageService ms: Console.WriteLine($"{Peer(ms.from_id)} in {Peer(ms.peer_id)} [{ms.action.GetType().Name[13..]}]"); break;
}
}
Here i can get the name or username of sender(if have) and the message itself
MessageService ('user' not channel or group) for example get me only firstname and lastname
How to get all info of sender or chat itself (i want to try mark as read the message)
I'm used to TLSharp and the new library WTelegramClient is different.
Thanks!!!
Below is a quick example on how to modify DisplayMessage to react to a message sent in private from a user, get the details about this user, verify who it is and which text was sent to us, and then send him a message back.
Notes:
For this example to work, you will need the latest version of Program_ListenUpdates.cs with static variables
DisplayMessage is now async Task, in order to use await
You can pass user to send a message because class User is implicitly converted to InputPeerUser (with the user id/access_hash).
You can do similarly for messages coming from chats, using PeerChat/PeerChannel classes and the _chats dictionary to get chat details
private static async Task DisplayMessage(MessageBase messageBase, bool edit = false)
{
if (edit) Console.Write("(Edit): ");
switch (messageBase)
{
case Message m:
Console.WriteLine($"{Peer(m.from_id) ?? m.post_author} in {Peer(m.peer_id)}> {m.message}");
if (m.flags.HasFlag(Message.Flags.out_))
break; // ignore our own outgoing messages
if (m.Peer is PeerUser pu) // got a message in a direct chat with a user
{
if (_users.TryGetValue(pu.user_id, out var user)) // get user details
{
if (user.username == "Wiz0u" && m.message == "hello")
{
await Client.SendMessageAsync(user, $"hi {user.first_name}, I'm {My.first_name}");
}
}
}
break;
case MessageService ms:
Console.WriteLine($"{Peer(ms.from_id)} in {Peer(ms.peer_id)} [{ms.action.GetType().Name[13..]}]");
break;
}
}

One request - Two responses. Which end is creating the problem (Front / Back)

Problem:
When I call a request from iOS swift based app, then the server is responding two responses.
Inputs:
In my request, am sending some user values including one base64 image string. I already ensure that my app is calling request only one time.
Outputs:
When we opened the server log, it printed two set of request and response. But, difference that the first one is not having base64 image string and second one is having it. Thats why am receiving two different responses.
Questions:
What end is causing this problem - Front / back end?
Note:
I given front code below but I can’t provide back end code.
let task = urlSession.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
if error != nil
{
print("Error ==",error!.localizedDescription);
onFailure(error!.localizedDescription)
}
else
{
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
// For some critical cases:
//print("Status code: ", statusCode)
//print("http Response: ", httpResponse)
// JSON serialize
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print("Server Response == ",jsonResponse)
onSuccess(statusCode, jsonResponse)
}
catch
{
onFailure("JSON Parser Error")
}
}
})`

How to make synchronous url requests with swift 3

I know the question has been asked before and I agree with most answers that claim it is better to follow the way requests are made async with URLSession in Swift 3. I haver the following scenario, where async request cannot be used.
With Swift 3 and the ability to run swift on servers I have the following problem.
Server Receives a request from a client
To process the request the server has to send a url request and wait for the response to arrive.
Once response arrives, process it and reply to the client
The problem arrises in step 2, where URLSession gives us the ability to initiate an async data task only. Most (if not all) server side swift web frameworks do not support async responses. When a request arrives to the server everything has to be done in a synchronous matter and at the end send the response.
The only solution I have found so far is using DispatchSemaphore (see example at the end) and I am not sure whether that will work in a scaled environment.
Any help or thoughts would be appreciated.
extension URLSession {
func synchronousDataTaskWithURL(_ url: URL) -> (Data?, URLResponse?, Error?) {
var data: Data?
var response: URLResponse?
var error: Error?
let sem = DispatchSemaphore(value: 0)
let task = self.dataTask(with: url as URL, completionHandler: {
data = $0
response = $1
error = $2 as Error?
sem.signal()
})
task.resume()
let result = sem.wait(timeout: DispatchTime.distantFuture)
switch result {
case .success:
return (data, response, error)
case .timedOut:
let error = URLSessionError(kind: URLSessionError.ErrorKind.timeout)
return (data, response, error)
}
}
}
I only have experience with kitura web framework and this is where i faced the problem. I suppose that similar problems exist in all other swift web frameworks.
In Vapor, you can use the Droplet's client to make synchronous requests.
let res = try drop.client.get("https://httpbin.org")
print(res)
Additionally, you can use the Portal class to make asynchronous tasks synchronous.
let res = try Portal.open { portal in
asyncClient.get("https://httpbin.org") { res in
portal.close(with: res)
}
}
Your three-step problem can be solved via the use of a completion handler, i.e., a callback handler a la Node.js convention:
import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
let session = URLSession(configuration: URLSessionConfiguration.default)
Log.logger = HeliumLogger()
let router = Router()
router.get("/test") { req, res, next in
let datatask = session.dataTask(with: URL(string: "http://www.example.com")!) { data, urlResponse, error in
try! res.send(data: data!).end()
}
datatask.resume()
}
Kitura.addHTTPServer(onPort: 3000, with: router)
Kitura.run()
This is a quick demo of a solution to your problem, and it is by no means following best Swift/Kitura practices. But, with the use of a completion handler, I am able to have my Kitura app make an HTTP call to fetch the resource at http://www.example.com, wait for the response, and then send the result back to my app's client.
Link to the relevant API: https://developer.apple.com/reference/foundation/urlsession/1410330-datatask

swift 3.0 TViOS 10.0 MultipeerConnectivity works, but with errors

Using this code to setup Multipeer connectivity under TViOS 10.0.
import UIKit
import MultipeerConnectivity
class MPCHandler: NSObject, MCSessionDelegate {
var peerID: MCPeerID!
var session: MCSession!
var browser: MCBrowserViewController!
var advertiser: MCAdvertiserAssistant? = nil
func setupPeerWithDisplayName (displayName: String) {
peerID = MCPeerID(displayName: UIDevice.current.name)
}
func setupSession() {
session = MCSession(peer: peerID)
session.delegate = self
}
func setupBrowser() {
browser = MCBrowserViewController(serviceType: "my-game", session: session)
}
func advertiseSelf(advertise:Bool) {
if advertise {
advertiser = MCAdvertiserAssistant(serviceType: "my-game", discoveryInfo: nil, session: session)
advertiser!.start()
} else {
advertiser!.stop()
advertiser = nil
}
}
public class MyClass {
static let myNotification = Notification.Name("MPC_DidChangeStateNotification")
}
public class MyClass2 {
static let myNotification = Notification.Name("MPC_DidRecieveDataNotification")
}
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
let userInfo = ["peerID":peerID,"state":state.rawValue] as [String : Any]
DispatchQueue.main.async {
NotificationCenter.default.post(name: MyClass.myNotification, object: nil, userInfo: userInfo)
}
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
let userInfo = ["data":data, "peerID":peerID] as [String : Any]
DispatchQueue.main.async {
NotificationCenter.default.post(name: MyClass2.myNotification, object: nil, userInfo: userInfo)
}
}
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL, withError error: Error?) {
// code
}
func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
// code
}
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
// code
}
}
Reports connected, but I get this errors? Both devices TViOS and iPhone on the same network.
2016-09-08 11:13:13.602572 PeerCodeATV[172:7628] [ViceroyTrace] [ICE][ERROR] ICEStopConnectivityCheck() found no ICE check with call id (1969443468)
2016-09-08 11:13:17.168110 PeerCodeATV[172:7686] [ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed(C01A0041).
2016-09-08 11:13:18.044156 PeerCodeATV[172:7686] [ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed(C01A0041).
2016-09-08 11:13:18.766040 PeerCodeATV[172:7686] [ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed(C01A0041).
2016-09-08 11:13:20.015846 PeerCodeATV[172:7686] [ViceroyTrace] [ICE][ERROR]
2016-09-08 11:13:24.453030 PeerCodeATV[172:7588] [GCKSession] Not in connected state, so giving up for participant [7563528C] on channel [0].
2016-09-08 11:13:24.476176 PeerCodeATV[172:7588] [GCKSession] Not in connected state, so giving up for participant [7563528C] on channel [1].
2016-09-08 11:13:24.498394 PeerCodeATV[172:7588] [ViceroyTrace] [ICE][ERROR] ICEStopConnectivityCheck() found no ICE check with call id (1969443468)
2016-09-08 11:13:24.498840 PeerCodeATV[172:7588] [GCKSession] Not in connected state, so giving up for participant [7563528C] on channel [2].
2016-09-08 11:13:24.522667 PeerCodeATV[172:7588] [ViceroyTrace] [ICE][ERROR] ICEStopConnectivityCheck() found no ICE check with call id (1969443468)
2016-09-08 11:13:24.522954 PeerCodeATV[172:7588] [GCKSession] Not in connected state, so giving up for participant [7563528C] on channel [3].
2016-09-08 11:13:24.545934 PeerCodeATV[172:7588] [ViceroyTrace] [ICE][ERROR] ICEStopConnectivityCheck() found no ICE check with call id (1969443468)
I already tested the code iOS to iOS, it works perfectly across the same iOS, but iPad running iOS 9.2 -> TViOS 10.0 I see these errors?
It works if I reboot the AppleTV with these errors, subsequent connections however fail!!
Resolving the incompatible encryption preference error
I confirm that yonivav was on the right track when encountering the following error during connection of peers:
[MCSession] Peer [DisplayName] has incompatible encryption preference [Required].
However, setting the session encryption preference to .none did not work for me. At https://developer.apple.com/reference/multipeerconnectivity/mcsession/1407000-init it is stated that
On apps linked on or after iOS 9, the encryption is set to required.
On apps linked prior to iOS 9, the encryption is set to optional.
Since I was using one client at iOS 10.1 and another client with a lower iOS version, I initialized the session using
var session = MCSession(peer: ownPeerID,
securityIdentity: nil,
encryptionPreference: .optional)
and the connection works reliably again.
Bluetooth issues
However, I must confirm that the connection is not established using Bluetooth only. The invitation is sent and accepted, the connection state changes to connecting and then to not connected 10 seconds later. Right after changing the state to connecting a
[ViceroyTrace] [ICE][ERROR] ICEStopConnectivityCheck() found no ICE check with call id (108154439)
error is thrown.
If I turn on Wifi and Bluetooth on the the iOS 10.1 device, the Bluetooth only device is discovered, followed by a dozen
[ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed(C01A0041).
errors and a connection state change to not connected.
Update to iOS 10.1.1: still broken
I updated the iPhone from iOS 10.1 to 10.1.1, and the errors still persist, no changes at all.
Update to iOS 10.2.1: seems to work!
After the update from 10.2 (where it was still broken) to 10.2.1, it seems to work again (tested with one device using 10.2.1, the other device was an old iOS 8 device. A colleague tested with 10.2.1 and 10.2 and oddly it worked too)! The connection is established when using Bluetooth only (disabling WiFi). However, at times I still get all the ICE-errors and connection errors in the log, BUT not always. Right now I tried to reproduce them and it runs without warnings. Strange, but the good news is: it seems like Apple fixed the issue!
in my case, instead of:
_mpcSession = [[MCSession alloc] initWithPeer:self.mpcPeerID];
i used:
_mpcSession = [[MCSession alloc] initWithPeer:self.mpcPeerID securityIdentity:nil encryptionPreference:MCEncryptionNone];
Multipeer in iOS 10 is a bag of hurt. I did testing yesterday and it seems like it will only work if wifi is turned on (bluetooth-only is broken).
As an alternative to Multipeer, you can use the dns_sd (Bonjour) approach and build your own. I made a framework (Pod) that does exactly this (it mimicks Multipeer). It is unicast not multicast, but supports roles and bluetooth-only. More info here: https://github.com/xaphod/Bluepeer . I'm afraid I have not tested with tvOS, so it might need some work. Pull-requests welcome ;)
Got an answer from Apple. Seems you can ignore these messages; they are a side effect related to logging changes it seems?
Watch this for details of the logging changes...
(If you’re curious about this change, check out this video from WWDC 2016: https://developer.apple.com/videos/play/wwdc2016/721/ ).
Into my app I developer the feature: stream videos between two iOS device.I cannot stream video to another device,and I got the same log message as you, And I think the problem is as the log said:
[ERROR] ProcessEvent:1199 Send BINDING_REQUEST failed(C01A0041).
[ERROR] ICEStopConnectivityCheck:2688 ICEStopConnectivityCheck() found no ICE check with call id
But after many time tried debug I figure out that I declared the wrong function of the delegate AVCaptureVideoDataOutputSampleBufferDelegate. After corrected the delegate function then I can stream video between two iOS device -> Done task
But I still got the same log as before. So I think if the feature is work then we can ignore the log message, or report it to Apple. I already report this bug to Apple.