diff --git a/lib/db/api.js b/lib/db/api.js index 74401199..9a90c7e9 100644 --- a/lib/db/api.js +++ b/lib/db/api.js @@ -22,6 +22,7 @@ dbapi.saveUserAfterLogin = function(user) { , group: wireutil.makePrivateChannel() , lastLoggedInAt: r.now() , createdAt: r.now() + , forwards: [] })) } return stats @@ -32,6 +33,20 @@ dbapi.loadUser = function(email) { return db.run(r.table('users').get(email)) } +dbapi.addUserForward = function(email, forward) { + return db.run(r.table('users').get(email).update({ + forwards: r.row('forwards').default([]).append(forward) + })) +} + +dbapi.removeUserForward = function(email, devicePort) { + return db.run(r.table('users').get(email).update({ + forwards: r.row('forwards').default([]).filter(function(forward) { + return forward('devicePort').eq(devicePort) + }) + })) +} + dbapi.loadGroup = function(email) { return db.run(r.table('devices').getAll(email, { index: 'owner' diff --git a/lib/roles/app.js b/lib/roles/app.js index d4c25a0f..2c9fa71a 100644 --- a/lib/roles/app.js +++ b/lib/roles/app.js @@ -234,6 +234,10 @@ module.exports = function(options) { io.on('connection', function(socket) { var channels = [] , user = socket.handshake.user + , ip = socket.handshake.headers['x-forwarded-for'] || + socket.handshake.address.address + + socket.emit('socket.ip', ip) function joinChannel(channel) { channels.push(channel) @@ -483,6 +487,48 @@ module.exports = function(options) { ]) }) }) + .on('forward.test', function(channel, responseChannel, data) { + joinChannel(responseChannel) + if (!data.targetHost || data.targetHost === 'localhost') { + data.targetHost = ip + } + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.ForwardTestMessage(data) + ) + ]) + }) + .on('forward.create', function(channel, responseChannel, data) { + if (!data.targetHost || data.targetHost === 'localhost') { + data.targetHost = ip + } + dbapi.addUserForward(user.email, data) + .then(function() { + joinChannel(responseChannel) + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.ForwardCreateMessage(data) + ) + ]) + }) + }) + .on('forward.remove', function(channel, responseChannel, data) { + dbapi.removeUserForward(user.email, data.devicePort) + .then(function() { + joinChannel(responseChannel) + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.ForwardRemoveMessage(data) + ) + ]) + }) + }) }) .finally(function() { // Clean up all listeners and subscriptions diff --git a/lib/roles/device/plugins/forward.js b/lib/roles/device/plugins/forward.js index dc38b713..cba00c89 100644 --- a/lib/roles/device/plugins/forward.js +++ b/lib/roles/device/plugins/forward.js @@ -59,7 +59,7 @@ module.exports = syrup.serial() function createForward(data) { log.info( - 'Reverse forwarding port %d to %s:%d' + 'Reverse port forwarding port %d to %s:%d' , data.devicePort , data.targetHost , data.targetPort @@ -136,6 +136,7 @@ module.exports = syrup.serial() } function removeForward(data) { + log.info('Removing reverse port forwarding on port %d', data.devicePort) var forward = service.forwards[data.devicePort] if (forward) { forward.connection.end() @@ -152,7 +153,7 @@ module.exports = syrup.serial() }) function connectListener() { - resolver.resolve() + resolver.resolve(conn) } function errorListener(err) { @@ -165,7 +166,6 @@ module.exports = syrup.serial() return resolver.promise.finally(function() { conn.removeListener('connect', connectListener) conn.removeListener('error', errorListener) - conn.end() }) } @@ -208,7 +208,7 @@ module.exports = syrup.serial() ]) }) }) - .on(wire.ForwardMessage, function(channel, message) { + .on(wire.ForwardCreateMessage, function(channel, message) { var reply = wireutil.reply(options.serial) createForward(message) .then(function() { @@ -225,13 +225,6 @@ module.exports = syrup.serial() ]) }) }) - .on(wire.ForwardListMessage, function(channel) { - var reply = wireutil.reply(options.serial) - push.send([ - channel - , reply.okay('success', listForwards()) - ]) - }) .on(wire.ForwardRemoveMessage, function(channel, message) { var reply = wireutil.reply(options.serial) removeForward(message) diff --git a/lib/wire/wire.proto b/lib/wire/wire.proto index e580c9d8..29948929 100644 --- a/lib/wire/wire.proto +++ b/lib/wire/wire.proto @@ -36,11 +36,9 @@ enum MessageType { UngroupMessage = 27; UninstallMessage = 34; RotateMessage = 35; - ForwardMessage = 36; - ForwardTestMessage = 37; - ForwardListMessage = 38; - ForwardRemoveMessage = 39; - DeviceForwardsMessage = 40; + ForwardTestMessage = 36; + ForwardCreateMessage = 37; + ForwardRemoveMessage = 38; } message Envelope { @@ -357,25 +355,11 @@ message ForwardTestMessage { required uint32 targetPort = 2; } -message ForwardMessage { +message ForwardCreateMessage { required uint32 devicePort = 1; required string targetHost = 2; required uint32 targetPort = 3; - required bool system = 4; -} - -message ForwardListMessage { -} - -message DeviceForward { - required uint32 devicePort = 1; - required string targetHost = 2; - required uint32 targetPort = 3; - required bool system = 4; -} - -message DeviceForwardsMessage { - repeated DeviceForward forwards = 1; + optional bool system = 4; } message ForwardRemoveMessage { diff --git a/res/app/components/stf/control/control-service.js b/res/app/components/stf/control/control-service.js index c4035955..3f747793 100644 --- a/res/app/components/stf/control/control-service.js +++ b/res/app/components/stf/control/control-service.js @@ -169,6 +169,26 @@ module.exports = function ControlServiceFactory( rotation: rotation }) } + + this.testForward = function(forward) { + var tx = TransactionService.create(target) + socket.emit('forward.test', channel, tx.channel, forward) + return tx + } + + this.createForward = function(forward) { + var tx = TransactionService.create(target) + socket.emit('forward.create', channel, tx.channel, forward) + return tx + } + + this.removeForward = function(forward) { + var tx = TransactionService.create(target) + socket.emit('forward.remove', channel, tx.channel, { + devicePort: forward.devicePort + }) + return tx + } } controlService.create = function(target, channel) { diff --git a/res/app/components/stf/socket/socket-service.js b/res/app/components/stf/socket/socket-service.js index e9d6e914..ecfef492 100644 --- a/res/app/components/stf/socket/socket-service.js +++ b/res/app/components/stf/socket/socket-service.js @@ -1,6 +1,6 @@ var io = require('socket.io') -module.exports = function SocketFactory() { +module.exports = function SocketFactory($rootScope) { var socket = io.connect(null, { reconnect: false }) @@ -26,5 +26,11 @@ module.exports = function SocketFactory() { } } + socket.on('socket.ip', function(ip) { + $rootScope.$apply(function() { + socket.ip = ip + }) + }) + return socket }