/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *    Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
 *    Copyright 2014, 2017 (c) Florian Palm
 *    Copyright 2015 (c) Sten Grüner
 *    Copyright 2015 (c) Oleksiy Vasylyev
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
 */

#include "ua_session_manager.h"
#include "ua_server_internal.h"
#include "ua_subscription.h"

UA_StatusCode
UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server) {
    LIST_INIT(&sm->sessions);
    sm->currentSessionCount = 0;
    sm->server = server;
    return UA_STATUSCODE_GOOD;
}

/* Delayed callback to free the session memory */
static void
removeSessionCallback(UA_Server *server, session_list_entry *entry) {
    UA_Session_deleteMembersCleanup(&entry->session, server);
}

static void
removeSession(UA_SessionManager *sm, session_list_entry *sentry) {
    UA_Server *server = sm->server;
    UA_Session *session = &sentry->session;

    /* Remove the Subscriptions */
#ifdef UA_ENABLE_SUBSCRIPTIONS
    UA_Subscription *sub, *tempsub;
    LIST_FOREACH_SAFE(sub, &session->serverSubscriptions, listEntry, tempsub) {
        UA_Session_deleteSubscription(server, session, sub->subscriptionId);
    }

    UA_PublishResponseEntry *entry;
    while((entry = UA_Session_dequeuePublishReq(session))) {
        UA_PublishResponse_deleteMembers(&entry->response);
        UA_free(entry);
    }
#endif

    /* Callback into userland access control */
    if(server->config.accessControl.closeSession)
        server->config.accessControl.closeSession(server, &server->config.accessControl,
                                                  &session->sessionId, session->sessionHandle);

    /* Detach the Session from the SecureChannel */
    UA_Session_detachFromSecureChannel(session);

    /* Deactivate the session */
    sentry->session.activated = false;

    /* Detach the session from the session manager and make the capacity
     * available */
    LIST_REMOVE(sentry, pointers);
    UA_atomic_subUInt32(&sm->currentSessionCount, 1);

    /* Add a delayed callback to remove the session when the currently
     * scheduled jobs have completed */
    sentry->cleanupCallback.callback = (UA_ApplicationCallback)removeSessionCallback;
    sentry->cleanupCallback.application = sm->server;
    sentry->cleanupCallback.data = sentry;
    UA_WorkQueue_enqueueDelayed(&server->workQueue, &sentry->cleanupCallback);
}

void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
    session_list_entry *current, *temp;
    LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
        removeSession(sm, current);
    }
}

void
UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
                                  UA_DateTime nowMonotonic) {
    session_list_entry *sentry, *temp;
    LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
        /* Session has timed out? */
        if(sentry->session.validTill >= nowMonotonic)
            continue;
        UA_LOG_INFO_SESSION(&sm->server->config.logger, &sentry->session,
                            "Session has timed out");
        removeSession(sm, sentry);
    }
}

UA_Session *
UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *token) {
    session_list_entry *current = NULL;
    LIST_FOREACH(current, &sm->sessions, pointers) {
        /* Token does not match */
        if(!UA_NodeId_equal(&current->session.header.authenticationToken, token))
            continue;

        /* Session has timed out */
        if(UA_DateTime_nowMonotonic() > current->session.validTill) {
            UA_LOG_INFO_SESSION(&sm->server->config.logger, &current->session,
                                "Client tries to use a session that has timed out");
            return NULL;
        }

        /* Ok, return */
        return &current->session;
    }

    /* Session not found */
#if UA_LOGLEVEL <= 300
    UA_String nodeIdStr = UA_STRING_NULL;
    UA_NodeId_toString(token, &nodeIdStr);
    UA_LOG_INFO(&sm->server->config.logger, UA_LOGCATEGORY_SESSION,
                "Try to use Session with token %.*s but is not found",
                (int)nodeIdStr.length, nodeIdStr.data);
    UA_String_deleteMembers(&nodeIdStr);
#endif
    return NULL;
}

UA_Session *
UA_SessionManager_getSessionById(UA_SessionManager *sm, const UA_NodeId *sessionId) {
    session_list_entry *current = NULL;
    LIST_FOREACH(current, &sm->sessions, pointers) {
        /* Token does not match */
        if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
            continue;

        /* Session has timed out */
        if(UA_DateTime_nowMonotonic() > current->session.validTill) {
            UA_LOG_INFO_SESSION(&sm->server->config.logger, &current->session,
                                "Client tries to use a session that has timed out");
            return NULL;
        }

        /* Ok, return */
        return &current->session;
    }

    /* Session not found */
    UA_String sessionIdStr = UA_STRING_NULL;
    UA_NodeId_toString(sessionId, &sessionIdStr);
    UA_LOG_INFO(&sm->server->config.logger, UA_LOGCATEGORY_SESSION,
                "Try to use Session with identifier %.*s but is not found",
                (int)sessionIdStr.length, sessionIdStr.data);
    UA_String_deleteMembers(&sessionIdStr);
    return NULL;
}

/* Creates and adds a session. But it is not yet attached to a secure channel. */
UA_StatusCode
UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
                                const UA_CreateSessionRequest *request, UA_Session **session) {
    if(sm->currentSessionCount >= sm->server->config.maxSessions)
        return UA_STATUSCODE_BADTOOMANYSESSIONS;

    session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
    if(!newentry)
        return UA_STATUSCODE_BADOUTOFMEMORY;

    UA_atomic_addUInt32(&sm->currentSessionCount, 1);
    UA_Session_init(&newentry->session);
    newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
    newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());

    if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
       request->requestedSessionTimeout > 0)
        newentry->session.timeout = request->requestedSessionTimeout;
    else
        newentry->session.timeout = sm->server->config.maxSessionTimeout;

    UA_Session_updateLifetime(&newentry->session);
    LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
    *session = &newentry->session;
    return UA_STATUSCODE_GOOD;
}

UA_StatusCode
UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
    session_list_entry *current;
    LIST_FOREACH(current, &sm->sessions, pointers) {
        if(UA_NodeId_equal(&current->session.header.authenticationToken, token))
            break;
    }
    if(!current)
        return UA_STATUSCODE_BADSESSIONIDINVALID;

    removeSession(sm, current);
    return UA_STATUSCODE_GOOD;
}
