2 * Copyright (C) 2012, BMW AG
4 * This file is part of GENIVI Project AudioManager.
6 * Contributions are licensed to the GENIVI Alliance under one or more
7 * Contribution License Agreements.
10 * This Source Code Form is subject to the terms of the
11 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
12 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
16 * \author Frank Herchet, frank.fh.herchet@bmw.de BMW 2012
18 * \file CAmTelnetServer.cpp
19 * For further information see http://www.genivi.org/.
23 #include "CAmTelnetServer.h"
25 #include <sys/socket.h>
26 #include <arpa/inet.h>
27 #include <sys/ioctl.h>
39 #include "CAmDatabaseHandlerInterface.h"
40 #include "CAmRoutingSender.h"
41 #include "CAmTelnetMenuHelper.h"
42 #include "shared/CAmDltWrapper.h"
47 CAmTelnetServer* CAmTelnetServer::mpInstance = NULL;
49 #define PRINT_BOOL(var) var ? output+="true\t\t" : output+="false\t\t";
51 CAmTelnetServer::CAmTelnetServer(CAmSocketHandler *iSocketHandler, CAmCommandSender *iCommandSender, CAmCommandReceiver *iCommandReceiver, CAmRoutingSender *iRoutingSender, CAmRoutingReceiver *iRoutingReceiver, CAmControlSender *iControlSender, CAmControlReceiver *iControlReceiver, CAmDatabaseHandlerInterface *iDatabasehandler, CAmRouter *iRouter, unsigned int servPort, unsigned int maxConnections) :
52 telnetConnectFiredCB(this, &CAmTelnetServer::connectSocket), //
53 telnetReceiveFiredCB(this, &CAmTelnetServer::receiveData), //
54 telnetDispatchCB(this, &CAmTelnetServer::dispatchData), //
55 telnetCheckCB(this, &CAmTelnetServer::check), //
56 mpSocketHandler(iSocketHandler), //
57 mpCommandSender(iCommandSender), //
58 mpCommandReceiver(iCommandReceiver), //
59 mpRoutingSender(iRoutingSender), //
60 mpRoutingReceiver(iRoutingReceiver), //
61 mpControlSender(iControlSender), //
62 mpControlReceiver(iControlReceiver), //
63 mpDatabasehandler(iDatabasehandler), //
67 mListConnections(), //
69 mServerPort(servPort), //
70 mMaxConnections(maxConnections), //
71 mTelnetMenuHelper(iSocketHandler, iCommandSender, iCommandReceiver, iRoutingSender, iRoutingReceiver, iControlSender, iControlReceiver, iDatabasehandler, iRouter, this)
73 assert(mpSocketHandler!=NULL);
74 assert(mpCommandReceiver!=NULL);
75 assert(mpCommandSender!=NULL);
76 assert(mpControlSender!=NULL);
77 assert(mpControlReceiver!=NULL);
78 assert(mpRoutingSender!=NULL);
79 assert(mpRoutingReceiver!=NULL);
80 assert(mpDatabasehandler!=NULL);
81 assert(mpRouter!=NULL);
83 assert(mMaxConnections!=0);
86 //mTelnetMenuHelper.setTelnetServer(this);
89 struct sockaddr_in servAddr;
91 //setup the port Listener
92 mConnectFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
93 assert (mConnectFD>0);
94 assert(setsockopt(mConnectFD, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))==0);
95 memset(&servAddr, 0, sizeof(servAddr));
96 servAddr.sin_family = AF_INET;
97 servAddr.sin_addr.s_addr = INADDR_ANY;
98 servAddr.sin_port = htons(servPort);
99 if(bind(mConnectFD, (struct sockaddr *) &servAddr, sizeof(servAddr))!=0)
101 logError("CAmTelnetServer::CAmTelnetServer bind failed, error",errno);
102 throw std::runtime_error("CAmTelnetServer::CAmTelnetServer bind failed");
105 if (listen(mConnectFD, mMaxConnections) < 0)
107 logError("TelnetServer::TelnetServerk cannot listen ", errno);
108 throw std::runtime_error("CAmTelnetServer::CAmTelnetServer bind failed");
111 logInfo("TelnetServer::TelnetServer started listening on port", mServerPort);
114 ioctl(mConnectFD, FIONBIO, (char *) &a);
115 setsockopt(mConnectFD, SOL_SOCKET, SO_KEEPALIVE, (char *) &a, sizeof(a));
119 mpSocketHandler->addFDPoll(mConnectFD, events, NULL, &telnetConnectFiredCB, NULL, NULL, NULL, mConnecthandle);
122 CAmTelnetServer::~CAmTelnetServer()
126 void CAmTelnetServer::connectSocket(const pollfd pfd, const sh_pollHandle_t handle, void *userData)
130 //first, accept the connection, create a new filedescriptor
131 struct sockaddr answer;
132 socklen_t len = sizeof(answer);
133 connection_s connection;
134 connection.handle = 0;
135 connection.filedescriptor = accept(pfd.fd, (struct sockaddr*) &answer, &len);
137 assert(connection.filedescriptor>0);
140 mTelnetMenuHelper.newSocketConnection(connection.filedescriptor);
142 //set the correct event:
146 //aded the filedescriptor to the sockethandler and register the callbacks for receiving the data
147 mpSocketHandler->addFDPoll(connection.filedescriptor, event, NULL, &telnetReceiveFiredCB, &telnetCheckCB, &telnetDispatchCB, NULL, connection.handle);
148 mListConnections.push_back(connection);
151 void CAmTelnetServer::disconnectClient(int filedescriptor)
153 std::vector<connection_s>::iterator iter = mListConnections.begin();
154 while (iter != mListConnections.end())
156 if (filedescriptor == iter->filedescriptor)
158 if (E_OK == mpSocketHandler->removeFDPoll(iter->handle))
160 mListConnections.erase(iter);
161 close(filedescriptor);
165 // TODO: Handle error
174 void CAmTelnetServer::receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void *userData)
180 //read until buffer is full or no more data is there
181 int read = recv(pollfd.fd, buffer, 100, 0);
184 //read the message and store it in a queue - its a telnet connection so data will be sent on enter !
185 std::string msg = std::string(buffer, read);
186 mListMessages.push(msg);
190 bool CAmTelnetServer::dispatchData(const sh_pollHandle_t handle, void *userData)
193 std::vector<connection_s>::iterator iterator = mListConnections.begin();
194 for (; iterator != mListConnections.end(); ++iterator)
196 if (iterator->handle == handle)
199 if (iterator==mListConnections.end())
201 logError("CAmTelnetServer::dispatchData could not find handle !");
206 std::queue<std::string> MsgQueue;
207 if (!mListMessages.empty())
209 sliceCommand(mListMessages.front(), command, MsgQueue);
211 mTelnetMenuHelper.enterCmdQueue(MsgQueue, iterator->filedescriptor);
215 logError("CAmTelnetServer::dispatchData Message queue was empty!");
218 // must return false to stop endless polling
222 bool CAmTelnetServer::check(const sh_pollHandle_t handle, void *userData)
226 if (mListMessages.size() != 0)
231 void am::CAmTelnetServer::sliceCommand(const std::string & string, std::string & command, std::queue<std::string> & MsgQueue)
234 std::stringstream stream(string);
235 std::istream_iterator<std::string> begin(stream);
236 std::istream_iterator<std::string> end;
238 bool endOfStream = false;