HCE project C++ developers source code library  1.1.1
HCE project developer library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
DRCEFunctionalObject.cpp
Go to the documentation of this file.
1 #include <Poco/Environment.h>
2 #include <Poco/Process.h>
3 #include <fstream>
4 #include <iterator>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <utility>
10 
12 #include "DRCEFunctionalObject.hpp"
13 #include "DRCEDefaultJSON.hpp"
14 #include "DRCEFilesList.hpp"
15 #include "DRCEError.hpp"
16 #include "ShellExec.hpp"
17 #include "DRCEMessageConst.hpp"
19 
20 namespace HCE
21 {
22 namespace drce
23 {
24 //-----------------------------------------------------------------------------
25 DRCEFunctionalObject::DRCEFunctionalObject(const std::string& nodeName_, const std::string& homeDir_)
26 : inherited(), nodeName(nodeName_), homeDir(""), messagesCollection(message_const::messages), message(messagesCollection)
27 {
28  setHomeDir(homeDir_);
29 }
30 //-----------------------------------------------------------------------------
31 bool DRCEFunctionalObject::setHomeDir(const std::string& homeDir_)
32 {
33  resetError();
34  if (chdir(homeDir_.c_str())==0)
35  homeDir=homeDir_;
36  else
37  {
38  isError(true);
40  setErrorMsg(strerror(errno));
41  }
42  return !_isError;
43 }
44 //-----------------------------------------------------------------------------
46 {
47  isError(false);
49  setErrorMsg("");
50 }
51 //-----------------------------------------------------------------------------
53 {
55  DRCEDefaultJSON defaultJson;
56  return defaultJson.getJSON();
57 }
58 //-----------------------------------------------------------------------------
59 std::string DRCEFunctionalObject::Process(const std::string& json)
60 {
61  std::string resJson;
63  setErrorMsg("");
64  try
65  {
66  DRCEInputJsonMessage inputJsonMessage(json);
67  if (inputJsonMessage.isError())
68  throw Poco::Exception(inputJsonMessage.getErrorMsg(), PARSE_ERROR);
69 
70  DRCEOutputJsonMessage outputMessage = Process(inputJsonMessage);
71 
72  outputMessage.setErrorCode(this->getErrorCode());
73  outputMessage.setErrorMessage(this->getErrorMsg());
74 
75  if (!outputMessage.serialize(resJson))
76  throw Poco::Exception(outputMessage.getErrorMsg(), outputMessage.getErrorCode());
77  }
78  catch(Poco::Exception& e)
79  {
80  errorMsg = e.message();
81  errorCode = e.code();
83  }
84  return (resJson.empty())?getDefaultJSON():resJson;
85 }
86 //-----------------------------------------------------------------------------
88 {
89  Poco::Timestamp tsStart;
90  DRCEOutputJsonMessage outputMessage;
91  DRCEResultDataItem resultDataItem;
92  DRCEResultData resultData;
93 
94  try
95  {
96  if (inputJsonMessage.getSessionOptions().sessionType==SessionOptions::SessionType::stHostShell)
97  {
98  makeProcessHostShell(inputJsonMessage, resultDataItem);
99  }
100  else if (inputJsonMessage.getSessionOptions().sessionType==SessionOptions::SessionType::stSsh)
101  {
102  makeProcessSsh(inputJsonMessage, resultDataItem);
103  }
104  else
105  {
106  throw Poco::Exception(message(message_const::UNKNOWN_SESSION_TYPE,
107  std::to_string(static_cast<unsigned int>(inputJsonMessage.getSessionOptions().sessionType))),
109  }
110  }
111  catch(Poco::Exception& e)
112  {
113  isError(true);
114  setErrorCode(e.code());
115  setErrorMsg(e.message());
116  }
117  catch(std::exception& e)
118  {
119  isError(true);
121  setErrorMsg(e.what());
122  }
123  outputMessage.setTime(getElapsedTimeMsec(tsStart));
124 
125  const size_t timeInterval = getElapsedTimeMsec(tsStart);
126  outputMessage.setTime(timeInterval);
127  resultDataItem.setTime(timeInterval);
128 
129  resultData.addDataItem(std::forward<DRCEResultDataItem>(resultDataItem));
130 
131  std::string resultJson;
132  DRCEResultDataSerializator resultDataSerializator(resultData);
133  if (!resultDataSerializator.serialize(resultJson))
134  throw Poco::Exception(resultDataSerializator.getErrorMsg(), resultDataSerializator.getErrorCode());
135 
136  outputMessage.setData(resultJson);
137 
138  return outputMessage;
139 }
140 //-----------------------------------------------------------------------------
141 std::string DRCEFunctionalObject::getFullFileName(const std::string& fileName)
142 {
143  std::string result;
144  if (fileName.find_last_of('/')==std::string::npos)
145  result.append("./").append(fileName);
146  else
147  result = fileName;
148 
149  return result;
150 }
151 //-----------------------------------------------------------------------------
152 void DRCEFunctionalObject::makeFilesBefore(DRCEFilesList& filesList) throw (Poco::Exception)
153 {
154  const size_t filesCount = filesList.getFilesCount();
155  for (size_t i=0;i<filesCount;++i)
156  {
157  const std::string fileName = getFullFileName(filesList.getFileItem(i).name);
158 
159  if (((filesList.getFileItem(i).actionType & FileItem::CREATE_BEFORE_EXEC_AND_WRITE_DATA)!=0)==1)
160  {
161  std::fstream ofs(fileName.c_str(), std::fstream::out|std::fstream::trunc|std::fstream::binary);
162  if (!ofs)
163  throw Poco::Exception(message(message_const::CREATE_FILE, fileName) , ERROR_CREATE_FILE_BEFORE_EXEC);
164 
165  ofs << ((((filesList.getFileItem(i).actionType & FileItem::ENCODE_DECODE_CONTENT_BASE64)!=0)==1)?DRCEDecodeBase64(filesList.getFileItem(i).data):filesList.getFileItem(i).data);
166  ofs.close();
167  }
168  if (((filesList.getFileItem(i).actionType & FileItem::DELETE_BEFORE_EXEC)!=0)==1)
169  {
170  if (remove(fileName.c_str())!=0)
171  throw Poco::Exception(message(message_const::DELETE_FILE, fileName)+
172  message(message_const::ERROR, strerror(errno)),
174  }
175  }
176 }
177 //-----------------------------------------------------------------------------
178 void DRCEFunctionalObject::makeFilesAfter(DRCEFilesList& filesList, DRCEResultDataItem& resultDataItem) throw (Poco::Exception)
179 {
180  const size_t filesCount = filesList.getFilesCount();
181  for (size_t i=0;i<filesCount;++i)
182  {
183  const std::string fileName = getFullFileName(filesList.getFileItem(i).name);
184 
185  if (((filesList.getFileItem(i).actionType & FileItem::READ_AFTER_EXEC_AND_RETURN_RESULT)!=0)==1)
186  {
187  std::ifstream ifs;
188  ifs.open(fileName, std::fstream::binary);
189  if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
190  throw Poco::Exception(message(message_const::READ_FILE, fileName), ERROR_READ_FILE_AFTER_EXEC);
191 
192  std::string fileContent;
193  ifs.seekg(0, std::ios::end);
194  fileContent.resize(ifs.tellg());
195  ifs.seekg(0, std::ios::beg);
196  ifs.read(const_cast<char*>(fileContent.c_str()), fileContent.size());
197  ifs.close();
198 
199  FileItem fileItem;
200  fileItem.actionType = filesList.getFileItem(i).actionType;
201  fileItem.name = filesList.getFileItem(i).name;
202  fileItem.data = ((((filesList.getFileItem(i).actionType & FileItem::ENCODE_DECODE_CONTENT_BASE64)!=0)==1)?DRCEEncodeBase64(fileContent):fileContent);
203  resultDataItem.addFileItem(std::forward<FileItem>(fileItem));
204  }
205  if (((filesList.getFileItem(i).actionType & FileItem::DELETE_AFTER_EXEC)!=0)==1)
206  {
207  if (remove(fileName.c_str())!=0)
208  throw Poco::Exception(message(message_const::DELETE_FILE, fileName)+
209  message(message_const::ERROR, strerror(errno)),
211  }
212  }
213 }
214 //-----------------------------------------------------------------------------
215 void DRCEFunctionalObject::makeSetEnviroment(const std::vector<std::pair<std::string, std::string> >& enviroments) throw (Poco::Exception)
216 {
217  for (size_t i=0;i<enviroments.size();++i)
218  {
219  if (setenv(enviroments[i].first.c_str(), enviroments[i].second.c_str(), 0)!=0)
220  throw Poco::Exception(strerror(errno), ERROR_SET_ENVIRONMENT);
221  }
222 }
223 //-----------------------------------------------------------------------------
224 void DRCEFunctionalObject::applyInputStream(std::stringstream& cmd, std::stringstream& istr)
225 {
226  std::istream_iterator<std::string> eos;
227  std::istream_iterator<std::string> iit(istr);
228 
229  cmd << "echo \"";
230  while(iit!=eos)
231  {
232  cmd << *iit;
233  iit++;
234  if (iit!=eos)
235  cmd << "\n";
236  }
237  cmd << "\"| ";
238 }
239 //-----------------------------------------------------------------------------
240 void DRCEFunctionalObject::makeProcessHostShell(DRCEInputJsonMessage& inputJsonMessage, DRCEResultDataItem& resultDataItem) throw (Poco::Exception)
241 {
242  makeFilesBefore(inputJsonMessage);
243 
244  makeSetEnviroment(inputJsonMessage.getSessionOptions().environments);
245 
246  std::stringstream cmd, istr(inputJsonMessage.getInputStream()), ostr, estr;
247  if (!istr.str().empty())
248  {
249  if (inputJsonMessage.getCommandLine().empty())
250  throw Poco::Exception(message(message_const::EMPTY_COMMAND_LINE), ERROR_COMMAND_EXECUTION);
251 
252  applyInputStream(cmd, istr);
253  }
254 
255  if (!inputJsonMessage.getCommandLine().empty())
256  {
257  cmd << inputJsonMessage.getCommandLine();
258  log() << message(message_const::COMMAND, cmd.str()) << std::endl;
259 
260  ShellExec shellExec(cmd.str());
261  if (!shellExec.exec(ostr, estr))
262  {
263  isError(true);
264  setErrorCode(ERROR_COMMAND_EXECUTION);
265  setErrorMsg(message(message_const::EXECUTE_COMMAND_FAIL)+
266  message(message_const::ERROR, estr.str()));
267  }
268  resultDataItem.setExitStatus(shellExec.getExitStatus());
269  }
270 
271  resultDataItem.setStdoutStream(ostr.str());
272  resultDataItem.setStderrStream(estr.str());
273  resultDataItem.setNodeName(nodeName);
274 
275  makeFilesAfter(inputJsonMessage, resultDataItem);
276 }
277 //-----------------------------------------------------------------------------
278 void DRCEFunctionalObject::makeProcessSsh(DRCEInputJsonMessage& inputJsonMessage, DRCEResultDataItem& resultDataItem) throw (Poco::Exception)
279 {
280  // TODO
281 }
282 //-----------------------------------------------------------------------------
283 //-----------------------------------------------------------------------------
284 } // namespace drce
285 } // namespace HCE