Use variable to store active sessions
Keep session data in process for as long as the TCP connectoin is open. Use redis if connection closes before the session is over.
This commit is contained in:
1 parent
e6aab4229d
commit
41fb97adef
3 files changed
+68
-37
No files matched your search
+43
-14
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
util = require 'util'
|
util = require 'util'
|
||||||
zlib = require 'zlib'
|
zlib = require 'zlib'
|
||||||
|
crypto = require 'crypto'
|
||||||
mongodb = require 'mongodb'
|
mongodb = require 'mongodb'
|
||||||
|
|
||||||
config = require './config'
|
config = require './config'
|
||||||
@@ -94,16 +95,13 @@ inform = (currentRequest, cwmpRequest) ->
|
|||||||
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
||||||
})
|
})
|
||||||
|
|
||||||
session.save(currentRequest.sessionData, (err, sessionId) ->
|
|
||||||
throw err if err
|
|
||||||
if !!cookiesPath = config.get('COOKIES_PATH', currentRequest.sessionData.deviceId)
|
if !!cookiesPath = config.get('COOKIES_PATH', currentRequest.sessionData.deviceId)
|
||||||
res.headers['Set-Cookie'] = "session=#{sessionId}; Path=#{cookiesPath}"
|
res.headers['Set-Cookie'] = "session=#{currentRequest.sessionData.sessionId}; Path=#{cookiesPath}"
|
||||||
else
|
else
|
||||||
res.headers['Set-Cookie'] = "session=#{sessionId}"
|
res.headers['Set-Cookie'] = "session=#{currentRequest.sessionData.sessionId}"
|
||||||
|
|
||||||
writeResponse(currentRequest, res)
|
writeResponse(currentRequest, res)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
testSchedule = (schedule, timestamp) ->
|
testSchedule = (schedule, timestamp) ->
|
||||||
@@ -268,6 +266,8 @@ sendRpcRequest = (currentRequest, id, rpcRequest) ->
|
|||||||
if not rpcRequest?
|
if not rpcRequest?
|
||||||
session.end(currentRequest.sessionData, (err, isNew) ->
|
session.end(currentRequest.sessionData, (err, isNew) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
|
|
||||||
|
delete currentSessions.get(currentRequest.httpRequest.connection)[currentRequest.sessionData.sessionId]
|
||||||
if isNew
|
if isNew
|
||||||
util.log("#{currentRequest.sessionData.deviceId}: New device registered")
|
util.log("#{currentRequest.sessionData.deviceId}: New device registered")
|
||||||
|
|
||||||
@@ -293,10 +293,7 @@ sendRpcRequest = (currentRequest, id, rpcRequest) ->
|
|||||||
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
||||||
})
|
})
|
||||||
|
|
||||||
session.save(currentRequest.sessionData, (err) ->
|
|
||||||
throw err if err
|
|
||||||
writeResponse(currentRequest, res)
|
writeResponse(currentRequest, res)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
getSession = (httpRequest, callback) ->
|
getSession = (httpRequest, callback) ->
|
||||||
@@ -307,9 +304,38 @@ getSession = (httpRequest, callback) ->
|
|||||||
|
|
||||||
return callback() if not sessionId?
|
return callback() if not sessionId?
|
||||||
|
|
||||||
session.load(sessionId, (err, sessionData) ->
|
sessionData = currentSessions.get(httpRequest.connection)?[sessionId]
|
||||||
|
|
||||||
|
if sessionData?
|
||||||
|
return callback(null, sessionData)
|
||||||
|
|
||||||
|
setTimeout(() ->
|
||||||
|
db.redisClient.eval('local v=redis.call("get",KEYS[1]);redis.call("del",KEYS[1]);return v;', 1, "session_#{sessionId}", (err, sessionDataString) ->
|
||||||
|
return callback(err) if err or not sessionDataString
|
||||||
|
session.deserialize(sessionDataString, (err, sessionData) ->
|
||||||
|
return callback(err) if err
|
||||||
|
currentSessions.get(httpRequest.connection)[sessionId] = sessionData
|
||||||
|
callback(null, sessionData)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
, 100
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
currentSessions = new WeakMap()
|
||||||
|
|
||||||
|
# When socket closes, store active sessions in redis
|
||||||
|
onConnection = (socket) ->
|
||||||
|
currentSessions.set(socket, {})
|
||||||
|
socket.on('close', () ->
|
||||||
|
sessions = currentSessions.get(socket)
|
||||||
|
for sessionId, sessionData of sessions
|
||||||
|
session.serialize(sessionData, (err, sessionDataString) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
return callback(sessionId, sessionData)
|
db.redisClient.setex("session_#{sessionId}", sessionData.timeout, sessionDataString, (err) ->
|
||||||
|
throw err if err
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -352,7 +378,8 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
|
|
||||||
stream.on('end', () ->
|
stream.on('end', () ->
|
||||||
cwmpRequest = null
|
cwmpRequest = null
|
||||||
getSession(httpRequest, f = (sessionId, sessionData) ->
|
getSession(httpRequest, f = (err, sessionData) ->
|
||||||
|
throw err if err
|
||||||
cwmpRequest ?= soap.request(httpRequest, sessionData?.cwmpVersion)
|
cwmpRequest ?= soap.request(httpRequest, sessionData?.cwmpVersion)
|
||||||
if not sessionData?
|
if not sessionData?
|
||||||
if cwmpRequest.methodRequest?.type isnt 'Inform'
|
if cwmpRequest.methodRequest?.type isnt 'Inform'
|
||||||
@@ -364,6 +391,10 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
return session.init(deviceId, cwmpRequest.cwmpVersion, cwmpRequest.sessionTimeout ? config.get('SESSION_TIMEOUT', deviceId), (err, sessionData) ->
|
return session.init(deviceId, cwmpRequest.cwmpVersion, cwmpRequest.sessionTimeout ? config.get('SESSION_TIMEOUT', deviceId), (err, sessionData) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
|
|
||||||
|
sessionData.sessionId = crypto.randomBytes(8).toString('hex')
|
||||||
|
|
||||||
|
currentSessions.get(httpRequest.connection)[sessionData.sessionId] = sessionData
|
||||||
|
|
||||||
httpRequest.connection.setTimeout(sessionData.timeout * 1000)
|
httpRequest.connection.setTimeout(sessionData.timeout * 1000)
|
||||||
|
|
||||||
db.getDueTasksAndFaults(deviceId, sessionData.timestamp, (err, dueTasks, faults) ->
|
db.getDueTasksAndFaults(deviceId, sessionData.timestamp, (err, dueTasks, faults) ->
|
||||||
@@ -401,10 +432,7 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
methodResponse : {type : 'GetRPCMethodsResponse', methodList : ['Inform', 'GetRPCMethods', 'TransferComplete', 'RequestDownload']},
|
methodResponse : {type : 'GetRPCMethodsResponse', methodList : ['Inform', 'GetRPCMethods', 'TransferComplete', 'RequestDownload']},
|
||||||
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
cwmpVersion : currentRequest.sessionData.cwmpVersion
|
||||||
})
|
})
|
||||||
session.save(currentRequest.sessionData, (err) ->
|
|
||||||
throw err if err
|
|
||||||
writeResponse(currentRequest, res)
|
writeResponse(currentRequest, res)
|
||||||
)
|
|
||||||
else if cwmpRequest.methodRequest.type is 'TransferComplete'
|
else if cwmpRequest.methodRequest.type is 'TransferComplete'
|
||||||
throw new Error('ACS method not supported')
|
throw new Error('ACS method not supported')
|
||||||
else if cwmpRequest.methodResponse?
|
else if cwmpRequest.methodResponse?
|
||||||
@@ -469,3 +497,4 @@ listener = (httpRequest, httpResponse) ->
|
|||||||
|
|
||||||
|
|
||||||
exports.listener = listener
|
exports.listener = listener
|
||||||
|
exports.onConnection = onConnection
|
||||||
@@ -30,6 +30,7 @@ port = config.get("#{service.toUpperCase()}_PORT")
|
|||||||
useHttps = config.get("#{service.toUpperCase()}_SSL")
|
useHttps = config.get("#{service.toUpperCase()}_SSL")
|
||||||
|
|
||||||
serviceListener = require("./#{service}").listener
|
serviceListener = require("./#{service}").listener
|
||||||
|
onConnection = require("./#{service}").onConnection
|
||||||
|
|
||||||
server = null
|
server = null
|
||||||
|
|
||||||
@@ -77,6 +78,9 @@ if useHttps
|
|||||||
else
|
else
|
||||||
server = require('http').createServer(listener)
|
server = require('http').createServer(listener)
|
||||||
|
|
||||||
|
if onConnection?
|
||||||
|
server.on('connection', onConnection)
|
||||||
|
|
||||||
db.connect((err) ->
|
db.connect((err) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
server.listen(port, networkInterface)
|
server.listen(port, networkInterface)
|
||||||
|
|||||||
+21
-23
@@ -15,8 +15,6 @@
|
|||||||
# along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
# along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
###
|
###
|
||||||
|
|
||||||
crypto = require 'crypto'
|
|
||||||
|
|
||||||
config = require './config'
|
config = require './config'
|
||||||
common = require './common'
|
common = require './common'
|
||||||
db = require './db'
|
db = require './db'
|
||||||
@@ -1090,10 +1088,7 @@ rpcFault = (sessionData, id, faultResponse, callback) ->
|
|||||||
return callback(null, faultResponse)
|
return callback(null, faultResponse)
|
||||||
|
|
||||||
|
|
||||||
load = (id, callback) ->
|
deserialize = (sessionDataString, callback) ->
|
||||||
db.redisClient.get("session_#{id}", (err, sessionDataString) ->
|
|
||||||
return callback(err) if err or not sessionDataString?
|
|
||||||
|
|
||||||
cache.getProvisionsAndVirtualParameters((err, hash, provisions, virtualParameters) ->
|
cache.getProvisionsAndVirtualParameters((err, hash, provisions, virtualParameters) ->
|
||||||
return callback(err) if err
|
return callback(err) if err
|
||||||
|
|
||||||
@@ -1129,15 +1124,9 @@ load = (id, callback) ->
|
|||||||
|
|
||||||
return callback(null, sessionData)
|
return callback(null, sessionData)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
save = (sessionData, callback) ->
|
serialize = (sessionData, callback) ->
|
||||||
delete sessionData.syncState
|
|
||||||
delete sessionData.toLoad
|
|
||||||
delete sessionData.cache
|
|
||||||
|
|
||||||
sessionData.id ?= crypto.randomBytes(8).toString('hex')
|
|
||||||
deviceData = []
|
deviceData = []
|
||||||
keys = ['exist', 'object', 'writable', 'value']
|
keys = ['exist', 'object', 'writable', 'value']
|
||||||
iter = sessionData.deviceData.paths.find([], 99)
|
iter = sessionData.deviceData.paths.find([], 99)
|
||||||
@@ -1154,15 +1143,24 @@ save = (sessionData, callback) ->
|
|||||||
|
|
||||||
deviceData.push(e)
|
deviceData.push(e)
|
||||||
|
|
||||||
oldDeviceData = sessionData.deviceData.deviceData
|
oldDeviceData = sessionData.deviceData
|
||||||
sessionData.deviceData = deviceData
|
oldSyncState = sessionData.syncState
|
||||||
sessionDataString = JSON.stringify(sessionData)
|
oldToLoad = sessionData.toLoad
|
||||||
sessionData.deviceData = oldDeviceData
|
oldCache = sessionData.cache
|
||||||
|
|
||||||
db.redisClient.setex("session_#{sessionData.id}", sessionData.timeout, sessionDataString, (err) ->
|
sessionData.deviceData = deviceData
|
||||||
return callback(err, sessionData.id)
|
delete sessionData.syncState
|
||||||
)
|
delete sessionData.toLoad
|
||||||
return
|
delete sessionData.cache
|
||||||
|
|
||||||
|
sessionDataString = JSON.stringify(sessionData)
|
||||||
|
|
||||||
|
sessionData.deviceData = oldDeviceData
|
||||||
|
sessionData.syncState = oldSyncState
|
||||||
|
sessionData.toLoad = sessionData.toLoad
|
||||||
|
sessionData.cache = sessionData.cache
|
||||||
|
|
||||||
|
return callback(null, sessionDataString)
|
||||||
|
|
||||||
|
|
||||||
end = (sessionData, callback) ->
|
end = (sessionData, callback) ->
|
||||||
@@ -1182,5 +1180,5 @@ exports.rpcRequest = rpcRequest
|
|||||||
exports.rpcResponse = rpcResponse
|
exports.rpcResponse = rpcResponse
|
||||||
exports.rpcFault = rpcFault
|
exports.rpcFault = rpcFault
|
||||||
exports.end = end
|
exports.end = end
|
||||||
exports.save = save
|
exports.serialize = serialize
|
||||||
exports.load = load
|
exports.deserialize = deserialize
|
||||||
Reference in new issue
Block a user