RabbitMQ Obj-C client connection status check - objective-c

I'm using rabbitmq/rabbitmq-objc-client. Is there a way how to check if connection was opened successfully? I see there is RMQConnectionDelegate but there are only methods that are called when an error appears. I'm looking for something like
RMQConnection *conn = [[RMQConnection alloc] /*...*/];
if ([conn isOpen]) {
/* ... */
}

You can do this:
[conn start:^{ // code to execute when connection established }];
But note that the client is async and all channel operations are placed onto a queue for execution after the connection is established.
I've added a note to the issue Michael opened: https://github.com/rabbitmq/rabbitmq-objc-client/issues/101

Related

Ratchet PHP server establishes connection, but Kotlin never receives acknowledgement

I have a ratchet server, that I try to access via Websocket. It is similar to the tutorial: logging when there is a new client or when it receives a message. The Ratchet server reports having successfully established a connection while the Kotlin client does not (the connection event in Kotlin is never fired). I am using the socket-io-java module v.2.0.1. The client shows a timeout after the specified timeout time, gets detached at the server and attaches again after a short while, just as it seems to think, the connection did not properly connect (because of a missing connection response?).
The successful connection confirmation gets reported to the client, if the client is a Websocket-Client in the JS-console of Chrome, but not to my Kotlin app. Even an Android emulator running on the same computer doesn´t get a response (So I think the problem is not wi-fi related).
The connection works fine with JS, completing the full handshake, but with an Android app it only reaches the server, but never the client again.
That´s my server code:
<?php
namespace agroSMS\Websockets;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;
class SocketConnection implements MessageComponentInterface
{
protected \SplObjectStorage $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
error_log("New client attached");
}
function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
error_log("Client detached");
}
function onError(ConnectionInterface $conn, \Exception $e)
{
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
function onMessage(ConnectionInterface $from, $msg)
{
error_log("Received message: $msg");
// TODO: Implement onMessage() method.
}
}
And the script that I run in the terminal:
<?php
use Ratchet\Server\IoServer;
use agroSMS\Websockets\SocketConnection;
use Ratchet\WebSocket\WsServer;
use Ratchet\Http\HttpServer;
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new SocketConnection()
)
)
);
$server->run();
What I run in the browser for tests (returns "Connection established" in Chrome, but for some reason not in the Browser "Brave"):
var conn = new WebSocket('ws://<my-ip>:80');
conn.onopen = function(e) {
console.log("Connection established!");
};
conn.onmessage = function(e) {
console.log(e.data);
};
What my Kotlin-code looks like:
try {
val uri = URI.create("ws://<my-ip>:80")
val options = IO.Options.builder()
.setTimeout(60000)
.setTransports(arrayOf(WebSocket.NAME))
.build()
socket = IO.socket(uri, options)
socket.connect()
.on(Socket.EVENT_CONNECT) {
Log.d(TAG, "[INFO] Connection established")
socket.send(jsonObject)
}
.once(Socket.EVENT_CONNECT_ERROR) {
val itString = gson.toJson(it)
Log.d(TAG, itString)
}
}catch(e : Exception) {
Log.e(TAG, e.toString())
}
After a minute the Kotlin code logs a "timeout"-error, detaches from the server, and attaches again.
When I stop the script on the server, it then gives an error: "connection reset, websocket error" (which makes sense, but why doesn´t he get the connection in the first time?)
I also tried to "just" change the protocol to "wss" in the url, in case it might be the problem, even though my server doesn´t even work with SSL, but this just gave me another error:
[{"cause":{"bytesTransferred":0,"detailMessage":"Read timed out","stackTrace":[],"suppressedExceptions":[]},"detailMessage":"websocket error","stackTrace":[],"suppressedExceptions":[]}]
And the connection isn´t even established at the server. So this try has been more like a down-grade.
I went to the github page of socket.io-java-client to find a solution to my problem there and it turned out, the whole problem was, that I misunderstood a very important concept:
That socket.io uses Websockets doesn´t mean it is compatible with Websockets.
So speaking in clear words:
If you use socket.io at client side, you also need to use it at the server side and vice versa. Since socket.io sends a lot of meta data with its packets, a pure Websocket-server will accept their connection establishment, but his acknowledgement coming back will not be accepted by the socket.io client.
You have to go for either full socket.io or full pure Websockets.

PNAccessDeniedCategory for sending the message in pubnub objective c

