mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 939318 - Have websockets act on network interface changes. r=mcmanus
If there's no outstanding PING, send a new to make sure the connection is still alive and fine.
This commit is contained in:
parent
e6b07731ef
commit
c0691b4a28
@ -24,6 +24,7 @@ BaseWebSocketChannel::BaseWebSocketChannel()
|
||||
, mWasOpened(0)
|
||||
, mClientSetPingInterval(0)
|
||||
, mClientSetPingTimeout(0)
|
||||
, mPingForced(0)
|
||||
, mPingInterval(0)
|
||||
, mPingResponseTimeout(10000)
|
||||
{
|
||||
|
@ -72,6 +72,7 @@ class BaseWebSocketChannel : public nsIWebSocketChannel,
|
||||
uint32_t mWasOpened : 1;
|
||||
uint32_t mClientSetPingInterval : 1;
|
||||
uint32_t mClientSetPingTimeout : 1;
|
||||
uint32_t mPingForced : 1;
|
||||
|
||||
uint32_t mPingInterval; /* milliseconds */
|
||||
uint32_t mPingResponseTimeout; /* milliseconds */
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsNetCID.h"
|
||||
@ -85,7 +87,8 @@ NS_IMPL_ISUPPORTS(WebSocketChannel,
|
||||
nsIProtocolProxyCallback,
|
||||
nsIInterfaceRequestor,
|
||||
nsIChannelEventSink,
|
||||
nsIThreadRetargetableRequest)
|
||||
nsIThreadRetargetableRequest,
|
||||
nsIObserver)
|
||||
|
||||
// We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire.
|
||||
#define SEC_WEBSOCKET_VERSION "13"
|
||||
@ -1046,6 +1049,16 @@ WebSocketChannel::WebSocketChannel() :
|
||||
LOG(("Failed to initiate dashboard service."));
|
||||
|
||||
mSerial = sSerialSeed++;
|
||||
|
||||
// Register for prefs change notifications
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
|
||||
} else {
|
||||
NS_WARNING("failed to get observer service");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WebSocketChannel::~WebSocketChannel()
|
||||
@ -1104,6 +1117,55 @@ WebSocketChannel::~WebSocketChannel()
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannel::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
const char16_t *data)
|
||||
{
|
||||
LOG(("WebSocketChannel::Observe [topic=\"%s\"]\n", topic));
|
||||
|
||||
if (strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0) {
|
||||
nsCString converted = NS_ConvertUTF16toUTF8(data);
|
||||
const char *state = converted.get();
|
||||
|
||||
if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED) == 0) {
|
||||
LOG(("WebSocket: received network CHANGED event"));
|
||||
if (mPingOutstanding) {
|
||||
// If there's an outstanding ping that's expected to get a pong back
|
||||
// we let that do its thing.
|
||||
LOG(("WebSocket: pong already pending"));
|
||||
} else if (!mSocketThread) {
|
||||
// there has not been an asyncopen yet on the object and then we need
|
||||
// no ping.
|
||||
LOG(("WebSocket: early object, no ping needed"));
|
||||
} else {
|
||||
LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"));
|
||||
|
||||
if (mPingForced) {
|
||||
// avoid more than one
|
||||
return NS_OK;
|
||||
}
|
||||
if (!mPingTimer) {
|
||||
// The ping timer is only conditionally running already. If it
|
||||
// wasn't already created do it here.
|
||||
nsresult rv;
|
||||
mPingTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("unable to create ping timer. Carrying on.");
|
||||
} else {
|
||||
mPingTimer->SetTarget(mSocketThread);
|
||||
}
|
||||
}
|
||||
// Trigger the ping timeout asap to fire off a new ping. Wait just
|
||||
// a little bit to better avoid multi-triggers.
|
||||
mPingForced = 1;
|
||||
mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::Shutdown()
|
||||
{
|
||||
@ -2623,11 +2685,16 @@ WebSocketChannel::Notify(nsITimer *timer)
|
||||
}
|
||||
|
||||
if (!mPingOutstanding) {
|
||||
LOG(("nsWebSocketChannel:: Generating Ping\n"));
|
||||
mPingOutstanding = 1;
|
||||
GeneratePing();
|
||||
mPingTimer->InitWithCallback(this, mPingResponseTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
// Allow for the case where a PING was force-sent even though ping
|
||||
// interval isn't enabled. Only issue a new PING if it truly is enabled.
|
||||
if (mPingInterval || mPingForced) {
|
||||
LOG(("nsWebSocketChannel:: Generating Ping\n"));
|
||||
mPingOutstanding = 1;
|
||||
mPingForced = 0;
|
||||
GeneratePing();
|
||||
mPingTimer->InitWithCallback(this, mPingResponseTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else {
|
||||
LOG(("nsWebSocketChannel:: Timed out Ping\n"));
|
||||
mPingTimer = nullptr;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
@ -62,6 +63,7 @@ class WebSocketChannel : public BaseWebSocketChannel,
|
||||
public nsIOutputStreamCallback,
|
||||
public nsITimerCallback,
|
||||
public nsIDNSListener,
|
||||
public nsIObserver,
|
||||
public nsIProtocolProxyCallback,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink
|
||||
@ -78,6 +80,7 @@ public:
|
||||
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
|
||||
//
|
||||
@ -160,8 +163,8 @@ private:
|
||||
|
||||
inline void ResetPingTimer()
|
||||
{
|
||||
mPingOutstanding = 0;
|
||||
if (mPingTimer) {
|
||||
mPingOutstanding = 0;
|
||||
mPingTimer->SetDelay(mPingInterval);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user