RDK Documentation (Open Sourced RDK Components)
Server.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 /**
22 * @defgroup trm
23 * @{
24 * @defgroup qtapp
25 * @{
26 **/
27 
28 
29 #include <errno.h>
30 #include <stdio.h>
31 
32 #include <QObject>
33 #include <QTcpSocket>
34 #include <QDataStream>
35 #include <QString>
36 #include <QCoreApplication>
37 #include <QThread>
38 
39 #include "trm/TRM.h"
40 #include "trm/JsonDecoder.h"
41 #include "Connection.h"
42 #include "trm/Header.h"
43 #include "ServerMessageProcessor.h"
44 #include "Manager.h"
45 #include "Util.h"
46 
47 #include "Server.h"
48 
49 extern void printThread(const char *func);
50 
51 using namespace TRM;
52 
53 Server::~Server(void)
54 {
55  //@TODO: traverse and delete connections.
56  tcpServer->close();
57  delete tcpServer;
58 }
59 
60 void Server::close(void)
61 {
62  tcpServer->close();
63 }
64 
65 const Connection & Server::getConnection(uint32_t clientId) const
66 {
67  QMap<uint32_t, const Connection *>::const_iterator it = connectionClientMap.find(clientId);
68  if (it == connectionClientMap.end()) {
70  }
71 
72  Assert(it.key() == clientId);
73  return *(it.value());
74 }
75 
76 void Server::getConnections(std::list<const Connection *> &connectionlist) const
77 {
78  QList<const Connection *>::const_iterator it = connections.begin();
79  while (it != connections.end()) {
80  connectionlist.push_back(*it);
81  it++;
82  }
83 }
84 
85 void Server::onDisconnected(Connection *connection)
86 {
87  /* connection is disconnected */
88  Log() << "Disconnected connection index is " << (void *)connection << std::endl;
89  /* remove all clients */
90  QMap<uint32_t, const Connection *>::iterator it = connectionClientMap.begin();
91  while(it != connectionClientMap.end()) {
92  if (it.value() == connection) {
93  Log() << "Removing client =======================" << (void *)it.key() << std::endl;
94 
95  /* relase all reservations that belongs to this client */
96  TunerReservation::TokenList tokensForClient;
97  Manager::getInstance().getReservationTokens(tokensForClient, it.key());
98 
99  TunerReservation::TokenList::const_iterator itt = tokensForClient.begin();
100  while(itt != tokensForClient.end()) {
101  Log() << "Releasing Token " << (*itt).c_str() << " for client " << (void *)it.key() << std::endl;
102  Manager::getInstance().releaseReservation(*itt);
103  itt++;
104  }
105 
106  it = connectionClientMap.erase(it);
107  }
108  else {
109  it++;
110  }
111  }
112 
113  if (connections.removeOne(connection)) {
114  connection->deleteLater();
115  }
116  else {
117  Assert(0);
118  }
119 }
120 
121 void Server::onMessageReceived(const Connection &fromConnection)
122 {
123  try {
124  const QByteArray & incomingMessageArray = fromConnection.recvMessage();
125  std::vector<uint8_t> headerBytes (incomingMessageArray.constData(), incomingMessageArray.constData() + Header::kHeaderLength);
126  std::vector<uint8_t> payloadBytes (incomingMessageArray.constData() + Header::kHeaderLength, incomingMessageArray.constData() + incomingMessageArray.size());
127 
128 
129  /* Send Data for Diag if TRM Manager is connected */
130  uint32_t clientId = Connection::kTRMMgrClientId;
131  QMap<uint32_t, const Connection *>::iterator itCon = connectionClientMap.find(clientId);
132  if(itCon != connectionClientMap.end() && Connection::isTRMDiagClient((itCon).key())) {
133  Log() << "Server::Sent Recvd Message to TRMDiagClient" << std::endl;
134  std::vector<uint8_t> out(incomingMessageArray.begin(),incomingMessageArray.end());
135  (itCon.value())->onHasMessageToSend(out);
136  }
137 
138  delete &incomingMessageArray;
139  Header header;
140  header.deserialize(headerBytes);
141 
142  QMap<uint32_t, const Connection *>::iterator it = connectionClientMap.find(header.getClientId());
143 
144  if (it == connectionClientMap.end()) {
145  connectionClientMap[header.getClientId()] = &fromConnection;
146  }
147 
148  it = connectionClientMap.find(header.getClientId());
149  if (it != connectionClientMap.end()) {
150  if (payloadBytes.size() > 0) {
151  ServerMessageProcessor myP(&fromConnection, header.getClientId());
152  JsonDecoder jdecoder(myP);
153  jdecoder.decode(payloadBytes);
154  }
155  else {
156  /* Reset clientId's connection on empty message. Client has disconnected */
157  /* connection is disconnected */
158  Log() << "Disconnected clientId is " << header.getClientId() << std::endl;
159  /* remove all clients */
160  QMap<uint32_t, const Connection *>::iterator it = connectionClientMap.begin();
161  while(it != connectionClientMap.end()) {
162  if (it.value() == &fromConnection) {
163  if (it.key() == header.getClientId()) {
164 
165  /* relase all reservations that belongs to this client */
166  TunerReservation::TokenList tokensForClient;
167  Manager::getInstance().getReservationTokens(tokensForClient, it.key());
168 
169  TunerReservation::TokenList::const_iterator itt = tokensForClient.begin();
170  while(itt != tokensForClient.end()) {
171  Log() << "Releasing Token " << (*itt).c_str() << "for client " << (void *)it.key() << std::endl;
172  Manager::getInstance().releaseReservation(*itt);
173  itt++;
174  }
175 
176  //remove connection from the map
177  Log() << "Removing client " << (void *)it.key() << std::endl;
178  connectionClientMap.erase(it);
179  break;
180  }
181  }
182  it++;
183  }
184  }
185  }
186  else {
187  //Discard the invalid message.
188  Assert(0);
189  }
190  }
191  catch(...) {
192  /* No data. Do nothing */
193  }
194 }
195 
196 void Server::onHasMessageToSend(const std::vector<uint8_t> out)
197 {
198  /* Send Data for Diag if TRM Manager is connected */
199  uint32_t clientId = Connection::kTRMMgrClientId;
200  QMap<uint32_t, const Connection *>::iterator it = connectionClientMap.find(clientId);
201 
202  if(it != connectionClientMap.end() && Connection::isTRMDiagClient((it).key())) {
203  std::vector<uint8_t> payloadBytes (out.data() + Header::kHeaderLength, out.data() + out.size());
204  Log() << "Server::Sent Has Message to TRMDiagClient " << std::endl;
205  (it.value())->onHasMessageToSend(out);
206  }
207 }
208 
209 void Server::onNewConnection(void)
210 {
211  qDebug() << ("New connection detected\r\n");
212  QTcpSocket *clientSocket = tcpServer->nextPendingConnection();
213  Connection *connection = new Connection(*clientSocket);
214  connections.append(connection);
215  QObject::connect(connection, SIGNAL(disconnected(Connection *)), this, SLOT(onDisconnected(Connection *)), Qt::QueuedConnection);
216  QObject::connect(connection, SIGNAL(messageReceived(const Connection &)), this, SLOT(onMessageReceived(const Connection &)));
217  /* Make it Sniff independent to listen for TRM SRV response */
218  QObject::connect(connection, SIGNAL(hasMessageToSend(const std::vector<uint8_t>)), this, SLOT(onHasMessageToSend(const std::vector<uint8_t>)));
219 }
220 
221 void Server::onReservationUpdated(void)
222 {
223  Log() << "Manager::onReservationUpdate " << std::endl;
224 
225  if (1) {
226  QMap<uint32_t, const Connection *>::iterator it = connectionClientMap.begin();
227 
228  while (it != connectionClientMap.end()) {
229  Log() << "Server::send NotifyTunerReservationUpdate to client " << std::hex << (it).key() << std::endl;
230  if (Connection::isXREClient((it).key()) || Connection::isSDVAgentClient((it).key()) || Connection::isTestClient((it).key()))
231  {
232  try {
233  std::vector<uint8_t> out;
234  SerializeMessage(Manager::getInstance().getTunerStatesUpdate(), (it).key(), out);
235  (it.value())->sendAsync(out);
236  }
237  catch (...) {
238  std::cout << "Exception caught during getTunerStatesUpdate " << std::endl;
239  SafeAssert(0);
240  }
241  }
242  it++;
243  }
244  }
245 }
246 
247 Server::Server(const QHostAddress &address, quint16 port)
248 {
249  //QThreadPool::globalInstance()->setMaxThreadCount(10);
250  tcpServer = new QTcpServer();
251  tcpServer->listen(address, port);
252  QObject::connect(tcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
253  //QObject::connect(&Manager::getInstance(), SIGNAL(reservationUpdated(void)), this, SLOT(onReservationUpdated(void)));
254  QObject::connect(&Manager::getInstance(), SIGNAL(reservationUpdated(void)), this, SLOT(onReservationUpdated(void)), Qt::QueuedConnection);
255 }
256 
257 
258 /** @} */
259 /** @} */
ServerMessageProcessor
#include <QObject>
Definition: ServerMessageProcessor.h:48
TRM::ConnectionNotFoundException
Definition: TRM.h:62
Header.h
TRM::Header
Definition: Header.h:94
TRM::JsonDecoder
Definition: JsonDecoder.h:73
TRM::Connection
Definition: Connection.h:43