#include "stdafx.h" #include "strEx.h" #include "NSParser.h" #include "NSClient++.h" #include "TCPSocketResponder.h" #include "Settings.h" extern NSClient mainClient; /** * Default c-tor */ TCPSocketResponder::TCPSocketResponder() : running_(false) { } /** * Return true if the socket is "running". * @return true if the socket is spoused to be running */ bool TCPSocketResponder::isRunning(void) { MutexLock mutex(mutexHandler); if (!mutex.hasMutex()) { LOG_ERROR_STD("Failed to get Mutex: " + strEx::itos(mutex.getWaitResult())); return false; } return running_; } /** * Set the running flag to "stop" (will prevent the socket to start waiting again) */ void TCPSocketResponder::stopRunning(void) { MutexLock mutex(mutexHandler); if (!mutex.hasMutex()) { LOG_ERROR_STD("Failed to get Mutex!" + strEx::itos(mutex.getWaitResult())); return; } running_ = false; } /** * Set the running flag to "start" (will make the socket wait again) */ void TCPSocketResponder::startRunning(void) { MutexLock mutex(mutexHandler); if (!mutex.hasMutex()) { LOG_ERROR_STD("Failed to get Mutex!" + strEx::itos(mutex.getWaitResult())); return; } running_ = true; } /** * Parse a command string into command, password and arguments. Then the command will be executed bu the core. * @param request A request string to parse * @return The result (if any) of the executed command. */ std::string TCPSocketResponder::parseCommand(char* request) { std::list args = charEx::split(request, '&'); if (args.size() < 2) { return "Insufficient arguments!"; } std::string password = args.front(); args.pop_front(); std::string command = args.front(); args.pop_front(); return mainClient.execute(password, command, args); } /** * Thread procedure for the socket listener * @param lpParameter Potential argument to the thread proc. * @return thread exit status * @todo This needs to be reworked, possibly completely redone ? */ DWORD TCPSocketResponder::threadProc(LPVOID lpParameter) { startRunning(); WSADATA wsaData; sockaddr_in local; int wsaret=WSAStartup(0x101,&wsaData); if(wsaret!=0) { LOG_ERROR_STD("WSA Startup failed: " + strEx::itos(wsaret)); return 0; } local.sin_family=AF_INET; local.sin_addr.s_addr=INADDR_ANY; local.sin_port=htons(static_cast(Settings::getInstance()->getInt("generic", "port", DEFAULT_TCP_PORT))); server=socket(AF_INET,SOCK_STREAM,0); if(server==INVALID_SOCKET) { LOG_ERROR_STD("Could not create listening socket: " + strEx::itos(GetLastError())); return 0; } if(bind(server,(sockaddr*)&local,sizeof(local))!=0) { LOG_ERROR_STD("Could not bind socket: " + strEx::itos(GetLastError())); return 0; } if(listen(server,10)!=0) { LOG_ERROR_STD("Could not open socket: " + strEx::itos(GetLastError())); return 0; } SOCKET client; sockaddr_in from; int fromlen=sizeof(from); while(isRunning()) { client=accept(server, (struct sockaddr*)&from,&fromlen); if (client != INVALID_SOCKET) { char *buff = new char[RECV_BUFFER_LEN+1]; int n=recv(client,buff,RECV_BUFFER_LEN,0); if ((n!=SOCKET_ERROR )&&(n > 0)&&(n < RECV_BUFFER_LEN)) { buff[n] = '\0'; LOG_DEBUG("Incoming data: "); LOG_DEBUG(buff); std::string ret = parseCommand(buff); LOG_DEBUG("Outgoing data: "); LOG_DEBUG(ret.c_str()); send(client, ret.c_str(), ret.length(), 0); } else { std::string str = "ERROR: Unknown socket error"; send(client,str.c_str(),str.length(),0); } delete [] buff; closesocket(client); } } closesocket(server); WSACleanup(); LOG_DEBUG("Socket closed!"); return 0; } /** * Exit thread callback proc. * This is called by the thread manager when the thread should initiate a shutdown procedure. * The thread manager is responsible for waiting for the actual termination of the thread. */ void TCPSocketResponder::exitThread(void) { LOG_DEBUG("Requesting shutdown!"); stopRunning(); closesocket(server); }