I am trying to send the message by using pubnub.
But it gives me error for : PNAccessDeniedCategory
I am not finding any solution how to solve this.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
PNConfiguration *configuration = [PNConfiguration configurationWithPublishKey:#"pub-c-..."subscribeKey:#"sub-c-..."];
self.client = [PubNub clientWithConfiguration:configuration];
//Subscription process results arrive to listener which should adopt to PNObjectEventListener protocol and registered using:
[self.client addListener:self];
//Listeners callbacks:
[self.client subscribeToChannels: #[#"test123"] withPresence:YES];
NSLog(#"channel-->%#",self.client.channels);
configuration.uuid = #"test123";
}
- (void)client:(PubNub *)client didReceiveStatus:(PNSubscribeStatus *)status {
if (status.category == PNUnexpectedDisconnectCategory) {
// This event happens when radio / connectivity is lost
}
else if (status.category == PNConnectedCategory) {
// Connect event. You can do stuff like publish, and know you'll get it.
// Or just use the connected event to confirm you are subscribed for
// UI / internal notifications, etc
}
else if (status.category == PNReconnectedCategory) {
// Happens as part of our regular operation. This event happens when
// radio / connectivity is lost, then regained.
}
else if (status.category == PNDecryptionErrorCategory) {
// Handle messsage decryption error. Probably client configured to
// encrypt messages and on live data feed it received plain text.
}else if (status.category == PNAccessDeniedCategory) {
Nslog(#"It gives me this error");
}
}
Please advice. Whether this error is because my account is expired and that is the reason it is not allowing me to access ?
Do i have to create another free account ? or have to create new key ?
Please help.
PubNub Access Manager
You have Access Manager add-on enabled on your keys and so it is just doing its job - denying un-granted access to your keys. You must grant all access to use your keys once this is enabled. When you enable Access Manager a dialog pops up with a warning:
Warning: This action will enable Access Manager on your keyset. If you
are already using this keyset in a production application, please be
aware you will need to grant access to all existing channels in order
to continue use without interruptions.
Here is a snapshot of that dialog:
You can disable Access Manager until you are ready to implement the proper granting logic on your server and you will no longer get this error.
Before you go live with your app, you should implement the necessary granting logic and enable Access Manager to protect your keys from being wrongfully used.

Proxy server persistent connection closing

I'm implementing proxy support for an osx app.
I've created a custom NSURLProtocol and it is working perfectly for a proxy without authentication. Tried with both CCProxy and FreeProxy on a Windows computer in the local network.
However when proxy authentication is on, any request in the first few seconds works perfectly then the connection goes from ESTABLISHED to CLOSE_WAIT in 5 seconds. The proxy shows 0 connections again and, after that in the app any HTTP request will get a 407, even though the proxy-auth header is pre-set.
My code looks like this :
// set the auth fields
CFStringRef usernameRef = (__bridge CFStringRef)appProxyPrefs.proxyUserName;
CFStringRef passwordRef = (__bridge CFStringRef)appProxyPrefs.proxyPassword;
CFHTTPMessageAddAuthentication(copyOfOriginal, nil, usernameRef, passwordRef, kCFHTTPAuthenticationSchemeBasic, YES);
...
// useless
CFHTTPMessageSetHeaderFieldValue(copyOfOriginal, (__bridge CFStringRef)#"Connection", (CFStringRef)(#"Keep-Alive"));
...
// create stream, callback, schedule
// apply proxy settings to the stream
if (isNoProxyOverride)
CFReadStreamSetProperty(myReadStream, kCFStreamPropertyHTTPProxy, (__bridge CFTypeRef)(noProxyDict));
else
CFReadStreamSetProperty(myReadStream, kCFStreamPropertyHTTPProxy, (__bridge CFTypeRef)(manualProxyDict));
...
CFReadStreamSetProperty(myReadStream, kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue);
if (!CFReadStreamOpen(myReadStream)) { // error }
else
{
// check if there is a prev stream
if (currentStream != nil)
{
[currentStream close];
currentStream = nil;
}
currentStream = (__bridge NSInputStream *)(myReadStream);
}
As you see I tried to store the previous conenction in a static inputstream and releasing it only after I open a new one, but seems useless.
Also tried setting the underlying socket to keep-alive in kCFStreamEventOpenCompleted as suggested in NSStream TCP Keep-alive iOS , still without success.
Why does the connection close ? How could I debug it or make it work ?
Is the connection's fault the proxy goes craxy ?
Thanks.
Edit 1:
Edit 2: It seems it has to do with HTTPS... If I change the the server to be plain http instead of https it will work perfectly.

How can I stop a stream when using STTWitter

On iOS (but I think this would be just the same on OSX) I'm using STTWitter.
Among other things, I want to use it to stream the main public timeline.
I've successfully used getStatusesSampleDelimited:stallWarnings:progressBlock:stallWarningBlock:errorBlock: to start streaming tweets.
How can I stop the stream once I've got enough, or want to switch to a different stream (e.g. streaming a search)?
I've tried destroying the STTWitterAPI object - with no effect. I can't see a method on the object to stop streaming, and I've traced the source code through and don't see any way I can stop a stream once it's started.
What have I missed?
The library didn't support cancelling request, so I just added this feature:
id request = [twitter getStatusesSampleDelimited:nil
stallWarnings:nil
progressBlock:^(id response) {
// ...
} stallWarningBlock:nil
errorBlock:^(NSError *error) {
// ...
}];
// ...
[request cancel]; // when you're done with it
After request cancellation, the error block is called once with a cancellation error.
Let me know if it doesn't fulfil your needs.

Close and Abort in custom service channel

My client is using one WCF service which is throwing an exception
(EXCEPTION: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state).
All subsequent calls throwing an same exception.
I read on internet that client need to close()/Abort() channel, this will solve the problem. is it completely right?
Also I am using customer serviceChannel factory provided by service developers. When I create channel it does not show the close and abort methods. So how do I get these close and abort methods when I create custom service channel instance on client side?
Assuming that you have a proxy instance that implements the IClientChannel interface, here is a way (hopefully the right way) to use it.
IClientChannel clientChannel = (IClientChannel)proxy;
bool success = false;
try
{
// do something with the proxy
clientChannel.Close();
success = true;
}
finally
{
if (!success)
{
clientChannel.Abort();
}
}
You may also want to check this. You can wrap your operations using a shared class or function.