mirror of
https://github.com/openstf/stf
synced 2025-10-05 10:39:25 +02:00
The screen websocket now sends ping messages every now and then, so that it won't get caught by nginx's proxy_read_timeout if the screen is off or not moving. Previously, nginx may have decided to kill the connection after a period of no activity.
This commit is contained in:
parent
d1602e6b79
commit
5e9aa427e9
3 changed files with 43 additions and 35 deletions
|
@ -85,6 +85,12 @@ module.exports.builder = function(yargs) {
|
||||||
, type: 'number'
|
, type: 'number'
|
||||||
, default: process.env.SCREEN_JPEG_QUALITY || 80
|
, default: process.env.SCREEN_JPEG_QUALITY || 80
|
||||||
})
|
})
|
||||||
|
.option('screen-ping-interval', {
|
||||||
|
describe: 'The interval at which to send ping messages to keep the ' +
|
||||||
|
'screen WebSocket alive.'
|
||||||
|
, type: 'number'
|
||||||
|
, default: 30000
|
||||||
|
})
|
||||||
.option('screen-port', {
|
.option('screen-port', {
|
||||||
describe: 'Port allocated to the screen WebSocket.'
|
describe: 'Port allocated to the screen WebSocket.'
|
||||||
, type: 'number'
|
, type: 'number'
|
||||||
|
@ -129,9 +135,10 @@ module.exports.handler = function(argv) {
|
||||||
, storageUrl: argv.storageUrl
|
, storageUrl: argv.storageUrl
|
||||||
, adbHost: argv.adbHost
|
, adbHost: argv.adbHost
|
||||||
, adbPort: argv.adbPort
|
, adbPort: argv.adbPort
|
||||||
, screenWsUrlPattern: argv.screenWsUrlPattern
|
|
||||||
, screenJpegQuality: argv.screenJpegQuality
|
, screenJpegQuality: argv.screenJpegQuality
|
||||||
|
, screenPingInterval: argv.screenPingInterval
|
||||||
, screenPort: argv.screenPort
|
, screenPort: argv.screenPort
|
||||||
|
, screenWsUrlPattern: argv.screenWsUrlPattern
|
||||||
, connectUrlPattern: argv.connectUrlPattern
|
, connectUrlPattern: argv.connectUrlPattern
|
||||||
, connectPort: argv.connectPort
|
, connectPort: argv.connectPort
|
||||||
, vncPort: argv.vncPort
|
, vncPort: argv.vncPort
|
||||||
|
|
|
@ -104,6 +104,12 @@ module.exports.builder = function(yargs) {
|
||||||
, type: 'number'
|
, type: 'number'
|
||||||
, default: process.env.SCREEN_JPEG_QUALITY || 80
|
, default: process.env.SCREEN_JPEG_QUALITY || 80
|
||||||
})
|
})
|
||||||
|
.option('screen-ping-interval', {
|
||||||
|
describe: 'The interval at which to send ping messages to keep the ' +
|
||||||
|
'screen WebSocket alive.'
|
||||||
|
, type: 'number'
|
||||||
|
, default: 30000
|
||||||
|
})
|
||||||
.option('screen-ws-url-pattern', {
|
.option('screen-ws-url-pattern', {
|
||||||
describe: 'The URL pattern to use for the screen WebSocket.'
|
describe: 'The URL pattern to use for the screen WebSocket.'
|
||||||
, type: 'string'
|
, type: 'string'
|
||||||
|
@ -163,8 +169,9 @@ module.exports.handler = function(argv) {
|
||||||
, '--storage-url', argv.storageUrl
|
, '--storage-url', argv.storageUrl
|
||||||
, '--adb-host', argv.adbHost
|
, '--adb-host', argv.adbHost
|
||||||
, '--adb-port', argv.adbPort
|
, '--adb-port', argv.adbPort
|
||||||
, '--screen-ws-url-pattern', argv.screenWsUrlPattern
|
|
||||||
, '--screen-jpeg-quality', argv.screenJpegQuality
|
, '--screen-jpeg-quality', argv.screenJpegQuality
|
||||||
|
, '--screen-ping-interval', argv.screenPingInterval
|
||||||
|
, '--screen-ws-url-pattern', argv.screenWsUrlPattern
|
||||||
, '--connect-url-pattern', argv.connectUrlPattern
|
, '--connect-url-pattern', argv.connectUrlPattern
|
||||||
, '--heartbeat-interval', argv.heartbeatInterval
|
, '--heartbeat-interval', argv.heartbeatInterval
|
||||||
, '--boot-complete-timeout', argv.bootCompleteTimeout
|
, '--boot-complete-timeout', argv.bootCompleteTimeout
|
||||||
|
|
|
@ -502,22 +502,18 @@ module.exports = syrup.serial()
|
||||||
|
|
||||||
wss.on('connection', function(ws) {
|
wss.on('connection', function(ws) {
|
||||||
var id = uuid.v4()
|
var id = uuid.v4()
|
||||||
|
var pingTimer
|
||||||
|
|
||||||
function wsStartNotifier() {
|
function send(message, options) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var message = util.format(
|
|
||||||
'start %s'
|
|
||||||
, JSON.stringify(frameProducer.banner)
|
|
||||||
)
|
|
||||||
|
|
||||||
switch (ws.readyState) {
|
switch (ws.readyState) {
|
||||||
case WebSocket.OPENING:
|
case WebSocket.OPENING:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
log.warn('Unable to send banner to OPENING client "%s"', id)
|
log.warn('Unable to send to OPENING client "%s"', id)
|
||||||
break
|
break
|
||||||
case WebSocket.OPEN:
|
case WebSocket.OPEN:
|
||||||
// This is what SHOULD happen.
|
// This is what SHOULD happen.
|
||||||
ws.send(message, function(err) {
|
ws.send(message, options, function(err) {
|
||||||
return err ? reject(err) : resolve()
|
return err ? reject(err) : resolve()
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
@ -527,41 +523,37 @@ module.exports = syrup.serial()
|
||||||
break
|
break
|
||||||
case WebSocket.CLOSED:
|
case WebSocket.CLOSED:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
log.warn('Unable to send banner to CLOSED client "%s"', id)
|
log.warn('Unable to send to CLOSED client "%s"', id)
|
||||||
|
clearInterval(pingTimer)
|
||||||
broadcastSet.remove(id)
|
broadcastSet.remove(id)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wsStartNotifier() {
|
||||||
|
return send(util.format(
|
||||||
|
'start %s'
|
||||||
|
, JSON.stringify(frameProducer.banner)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
function wsPingNotifier() {
|
||||||
|
return send('ping')
|
||||||
|
}
|
||||||
|
|
||||||
function wsFrameNotifier(frame) {
|
function wsFrameNotifier(frame) {
|
||||||
return new Promise(function(resolve, reject) {
|
return send(frame, {
|
||||||
switch (ws.readyState) {
|
|
||||||
case WebSocket.OPENING:
|
|
||||||
// This should never happen.
|
|
||||||
return reject(new Error(util.format(
|
|
||||||
'Unable to send frame to OPENING client "%s"', id)))
|
|
||||||
case WebSocket.OPEN:
|
|
||||||
// This is what SHOULD happen.
|
|
||||||
ws.send(frame, {
|
|
||||||
binary: true
|
binary: true
|
||||||
}, function(err) {
|
|
||||||
return err ? reject(err) : resolve()
|
|
||||||
})
|
|
||||||
return
|
|
||||||
case WebSocket.CLOSING:
|
|
||||||
// Ok, a 'close' event should remove the client from the set
|
|
||||||
// soon.
|
|
||||||
return
|
|
||||||
case WebSocket.CLOSED:
|
|
||||||
// This should never happen.
|
|
||||||
broadcastSet.remove(id)
|
|
||||||
return reject(new Error(util.format(
|
|
||||||
'Unable to send frame to CLOSED client "%s"', id)))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sending a ping message every now and then makes sure that
|
||||||
|
// reverse proxies like nginx don't time out the connection [1].
|
||||||
|
//
|
||||||
|
// [1] http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
|
||||||
|
pingTimer = setInterval(wsPingNotifier, options.screenPingInterval)
|
||||||
|
|
||||||
ws.on('message', function(data) {
|
ws.on('message', function(data) {
|
||||||
var match = /^(on|off|(size) ([0-9]+)x([0-9]+))$/.exec(data)
|
var match = /^(on|off|(size) ([0-9]+)x([0-9]+))$/.exec(data)
|
||||||
if (match) {
|
if (match) {
|
||||||
|
@ -574,6 +566,7 @@ module.exports = syrup.serial()
|
||||||
break
|
break
|
||||||
case 'off':
|
case 'off':
|
||||||
broadcastSet.remove(id)
|
broadcastSet.remove(id)
|
||||||
|
// Keep pinging even when the screen is off.
|
||||||
break
|
break
|
||||||
case 'size':
|
case 'size':
|
||||||
frameProducer.updateProjection(
|
frameProducer.updateProjection(
|
||||||
|
@ -584,6 +577,7 @@ module.exports = syrup.serial()
|
||||||
})
|
})
|
||||||
|
|
||||||
ws.on('close', function() {
|
ws.on('close', function() {
|
||||||
|
clearInterval(pingTimer)
|
||||||
broadcastSet.remove(id)
|
broadcastSet.remove(id)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue