1 /*
2  * Copyright 2014 Canonical Ltd.
3  * Authors:
4  *      Roberto Mier
5  *      Tiago Herrmann
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 3.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "sessionmanager.h"
22 
23 Q_LOGGING_CATEGORY(TG_CORE_SESSIONMANAGER, "tg.core.sessionmanager")
24 
SessionManager(Session * session,Settings * settings,CryptoUtils * crypto,QObject * parent)25 SessionManager::SessionManager(Session *session, Settings *settings, CryptoUtils *crypto, QObject *parent) :
26     QObject(parent),
27     mSettings(settings),
28     mCrypto(crypto),
29     mMainSession(session)
30 {
31     connect(mMainSession, SIGNAL(sessionReady(DC*)), this, SIGNAL(mainSessionReady()), Qt::UniqueConnection);
32     connect(mMainSession, SIGNAL(sessionClosed(qint64)), this, SIGNAL(mainSessionClosed()), Qt::UniqueConnection);
33 }
34 
~SessionManager()35 SessionManager::~SessionManager() {
36     if (mMainSession) {
37         mMainSession->close();
38     }
39     Q_FOREACH (Session *session, mFileSessions) {
40         if (session) {
41             session->close();
42         }
43     }
44 }
45 
fileSession(DC * dc)46 Session *SessionManager::fileSession(DC *dc) {
47     Session *session;
48     qint32 &resourcesAtDc = mDcResourceCounts[dc->id()];
49 
50     if (!resourcesAtDc) {
51         session = createFileSession(dc);
52     } else {
53         qint64 sessionId = mDcSessionIds.value(dc->id());
54         session = mFileSessions.value(sessionId);
55     }
56 
57     resourcesAtDc++;
58     qCDebug(TG_CORE_SESSIONMANAGER) << "file session resources at DC" << dc->id() << resourcesAtDc;
59 
60     return session;
61 }
62 
createFileSession(DC * dc)63 Session *SessionManager::createFileSession(DC *dc) {
64     Session *session = createSession(dc);
65     mFileSessions.insert(session->sessionId(), session);
66     mDcSessionIds.insert(dc->id(), session->sessionId());
67     qCDebug(TG_CORE_SESSIONMANAGER) << "created file session at DC" << dc->id();
68     return session;
69 }
70 
createSession(DC * dc)71 Session *SessionManager::createSession(DC *dc) {
72     Session *session = new Session(dc, mSettings, mCrypto, this);
73     connect(session, SIGNAL(sessionReleased(qint64)), SLOT(onSessionReleased(qint64)));
74     connect(session, SIGNAL(sessionClosed(qint64)), SLOT(onSessionClosed(qint64)));
75     connectResponsesSignals(session);
76     return session;
77 }
78 
onSessionReleased(qint64 sessionId)79 void SessionManager::onSessionReleased(qint64 sessionId) {
80     Session *session = mFileSessions.value(sessionId, 0);
81     if (session) {
82         qint32 dcId = session->dc()->id();
83         qint32 &resourcesAtDc = mDcResourceCounts[dcId];
84         resourcesAtDc--;
85 
86         if (!resourcesAtDc) {
87             session->close();
88             mDcSessionIds.remove(dcId);
89             qCDebug(TG_CORE_SESSIONMANAGER) << "closed file session at DC" << dcId;
90             qCDebug(TG_CORE_SESSIONMANAGER) << "remaining" << mFileSessions.count() << "file sessions, counting all DCs";
91         } else {
92             qCDebug(TG_CORE_SESSIONMANAGER) << "released file session at DC" << dcId << ", remaining" << resourcesAtDc << "resources";
93         }
94     } else if (mMainSession && mMainSession->sessionId() == sessionId) {
95         mMainSession->close();
96     }
97 }
98 
onSessionClosed(qint64 sessionId)99 void SessionManager::onSessionClosed(qint64 sessionId) {
100     Session *session = mFileSessions.take(sessionId);
101     if (session) {
102         session->deleteLater();
103     } else if (mMainSession && mMainSession->sessionId() == sessionId) {
104         mMainSession->deleteLater();
105     }
106 }
107 
mainSession()108 Session *SessionManager::mainSession() {
109     return mMainSession;
110 }
111 
setMainSession(Session * session)112 void SessionManager::setMainSession(Session *session) {
113     mMainSession = session;
114 }
115 
changeMainSessionToDc(DC * dc)116 void SessionManager::changeMainSessionToDc(DC *dc) {
117     // remove current main session that is connected to a wrong dc
118     if (mMainSession) {
119         mMainSession->close();
120     }
121     // create session and connect to dc, adding the signal of dc changed
122     mMainSession = createSession(dc);
123     connect(mMainSession, SIGNAL(sessionReady(DC*)), this, SIGNAL(mainSessionDcChanged(DC*)), Qt::UniqueConnection);
124     connect(mMainSession, SIGNAL(sessionReady(DC*)), this, SIGNAL(mainSessionReady()), Qt::UniqueConnection);
125     connect(mMainSession, SIGNAL(sessionClosed(qint64)), this, SIGNAL(mainSessionClosed()), Qt::UniqueConnection);
126     connectUpdatesSignals(mMainSession);
127     mMainSession->connectToServer();
128 }
129 
createMainSessionToDc(DC * dc)130 void SessionManager::createMainSessionToDc(DC *dc) {
131     // create session and connect to dc
132     mMainSession = createSession(dc);
133     connect(mMainSession, SIGNAL(sessionReady(DC*)), this, SIGNAL(mainSessionReady()), Qt::UniqueConnection);
134     connect(mMainSession, SIGNAL(sessionClosed(qint64)), this, SIGNAL(mainSessionClosed()), Qt::UniqueConnection);
135     connectUpdatesSignals(mMainSession);
136     mMainSession->connectToServer();
137 }
138