29 #include <arpa/inet.h>
30 #include <sys/socket.h>
40 #include <QCoreApplication>
43 #include <QStringList>
46 #include <QNetworkInterface>
47 #include <QNetworkAddressEntry>
50 #include <QtWebSockets/QWebSocketServer>
51 #include <QtWebSockets/QWebSocket>
54 #include "qt_websocketproxy.h"
55 #include "safec_lib.h"
57 static const int header_length = 16;
62 NOTIFICATION = 0x1400,
66 static const char *trm_ip = 0;
67 static const char *trm_port = 0;
69 static int trm_socket_fd = -1;
70 static pthread_mutex_t conn_mutex;
71 typedef std::map<void *, int> connection_ct_t;
72 static connection_ct_t connections;
73 const char* localHost=
"lo";
74 const char* devicePropertiesPath =
"/etc/device.properties";
75 const char* mocaIntTagName =
"MOCA_INTERFACE";
81 pthread_mutex_lock(&conn_mutex);
84 pthread_mutex_unlock(&conn_mutex);
88 #define AutoLock() AutoLock_ a()
90 static int get_connection_id(
void)
92 static int connection_id = 0;
95 connid = connection_id;
99 static int conn_to_id(
void *conn)
101 int connection_id = -1;
103 connection_ct_t::iterator it = connections.find(conn);
104 if (it != connections.end()) {
105 connection_id = it->second;
109 printf(
"Cannot find connection\r\n");
113 return connection_id;
116 static void * id_to_conn(
int connection_id)
120 if (connection_id >= 0) {
121 connection_ct_t::iterator it;
122 for (it = connections.begin(); it != connections.end(); it++) {
124 printf(
"id_to_conn::Trying Connection Pair [%d] with [%p]\r\n", it->second, it->first);
126 if (connection_id == (it->second)) {
136 static void add_connection(
void *conn)
138 int connection_id = get_connection_id();
140 printf(
"Adding Connection [%d] with [%p]\r\n", connection_id, conn);
141 connections.insert(connections.end(), std::pair<void*, int>(conn, connection_id));
144 static void remove_connection(
void *conn)
147 printf(
"Removing Connection [%p]\r\n", conn);
149 connection_ct_t::iterator it = connections.find(conn);
150 if (it != connections.end()) {
151 connections.erase(it);
155 static void remove_all_connections(
void)
157 connection_ct_t::iterator it;
158 for (it = connections.begin(); it != connections.end(); it++) {
160 printf(
"Removing Connection [%p]\r\n", it->first);
161 extern int mg_websocket_close(
void * conn);
162 mg_websocket_close(it->first);
166 extern int mg_websocket_close_all_ssl();
167 mg_websocket_close_all_ssl();
172 static int connect_to_trm(
const char *ip,
int port,
int *trm_fd)
175 int socket_error = 0;
176 struct sockaddr_in trm_address = {0};
177 trm_address.sin_family = AF_INET;
178 trm_address.sin_addr.s_addr = inet_addr(ip);
179 trm_address.sin_port = htons(port);
181 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
183 fprintf(_TRMPRX_OUT_,
"Connecting to remote\r\n");
185 static int retry_count = 10;
186 socket_error = connect(socket_fd, (
struct sockaddr *) &trm_address,
sizeof(
struct sockaddr_in));
187 if (socket_error == ECONNREFUSED && retry_count > 0) {
189 fprintf(_TRMPRX_OUT_,
"TRM Server is not started...retry to connect\r\n");
198 if (socket_error == 0) {
200 fprintf(_TRMPRX_OUT_,
"Connected\r\n");
202 int current_flags = fcntl(socket_fd, F_GETFL, 0);
203 current_flags &= (~O_NONBLOCK);
204 fcntl(socket_fd, F_SETFL, current_flags);
215 int begin_request_callback(
void *)
219 printf(
"[%s]\r\n", __func__);
223 void end_request_callback(
void *,
int )
227 printf(
"[%s]\r\n", __func__);
230 int websocket_connect_callback(
void *)
234 printf(
"[%s]\r\n", __func__);
238 int websocket_disconnect_callback(
void *conn)
241 QWebSocket *wssocket = (QWebSocket *)conn;
245 printf(
"[%s] - removing connection from TRM\r\n", __func__);
246 extern int websocket_data_callback(
void *conn,
int flags,
char *trm_data,
size_t trm_data_length);
252 char eventString[256];
253 QString ipString = wssocket->peerAddress().toString();
254 qint64 currentEpoch = QDateTime(QDate::currentDate(), QTime::currentTime()).toMSecsSinceEpoch();
255 std::string reason =
"TRM_Event_Disconnect";
257 int length = sprintf_s(eventString,
sizeof(eventString),
"{ \"notifyClientConnectionEvent\": { \"eventName\" :\"%s\",\"clientIP\" : \"%s\",\"timeStamp\": %lld } }",reason.c_str(),ipString.toUtf8().data(),currentEpoch);
261 websocket_data_callback(conn, 0, &eventString[0],length);
269 websocket_data_callback(conn, 8, NULL, 0);
273 printf(
"[%s]\r\n", __func__);
274 remove_connection(conn);
278 void websocket_ready_callback(
void *conn)
282 printf(
"[%s]\r\n", __func__);
283 add_connection(conn);
286 int log_message_callback(
void *,
const char *message)
290 printf(
"[wsLog][%s]\r\n", message);
294 int websocket_data_callback_with_clientId(
int connection_id,
int flags,
char *trm_data,
size_t trm_data_length){
295 int keep_connection = 1;
296 printf(
"[%s][%.*s]\r\n", __func__, trm_data_length, trm_data);
298 size_t payload_length = trm_data_length;
299 if (connection_id >= 0 && trm_data_length >= 0) {
301 unsigned char *buf = (
unsigned char *) malloc(payload_length + header_length);
309 buf[idx++] = (UNKNOWN & 0xFF000000) >> 24;
310 buf[idx++] = (UNKNOWN & 0x00FF0000) >> 16;
311 buf[idx++] = (UNKNOWN & 0x0000FF00) >> 8;
312 buf[idx++] = (UNKNOWN & 0x000000FF) >> 0;
314 buf[idx++] = (connection_id & 0xFF000000) >> 24;
315 buf[idx++] = (connection_id & 0x00FF0000) >> 16;
316 buf[idx++] = (connection_id & 0x0000FF00) >> 8;
317 buf[idx++] = (connection_id & 0x000000FF) >> 0;
319 buf[idx++] = (payload_length & 0xFF000000) >> 24;
320 buf[idx++] = (payload_length & 0x00FF0000) >> 16;
321 buf[idx++] = (payload_length & 0x0000FF00) >> 8;
322 buf[idx++] = (payload_length & 0x000000FF) >> 0;
325 if (payload_length > 0) {
326 errno_t safec_rc = memcpy_s((
void *)&buf[idx], payload_length, trm_data, payload_length);
330 for (idx = 0; idx < (header_length); idx++) {
331 fprintf(_TRMPRX_OUT_,
"%02x", buf[idx]);
333 for (; idx < (payload_length + header_length); idx++) {
334 fprintf(_TRMPRX_OUT_,
"%c", buf[idx]);
337 fprintf(_TRMPRX_OUT_,
"]At %d\r\n==============================================================\r\n", idx);
340 int write_trm_count = write(trm_socket_fd, buf, payload_length + header_length);
342 fprintf(_TRMPRX_OUT_,
"Send to TRM %d vs expected %d\r\n", write_trm_count, payload_length + header_length);
347 printf(
"invalid connection %d\r\n", connection_id);
350 return keep_connection;
352 int websocket_data_callback(
void *conn,
int flags,
char *trm_data,
size_t trm_data_length)
356 int connection_id = -1;
358 connection_id = conn_to_id(conn);
360 return websocket_data_callback_with_clientId (connection_id, flags, trm_data, trm_data_length);
363 static void * TRM_response_listener(
void * )
367 while (trm_socket_fd < 0) {
370 remove_all_connections();
374 fprintf(_TRMPRX_OUT_,
"Retry Connecting to TRM\r\n");
375 connect_to_trm(trm_ip, atoi(trm_port), &trm_socket_fd);
379 size_t payload_length = 0;
380 int connection_id = -1;
382 char *buf = (
char *) malloc(header_length);
384 int read_trm_count = read(trm_socket_fd, buf, header_length);
386 fprintf(_TRMPRX_OUT_,
"Read Header from TRM %d vs expected %d\r\n", read_trm_count, header_length);
388 fprintf(_TRMPRX_OUT_,
"\r\n=====RESPONSE HEADER===================================================\r\n[");
390 for (idx = 0; idx < (header_length); idx++) {
391 fprintf(_TRMPRX_OUT_,
"%02x", buf[idx]);
394 fprintf(_TRMPRX_OUT_,
"\r\n==============================================================\r\n[");
396 if (read_trm_count == header_length) {
397 int magic_cookie_offset = 0;
398 int connection_id_offset = 8;
399 int payload_length_offset = 12;
401 if ((buf[magic_cookie_offset+0] !=
'T') ||
402 (buf[magic_cookie_offset+1] !=
'R') ||
403 (buf[magic_cookie_offset+2] !=
'M') ||
404 (buf[magic_cookie_offset+3] !=
'S')) {
406 fprintf(_TRMPRX_OUT_,
"Mismatching Magic! Discard\r\n");
409 connection_id =((((
unsigned char)(buf[connection_id_offset+0])) << 24) |
410 (((
unsigned char)(buf[connection_id_offset+1])) << 16) |
411 (((
unsigned char)(buf[connection_id_offset+2])) << 8 ) |
412 (((
unsigned char)(buf[connection_id_offset+3])) << 0 ));
416 payload_length =((((
unsigned char)(buf[payload_length_offset+0])) << 24) |
417 (((
unsigned char)(buf[payload_length_offset+1])) << 16) |
418 (((
unsigned char)(buf[payload_length_offset+2])) << 8 ) |
419 (((
unsigned char)(buf[payload_length_offset+3])) << 0 ));
423 fprintf(_TRMPRX_OUT_,
" TRM Response payloads is %d and header %d\r\n", payload_length, header_length);
424 fflush(_TRMPRX_OUT_);
426 buf = (
char *) malloc(payload_length);
427 read_trm_count = read(trm_socket_fd, buf, payload_length);
429 fprintf(_TRMPRX_OUT_,
"Read Payload from TRM %d vs expected %d\r\n", read_trm_count, payload_length);
431 if (read_trm_count == (
int)payload_length) {
434 printf(
"Content-type: text/html\r\n"
435 "Content-length:%d\r\n"
436 "Content-type:application/json\r\n"
440 void *conn = id_to_conn(connection_id);
444 extern int mg_websocket_write(
void * conn,
const char *data,
size_t data_len);
445 size_t write_ws_count = mg_websocket_write(conn, buf, read_trm_count);
446 fprintf(stderr,
"Send to WS %d vs expected %d\r\n", write_ws_count, payload_length + 4);
447 if (write_ws_count == 0 ) {
448 remove_connection(conn);
452 extern int mg_websocket_write(
void * conn,
const char *data,
size_t data_len);
453 int write_ws_count = mg_websocket_write(conn, buf, read_trm_count);
454 write_ws_count = write_ws_count;
459 extern int mg_websocket_write_ssl(
int clientId,
char *data,
int data_len);
460 int write_ws_count = mg_websocket_write_ssl (connection_id, buf, read_trm_count);
461 write_ws_count = write_ws_count;
465 if (read_trm_count <= 0) {
467 fprintf(_TRMPRX_OUT_,
"Remote connection is closed...Retry\r\n");
468 close(trm_socket_fd);
477 fprintf(_TRMPRX_OUT_,
"Cannot find connection from id %d\r\n", connection_id);
482 if (read_trm_count <= 0) {
484 fprintf(_TRMPRX_OUT_,
"Remote connection is closed...Retry\r\n");
485 close(trm_socket_fd);
494 static QString getIPFromInterface(QString interfaceName,
bool isLoopback)
497 QNetworkInterface netInterface = QNetworkInterface::interfaceFromName(interfaceName);
498 if(netInterface.isValid())
500 foreach (
const QNetworkAddressEntry &address, netInterface.addressEntries())
502 if(address.ip().protocol() != QAbstractSocket::IPv4Protocol)
506 if (address.ip().isLoopback() == isLoopback)
508 interfaceIp = address.ip().toString();
515 qDebug()<<
"TRM Invalid interface";
520 int main(
int argc,
char *argv[])
523 QCoreApplication app(argc, argv);
524 QStringList args = app.arguments();
526 char *debugConfigFile = NULL;
528 QRegExp optionDebugFile(
"--debugconfig");
529 QRegExp optionBound(
"-bound");
530 QStringList boundIPs;
532 for (
int i = 1; i < args.size(); ++i) {
533 if (optionBound.indexIn(args.at(i)) != -1 ) {
534 boundIPs << args.at(i+1);
536 qDebug() <<
"bound to " << boundIPs;
538 else if (optionDebugFile.indexIn(args.at(i)) != -1 ) {
539 debugConfigFile = argv[i+1];
541 qDebug() <<
"rdklogger debug file is " << debugConfigFile;
546 printf(
"TRM-WS-Proxy <server ip addr> <port> --debugconfi <config file> [optionals]\r\n");
547 printf(
"optionals: -bound <bound ip addr1> <bound ip addr2>...\r\n");
553 RDK_LOG(RDK_LOG_DEBUG,
"LOG.RDK.TRM",
"This is a test line");
557 #define TRM_WS_PROXY_LISTENING_PORT 9989
560 pthread_mutex_init(&conn_mutex, NULL);
562 printf(
"Starting TRM-WS-Proxy\r\n");
569 connect_to_trm(trm_ip, atoi(trm_port), &trm_socket_fd);
570 pthread_t trm_rsp_listener_thread;
571 pthread_create(&trm_rsp_listener_thread, NULL, TRM_response_listener, (
void *)trm_socket_fd);
573 if (boundIPs.empty())
577 QString localHostIp = getIPFromInterface(localHost,
true);
578 if(!localHostIp.isNull())
580 boundIPs.append(localHostIp);
584 QSettings deviceSetting( devicePropertiesPath, QSettings::IniFormat );
585 QString mocaInterfaceName = deviceSetting.value( mocaIntTagName).toString();
586 if(!mocaInterfaceName.isNull())
592 QString mocaIp = getIPFromInterface(mocaInterfaceName,
false);
595 boundIPs.append(mocaIp);
596 qDebug()<<
"TRM Moca ip present ...continue ";
601 qDebug()<<
"TRM Moca ip not present retry after 5 sleep";
605 }
while( retryCount);
609 qDebug()<<
"TRM Moca interface name not found";
615 int app_return = app.exec();
618 pthread_mutex_destroy(&conn_mutex);
621 printf(
"TRM WS-Daemon Exit!!\r\n");