Open aijorgenson opened 6 months ago
Hi!
I'm having the same problem with pusher:ping.
Same here
I have the same problem with a Laravel Reverb server. If I understand the Pusher docs correctly, the pusher:ping
event is used when the WebSocket implementation doesn't support ping/pong messages? So maybe the problem is that the server isn't detecting that the client supports native websocket pings.
For those (and maybe even more applicable to @sundayz) who are still having this issue, you'll need to modify the library yourself. You'll need to add a pusher event for pong
when the server sends pings to inactive connections (this library in this case).
Add some constants for the messages:
namespace PusherClient
{
class Constants
{
public const string PUSHER_MESSAGE_PREFIX = "pusher";
public const string ERROR = "pusher:error";
public const string PING = "pusher:ping"; // <-- add here
public const string PONG = "pusher:pong"; // <-- add here
public const string CONNECTION_ESTABLISHED = "pusher:connection_established";
public const string CHANNEL_SUBSCRIBE = "pusher:subscribe";
public const string CHANNEL_UNSUBSCRIBE = "pusher:unsubscribe";
public const string CHANNEL_SUBSCRIPTION_SUCCEEDED = "pusher_internal:subscription_succeeded";
public const string CHANNEL_SUBSCRIPTION_ERROR = "pusher_internal:subscription_error";
public const string CHANNEL_MEMBER_ADDED = "pusher_internal:member_added";
public const string CHANNEL_MEMBER_REMOVED = "pusher_internal:member_removed";
public const string INSECURE_SCHEMA = "ws://";
public const string SECURE_SCHEMA = "wss://";
public const string PRIVATE_CHANNEL = "private-";
public const string PRESENCE_CHANNEL = "presence-";
}
}
Add the pong event:
using Newtonsoft.Json;
namespace PusherClient
{
internal class PusherPongEvent
{
public PusherPongEvent()
{
}
[JsonProperty(PropertyName = "event")] public string Event { get; } = Constants.PONG;
}
}
Remove the auto-ping configuration:
public async Task ConnectAsync()
{
_connectionSemaphore = new SemaphoreSlim(0, 1);
try
{
_currentError = null;
if (_pusher.PusherOptions.TraceLogger != null)
_pusher.PusherOptions.TraceLogger.TraceInformation($"Connecting to: {_url}");
ChangeState(ConnectionState.Connecting);
_websocket = new WebSocket(_url); // <-- removed unnecessary configuration
await Task.Run(() =>
{
_websocket.Error += WebsocketConnectionError;
_websocket.MessageReceived += WebsocketMessageReceived;
_websocket.Open();
}).ConfigureAwait(false);
var timeoutPeriod = _pusher.PusherOptions.InnerClientTimeout;
if (!await _connectionSemaphore.WaitAsync(timeoutPeriod).ConfigureAwait(false))
throw new OperationTimeoutException(timeoutPeriod, Constants.CONNECTION_ESTABLISHED);
if (_currentError != null) throw _currentError;
}
finally
{
if (_websocket != null) _websocket.Error -= WebsocketConnectionError;
_connectionSemaphore.Dispose();
_connectionSemaphore = null;
}
}
If you leave the default constructor configuration, it doesn't seem to hurt anything, but probably still a good idea to remove it.
Then add the handling of the ping
message, which sends the pong
message back:
private void ProcessPusherEvent(string eventName, string rawJson, Dictionary<string, object> message)
{
var messageData = string.Empty;
if (message.ContainsKey("data")) messageData = (string)message["data"];
switch (eventName)
{
case Constants.CONNECTION_ESTABLISHED:
ParseConnectionEstablished(messageData);
break;
case Constants.PUSHER_SIGNIN_SUCCESS:
case Constants.PUSHER_WATCHLIST_EVENT:
EmitEvent(eventName, rawJson, message);
break;
case Constants.PING: // <-- added
SendAsync(DefaultSerializer.Default.Serialize(new PusherPongEvent())).ConfigureAwait(false);
break;
}
}
I just ended up creating a channel that anyone authenticated can subscribe to, and then I send periodic "ping" events to keep the connection alive.
I could be wrong, but I would speculate that Pusher is intentionally not accommodating to projects that choose to self host their own websocket server.
I could be wrong, but I would speculate that Pusher is intentionally not accommodating to projects that choose to self host their own websocket server.
Agreed
For those using the Laravel Reverb websocket server, a fix has been merged on the server side: https://github.com/laravel/reverb/issues/224
I have a web app using the pusher library that regularly sends
pusher:ping
requests ( https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/#ping-and-pong-messages ); however, my .NET app is not sending these requests when subscribed to the same channels.Per the Pusher documentation, it seems like this should be an automatic thing. I'm not able to find anything in the documentation for this package around it.
I have tried both 2.1 and the beta build of the package.