| 1 | #include "stdafx.h" |
|---|
| 2 | #include "strEx.h" |
|---|
| 3 | #include "NSClientSocket.h" |
|---|
| 4 | |
|---|
| 5 | /** |
|---|
| 6 | * Default c-tor |
|---|
| 7 | */ |
|---|
| 8 | NSClientSocket::NSClientSocket(): hStopEvent(NULL) { |
|---|
| 9 | } |
|---|
| 10 | |
|---|
| 11 | NSClientSocket::~NSClientSocket() { |
|---|
| 12 | } |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | /** |
|---|
| 16 | * Thread procedure for the socket listener |
|---|
| 17 | * @param lpParameter Potential argument to the thread proc. |
|---|
| 18 | * @return thread exit status |
|---|
| 19 | * @todo This needs to be reworked, possibly completely redone ? |
|---|
| 20 | */ |
|---|
| 21 | DWORD NSClientSocket::threadProc(LPVOID lpParameter) |
|---|
| 22 | { |
|---|
| 23 | hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
|---|
| 24 | if (!hStopEvent) { |
|---|
| 25 | NSC_LOG_ERROR_STD("Create StopEvent failed: " + strEx::itos(GetLastError())); |
|---|
| 26 | return 0; |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | WSADATA wsaData; |
|---|
| 30 | sockaddr_in local; |
|---|
| 31 | int wsaret=WSAStartup(0x101,&wsaData); |
|---|
| 32 | if(wsaret!=0) { |
|---|
| 33 | NSC_LOG_ERROR_STD("WSA Startup failed: " + strEx::itos(wsaret)); |
|---|
| 34 | return 0; |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | local.sin_family=AF_INET; |
|---|
| 38 | local.sin_addr.s_addr=INADDR_ANY; |
|---|
| 39 | local.sin_port=htons(static_cast<u_short>(NSCModuleHelper::getSettingsInt("NSClient", "port", DEFAULT_TCP_PORT))); |
|---|
| 40 | server=socket(AF_INET,SOCK_STREAM,0); |
|---|
| 41 | if(server==INVALID_SOCKET) { |
|---|
| 42 | WSACleanup(); |
|---|
| 43 | NSC_LOG_ERROR_STD("Could not create listening socket: " + strEx::itos(GetLastError())); |
|---|
| 44 | return 0; |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | if(bind(server,(sockaddr*)&local,sizeof(local))!=0) { |
|---|
| 48 | closesocket(server); |
|---|
| 49 | WSACleanup(); |
|---|
| 50 | NSC_LOG_ERROR_STD("Could not bind socket: " + strEx::itos(GetLastError())); |
|---|
| 51 | return 0; |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | if(listen(server,10)!=0) { |
|---|
| 55 | closesocket(server); |
|---|
| 56 | WSACleanup(); |
|---|
| 57 | NSC_LOG_ERROR_STD("Could not open socket: " + strEx::itos(GetLastError())); |
|---|
| 58 | return 0; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | SOCKET client; |
|---|
| 62 | sockaddr_in from; |
|---|
| 63 | int fromlen=sizeof(from); |
|---|
| 64 | while (!(WaitForSingleObject(hStopEvent, 100) == WAIT_OBJECT_0)) { |
|---|
| 65 | client=accept(server, (struct sockaddr*)&from,&fromlen); |
|---|
| 66 | if (client != INVALID_SOCKET) |
|---|
| 67 | onAccept(client); |
|---|
| 68 | } |
|---|
| 69 | closesocket(server); |
|---|
| 70 | WSACleanup(); |
|---|
| 71 | NSC_DEBUG_MSG("Socket closed!"); |
|---|
| 72 | return 0; |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | #define RECV_BUFFER_LEN 1024 |
|---|
| 76 | |
|---|
| 77 | std::string NSClientSocket::parseRequest(char *buffer) { |
|---|
| 78 | charEx::token pwd = charEx::getToken(buffer, '&'); |
|---|
| 79 | if ( (pwd.first.empty()) || (pwd.first != NSCModuleHelper::getSettingsString("generic", "password", "")) ) |
|---|
| 80 | return "ERRRO: Invalid password."; |
|---|
| 81 | if (pwd.second == NULL) |
|---|
| 82 | return "ERRRO: No command specified."; |
|---|
| 83 | charEx::token cmd = charEx::getToken(pwd.second, '&'); |
|---|
| 84 | NSC_DEBUG_MSG("Command: " + cmd.first); |
|---|
| 85 | std::string message, perf; |
|---|
| 86 | NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd.first.c_str(), cmd.second, '&', message, perf); |
|---|
| 87 | int c = atoi(cmd.first.c_str()); |
|---|
| 88 | switch (c) { |
|---|
| 89 | case REQ_CLIENTVERSION: |
|---|
| 90 | case REQ_UPTIME: |
|---|
| 91 | case REQ_CPULOAD: |
|---|
| 92 | case REQ_USEDDISKSPACE: |
|---|
| 93 | return message; |
|---|
| 94 | case REQ_SERVICESTATE: |
|---|
| 95 | case REQ_PROCSTATE: |
|---|
| 96 | return NSCHelper::translateReturn(ret) + "&" + message; |
|---|
| 97 | default: |
|---|
| 98 | return NSCHelper::translateReturn(ret) + "&" + message + "|" + perf; |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | void NSClientSocket::onAccept(SOCKET client) { |
|---|
| 103 | char *buff = new char[RECV_BUFFER_LEN+1]; |
|---|
| 104 | int n=recv(client,buff,RECV_BUFFER_LEN,0); |
|---|
| 105 | if ((n!=SOCKET_ERROR )&&(n > 0)&&(n < RECV_BUFFER_LEN)) { |
|---|
| 106 | buff[n] = '\0'; |
|---|
| 107 | NSC_DEBUG_MSG("Incoming data: "); |
|---|
| 108 | NSC_DEBUG_MSG(buff); |
|---|
| 109 | std::string response = parseRequest(buff); |
|---|
| 110 | NSC_DEBUG_MSG("Outgoing data: " + response); |
|---|
| 111 | send(client, response.c_str(), static_cast<int>(response.length()), 0); |
|---|
| 112 | } else { |
|---|
| 113 | std::string str = "ERROR: Unknown socket error"; |
|---|
| 114 | send(client,str.c_str(),static_cast<int>(str.length()),0); |
|---|
| 115 | } |
|---|
| 116 | delete [] buff; |
|---|
| 117 | closesocket(client); |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | |
|---|
| 121 | /** |
|---|
| 122 | * Exit thread callback proc. |
|---|
| 123 | * This is called by the thread manager when the thread should initiate a shutdown procedure. |
|---|
| 124 | * The thread manager is responsible for waiting for the actual termination of the thread. |
|---|
| 125 | */ |
|---|
| 126 | void NSClientSocket::exitThread(void) { |
|---|
| 127 | NSC_DEBUG_MSG("Requesting shutdown!"); |
|---|
| 128 | if (!SetEvent(hStopEvent)) { |
|---|
| 129 | NSC_LOG_ERROR_STD("SetStopEvent failed"); |
|---|
| 130 | } |
|---|
| 131 | } |
|---|