1
0
Fork 0
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:
Simo Kinnunen 2017-01-25 17:46:23 +09:00
parent d1602e6b79
commit 5e9aa427e9
3 changed files with 43 additions and 35 deletions

View file

@ -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

View file

@ -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

View file

@ -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)
}) })
}) })