[22] | 1 | /** |
---|
| 2 | * @file ConnectionController.cpp |
---|
| 3 | * @author Tomas Urban |
---|
| 4 | * @version 0.5 |
---|
| 5 | * @date 23/07/2009 |
---|
| 6 | */ |
---|
| 7 | #include "ConnectionController.h" |
---|
| 8 | #include "PCAPLiveCapture.h" |
---|
| 9 | #include "Logger/Logger.h" |
---|
| 10 | #include "CaptureFactory.h" |
---|
| 11 | #include "Messages/TrafficCaptureMessageFactory.h" |
---|
| 12 | #include "Messages/CommonTrafficCaptureMessages.h" |
---|
| 13 | #include <boost/filesystem.hpp> |
---|
| 14 | |
---|
| 15 | ConnectionController::ConnectionController(SOCKET_TYPE hSocket) : |
---|
| 16 | m_hSocket(hSocket), |
---|
| 17 | m_pCapture(0) |
---|
| 18 | { |
---|
| 19 | } |
---|
| 20 | |
---|
| 21 | ConnectionController::~ConnectionController(void) |
---|
| 22 | { |
---|
| 23 | CaptureFactory::Instance().DisposeCaptureInstance(m_pCapture); |
---|
| 24 | } |
---|
| 25 | |
---|
| 26 | void ConnectionController::SendSimpleReply(CommonReplyMessage & reply, bool bRes) |
---|
| 27 | { |
---|
| 28 | reply.SetResult(bRes); |
---|
| 29 | send(m_hSocket, reply.GetEncodedMessage(), reply.GetEncodedDataLength(), 0); |
---|
| 30 | } |
---|
| 31 | |
---|
| 32 | void ConnectionController::ProcessMessage(const struct TMessageHeader & header, const char * pPayload, |
---|
| 33 | TcpipDispatch &td) |
---|
| 34 | { |
---|
| 35 | std::string s = "Control message received (id: "; |
---|
| 36 | s += boost::lexical_cast<std::string>(header.nMsgType); |
---|
| 37 | s += ", len: "; |
---|
| 38 | s += boost::lexical_cast<std::string>(header.nMsgLen); |
---|
| 39 | s += ")"; |
---|
| 40 | Logger::Instance().LogDebug(s); |
---|
| 41 | TrafficCaptureMessage * pMsg = TrafficCaptureMessageFactory::Instance().CreateMessage( |
---|
| 42 | header.nMsgType, pPayload, header.nMsgLen); |
---|
| 43 | if (!pMsg) |
---|
| 44 | return; |
---|
| 45 | const char * pszIgnoreWarn = "Warning: message ignored; the capturing device hasn't been created yet"; |
---|
| 46 | switch (pMsg->GetId()) |
---|
| 47 | { |
---|
| 48 | case OPEN_DEVICE_REQ: |
---|
| 49 | { |
---|
| 50 | Logger::Instance().LogInfo("OpenDeviceRequest message received"); |
---|
| 51 | ECaptureInitResult res = ECaptureInit_Failed; |
---|
| 52 | if (m_pCapture == 0) |
---|
| 53 | { |
---|
| 54 | Logger::Instance().LogDebug("Creating capture instance..."); |
---|
| 55 | OpenDeviceRequest * pReq = dynamic_cast<OpenDeviceRequest*>(pMsg); |
---|
| 56 | m_pCapture = CaptureFactory::Instance().CreateCaptureInstance( |
---|
| 57 | pReq->GetCaptureType(), pReq->GetCaptureMode()); |
---|
| 58 | if (m_pCapture != 0) |
---|
| 59 | { |
---|
| 60 | m_pCapture->InitDispatch(&td); |
---|
| 61 | m_pCapture->SetStartOffset(pReq->GetTimestamp()); |
---|
| 62 | Logger::Instance().LogDebug("Initializing capture instance..."); |
---|
| 63 | res = m_pCapture->OpenDevice(pReq->GetParameters()); |
---|
| 64 | std::string sFile = pReq->GetCaptureFile(); |
---|
| 65 | if (res != ECaptureInit_Failed && sFile.length() > 0) |
---|
| 66 | { |
---|
| 67 | if (!m_pCapture->SetCaptureFile(sFile)) |
---|
| 68 | res = ECaptureInit_Failed; |
---|
| 69 | } |
---|
| 70 | if (res == ECaptureInit_Failed) |
---|
| 71 | { |
---|
| 72 | CaptureFactory::Instance().DisposeCaptureInstance(m_pCapture); |
---|
| 73 | m_pCapture = 0; |
---|
| 74 | } |
---|
| 75 | } |
---|
| 76 | } |
---|
| 77 | else |
---|
| 78 | Logger::Instance().LogWarning("Capture device has been already created"); |
---|
| 79 | OpenDeviceReply reply; |
---|
| 80 | reply.SetResult(res); |
---|
| 81 | send(m_hSocket, reply.GetEncodedMessage(), reply.GetEncodedDataLength(), 0); |
---|
| 82 | Logger::Instance().LogDebug("OpenDeviceReply message sent"); |
---|
| 83 | } |
---|
| 84 | break; |
---|
| 85 | case SET_FILTER_REQ: |
---|
| 86 | Logger::Instance().LogInfo("SetFilterRequest message received"); |
---|
| 87 | { |
---|
| 88 | bool bRes = (m_pCapture != 0); |
---|
| 89 | if (bRes) |
---|
| 90 | { |
---|
| 91 | SetFilterRequest * pReq = dynamic_cast<SetFilterRequest*>(pMsg); |
---|
| 92 | std::string sFilter = pReq->GetFilter(); |
---|
| 93 | std::string s = "The received filter value is: "; |
---|
| 94 | s += sFilter; |
---|
| 95 | Logger::Instance().LogDebug(s); |
---|
| 96 | bRes = m_pCapture->SetFilter(sFilter); |
---|
| 97 | } |
---|
| 98 | else |
---|
| 99 | Logger::Instance().LogWarning(pszIgnoreWarn); |
---|
| 100 | SetFilterReply reply; |
---|
| 101 | SendSimpleReply(reply, !bRes); |
---|
| 102 | Logger::Instance().LogDebug("SetFilterReply message sent"); |
---|
| 103 | } |
---|
| 104 | break; |
---|
| 105 | case START_CAPTURE_REQ: |
---|
| 106 | { |
---|
| 107 | Logger::Instance().LogInfo("StartCaptureRequest message received"); |
---|
| 108 | if (m_pCapture) |
---|
| 109 | m_pCapture->StartCapture(); |
---|
| 110 | else |
---|
| 111 | Logger::Instance().LogWarning(pszIgnoreWarn); |
---|
| 112 | StartCaptureReply reply; |
---|
| 113 | SendSimpleReply(reply, m_pCapture == 0); |
---|
| 114 | } |
---|
| 115 | Logger::Instance().LogDebug("StartCaptureReply message sent"); |
---|
| 116 | break; |
---|
| 117 | case STOP_CAPTURE_REQ: |
---|
| 118 | { |
---|
| 119 | Logger::Instance().LogInfo("StopCaptureRequest message received"); |
---|
| 120 | if (m_pCapture) |
---|
| 121 | m_pCapture->StopCapture(); |
---|
| 122 | else |
---|
| 123 | Logger::Instance().LogWarning(pszIgnoreWarn); |
---|
| 124 | StopCaptureReply reply; |
---|
| 125 | SendSimpleReply(reply, m_pCapture == 0); |
---|
| 126 | Logger::Instance().LogDebug("StopCaptureReply message sent"); |
---|
| 127 | } |
---|
| 128 | break; |
---|
| 129 | case MERGE_FILES_REQ: |
---|
| 130 | { |
---|
| 131 | MergePcapFilesRequest * pReq = dynamic_cast<MergePcapFilesRequest*>(pMsg); |
---|
| 132 | Logger::Instance().LogInfo("MergePcapFilesRequest message received"); |
---|
| 133 | MergePcapFilesReply reply; |
---|
| 134 | bool bRes; |
---|
| 135 | std::vector<std::string> vsFiles = pReq->GetFilesToMerge(); |
---|
| 136 | if (bRes = vsFiles.size() > 0) |
---|
| 137 | { |
---|
| 138 | boost::filesystem::path targetFile = pReq->GetMergePath(); |
---|
| 139 | targetFile /= "mergefile.pcap"; |
---|
| 140 | if (boost::filesystem::exists(targetFile)) |
---|
| 141 | try |
---|
| 142 | { |
---|
| 143 | boost::filesystem::remove(targetFile); |
---|
| 144 | Logger::Instance().LogDebug( |
---|
| 145 | "Merge file from a previous session has been successfully removed"); |
---|
| 146 | } |
---|
| 147 | catch (boost::filesystem::filesystem_error) |
---|
| 148 | { |
---|
| 149 | Logger::Instance().LogError( |
---|
| 150 | "Merge file from a previous session could not be removed"); |
---|
| 151 | bRes = false; |
---|
| 152 | } |
---|
| 153 | else |
---|
| 154 | Logger::Instance().LogDebug("No merge file from a previous session"); |
---|
| 155 | if (bRes) |
---|
| 156 | { |
---|
| 157 | boost::filesystem::path mergecapPath = pReq->GetMergecapDirectory(); |
---|
| 158 | mergecapPath /= "mergecap"; |
---|
| 159 | std::string sCmd = "\""; |
---|
| 160 | #ifdef WIN32 |
---|
| 161 | sCmd += "\""; |
---|
| 162 | #endif |
---|
| 163 | sCmd += mergecapPath.string(); |
---|
| 164 | sCmd += "\" -w \""; |
---|
| 165 | sCmd += targetFile.string(); |
---|
| 166 | sCmd += "\""; |
---|
| 167 | for (unsigned int i = 0; i < vsFiles.size(); ++i) |
---|
| 168 | { |
---|
| 169 | sCmd += " \""; |
---|
| 170 | sCmd += vsFiles[i]; |
---|
| 171 | sCmd += "\""; |
---|
| 172 | } |
---|
| 173 | #ifdef WIN32 |
---|
| 174 | sCmd += "\""; |
---|
| 175 | #endif |
---|
| 176 | Logger::Instance().LogDebug("Starting mergecap..."); |
---|
| 177 | Logger::Instance().LogDebug(sCmd); |
---|
| 178 | system(sCmd.c_str()); |
---|
| 179 | reply.SetMergeFile(targetFile.string()); |
---|
| 180 | if (bRes = boost::filesystem::exists(targetFile)) |
---|
| 181 | Logger::Instance().LogDebug("Files merged successfully"); |
---|
| 182 | else |
---|
| 183 | Logger::Instance().LogError("File merging failed"); |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | } |
---|
| 187 | SendSimpleReply(reply, bRes); |
---|
| 188 | Logger::Instance().LogDebug("MergePcapFilesReply message sent"); |
---|
| 189 | } |
---|
| 190 | break; |
---|
| 191 | default: |
---|
| 192 | Logger::Instance().LogWarning("Warning: the received control message is not supported"); |
---|
| 193 | } |
---|
| 194 | TrafficCaptureMessageFactory::Instance().DisposeMessage(pMsg); |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | void ConnectionController::Run() |
---|
| 198 | { |
---|
| 199 | TcpipDispatch td(m_hSocket); |
---|
| 200 | Logger::Instance().LogInfo("Waiting for control messages to inialize capturing..."); |
---|
| 201 | |
---|
| 202 | // infinite receiving loop: interrupted when the connection is closed |
---|
| 203 | TMessageHeader header; |
---|
| 204 | int nReceived = 0, nLen, nRemaining; |
---|
| 205 | char * pBuf = NULL; |
---|
| 206 | while (-1) |
---|
| 207 | { |
---|
| 208 | if (nReceived < sizeof(header)) |
---|
| 209 | { |
---|
| 210 | nRemaining = sizeof(header) - nReceived; |
---|
| 211 | if ((nLen = recv(m_hSocket, reinterpret_cast<char*>(&header) + nReceived, nRemaining, 0)) <= 0) |
---|
| 212 | break; |
---|
| 213 | nReceived += nLen; |
---|
| 214 | } |
---|
| 215 | else |
---|
| 216 | { |
---|
| 217 | if (header.nMsgLen > 0) |
---|
| 218 | { |
---|
| 219 | if (pBuf == NULL) |
---|
| 220 | pBuf = new char[header.nMsgLen]; |
---|
| 221 | nRemaining = sizeof(header) + header.nMsgLen - nReceived; |
---|
| 222 | if ((nLen = recv(m_hSocket, pBuf + nReceived - sizeof(header), nRemaining , 0)) <= 0) |
---|
| 223 | break; |
---|
| 224 | nReceived += nLen; |
---|
| 225 | } |
---|
| 226 | if (nReceived == sizeof(header) + header.nMsgLen) |
---|
| 227 | { |
---|
| 228 | ProcessMessage(header, pBuf, td); |
---|
| 229 | delete[] pBuf; |
---|
| 230 | pBuf = NULL; |
---|
| 231 | nReceived = 0; |
---|
| 232 | if (!m_hSocket) |
---|
| 233 | break; |
---|
| 234 | } |
---|
| 235 | } |
---|
| 236 | } |
---|
| 237 | |
---|
| 238 | boost::mutex::scoped_lock cond(m_mutex); |
---|
| 239 | td.Stop(); |
---|
| 240 | CaptureFactory::Instance().DisposeCaptureInstance(m_pCapture); |
---|
| 241 | m_pCapture = NULL; |
---|
| 242 | Logger::Instance().LogInfo("Client connection terminated"); |
---|
| 243 | if (m_hSocket != SOCKET_CALL_ERROR) |
---|
| 244 | { |
---|
| 245 | CLOSE_SOCKET(m_hSocket); |
---|
| 246 | m_hSocket = SOCKET_CALL_ERROR; |
---|
| 247 | } |
---|
| 248 | m_captureClosed.notify_one(); |
---|
| 249 | |
---|
| 250 | } |
---|
| 251 | |
---|
| 252 | void ConnectionController::Stop() |
---|
| 253 | { |
---|
| 254 | boost::mutex::scoped_lock cond(m_mutex); |
---|
| 255 | if (m_hSocket != SOCKET_CALL_ERROR) |
---|
| 256 | { |
---|
| 257 | CLOSE_SOCKET(m_hSocket); |
---|
| 258 | m_hSocket = SOCKET_CALL_ERROR; |
---|
| 259 | m_captureClosed.wait(cond); |
---|
| 260 | } |
---|
| 261 | } |
---|