Server.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include "../include/Server.h"
  2. #include "../include/base64.h"
  3. #include <iostream>
  4. using namespace boost::asio;
  5. using ip::tcp;
  6. /***************
  7. * con_handler *
  8. ***************/
  9. con_handler::con_handler(
  10. basic_socket_acceptor<ip::tcp>::executor_type &io_service)
  11. : sock(io_service) {
  12. // disable indentation for json
  13. this->jsonStringBuilder.settings_["indentation"] = "";
  14. }
  15. con_handler::~con_handler() {}
  16. con_handler::pointer
  17. con_handler::create(basic_socket_acceptor<ip::tcp>::executor_type &io_service) {
  18. return pointer(new con_handler(io_service));
  19. }
  20. tcp::socket &con_handler::socket() { return sock; }
  21. void con_handler::start() { read(&con_handler::handle_read_version); }
  22. void con_handler::handle_read_version(const boost::system::error_code &err,
  23. size_t bytes_transferred) {
  24. if (!err) {
  25. // set up json stuff
  26. JSONCPP_STRING err;
  27. Json::Value root;
  28. Json::CharReaderBuilder builder;
  29. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  30. // parse data
  31. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  32. &err)) {
  33. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  34. sock.close();
  35. }
  36. // create answer
  37. Json::Value answer;
  38. answer["version"] = this->protocolVersion;
  39. // check version string
  40. if (root["version"].compare(this->protocolVersion) == 0) {
  41. answer["accept"] = true;
  42. read(&con_handler::handle_read_login);
  43. // send answer
  44. sendJson(answer);
  45. } else {
  46. answer["accept"] = false;
  47. // send answer
  48. sendJson(answer);
  49. ;
  50. // close connection
  51. sock.close();
  52. }
  53. } else {
  54. std::cerr << "error: " << err.message() << std::endl;
  55. sock.close();
  56. }
  57. }
  58. void con_handler::handle_read_login(const boost::system::error_code &err,
  59. size_t bytes_transferred) {
  60. if (!err) {
  61. // set up json stuff
  62. JSONCPP_STRING err;
  63. Json::Value root;
  64. Json::CharReaderBuilder builder;
  65. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  66. // parse data
  67. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  68. &err)) {
  69. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  70. sock.close();
  71. }
  72. Json::Value answer;
  73. // user credentials
  74. // TODO check user credentials!!!
  75. if (root["user"].compare("user") == 0 &&
  76. root["pass"].compare("pass") == 0) {
  77. answer["accept"] = true;
  78. // read next data
  79. read(&con_handler::handle_read_command);
  80. // send answer
  81. sendJson(answer);
  82. } else {
  83. answer["accept"] = false;
  84. // send answer
  85. sendJson(answer);
  86. // close connection
  87. sock.close();
  88. }
  89. } else {
  90. std::cerr << "error: " << err.message() << std::endl;
  91. sock.close();
  92. }
  93. }
  94. void con_handler::handle_read_command(const boost::system::error_code &err,
  95. size_t bytes_transferred) {
  96. if (!err) {
  97. // set up json stuff
  98. JSONCPP_STRING err;
  99. Json::Value root;
  100. Json::CharReaderBuilder builder;
  101. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  102. // parse data
  103. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  104. &err)) {
  105. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  106. sock.close();
  107. }
  108. Json::Value answer;
  109. // check command
  110. if (root["command"].compare("status") == 0) {
  111. // read next data
  112. read(&con_handler::handle_read_command);
  113. answer["command"] = "status";
  114. // TODO answer a real status message
  115. std::string response;
  116. if (this->getFile.is_open() && this->putFile.is_open()) {
  117. response = "download and upload running";
  118. } else if (this->putFile.is_open()) {
  119. response = "upload running";
  120. } else if (this->getFile.is_open()) {
  121. response = "download running";
  122. } else {
  123. response = "ok";
  124. }
  125. answer["response"] = response;
  126. // send answer
  127. sendJson(answer);
  128. } else if (root["command"].compare("list") == 0) {
  129. // read next data
  130. read(&con_handler::handle_read_command);
  131. answer["command"] = "list";
  132. // TODO look for real data
  133. Json::Value array;
  134. array.append("some");
  135. array.append("important");
  136. array.append("data");
  137. answer["names"] = array;
  138. answer["remaining"] = 0;
  139. // send answer
  140. sendJson(answer);
  141. } else if (root["command"].compare("put") == 0) {
  142. // read next data
  143. read(&con_handler::handle_read_command);
  144. answer["command"] = "put";
  145. if (this->putFile.is_open() && root["cancel"].asBool() == true) {
  146. // cancel upload
  147. this->putFile.close();
  148. std::remove(this->putFileName.c_str());
  149. } else if (this->putFile.is_open()) {
  150. // upload chunks
  151. // decode base64 string
  152. const std::vector<char> data =
  153. base64::decodeVector(root["data"].asString());
  154. // write the vector data to the output file
  155. std::ostream_iterator<char> output_iterator(putFile);
  156. std::copy(data.begin(), data.end(), output_iterator);
  157. // close file if put sends remaining = 0
  158. if (root["remaining"].asInt() == 0) {
  159. this->putFile.close();
  160. }
  161. } else {
  162. // start upload
  163. const std::string filename = root["file"].asString();
  164. if (filename.find("/") != std::string::npos) {
  165. // slashes in file names are illegal
  166. answer["accept"] = false;
  167. // send answer
  168. sendJson(answer);
  169. } else {
  170. // build file path
  171. this->putFileName = this->fileDirectory;
  172. this->putFileName.append(filename);
  173. // open file and test if it already exists
  174. this->putFile.open(this->putFileName,
  175. std::ios::app | std::ios::binary);
  176. if (this->putFile.tellp() != std::ios::beg) {
  177. // file already exists
  178. this->putFile.close();
  179. answer["accept"] = false;
  180. // send answer
  181. sendJson(answer);
  182. } else {
  183. // accept file
  184. answer["accept"] = true;
  185. // send answer
  186. sendJson(answer);
  187. }
  188. }
  189. }
  190. } else if (root["command"].compare("get") == 0) {
  191. // read next data
  192. read(&con_handler::handle_read_command);
  193. answer["command"] = "get";
  194. // a get request is already being progressed
  195. if (this->getFile.is_open()) {
  196. answer["accept"] = false;
  197. // send answer
  198. sendJson(answer);
  199. } else {
  200. // open file
  201. const std::string filename = root["file"].asString();
  202. if (filename.find("/") != std::string::npos) {
  203. // slashes in file names are illegal
  204. answer["accept"] = false;
  205. // send answer
  206. sendJson(answer);
  207. } else {
  208. std::string file = this->fileDirectory;
  209. file.append(filename);
  210. this->getFile = std::ifstream(file, std::ios::ate | std::ios::binary);
  211. if (this->getFile.is_open() == 0) {
  212. // file does not exist or cannot be opened
  213. answer["accept"] = false;
  214. // send answer
  215. sendJson(answer);
  216. } else {
  217. answer["accept"] = true;
  218. sendJson(answer);
  219. answer = Json::Value();
  220. answer["command"] = "get";
  221. // get size of file
  222. size_t size = this->getFile.tellg();
  223. this->getFile.seekg(std::ios::beg);
  224. char fileBuffer[max_data_length + 1];
  225. while (size_t read =
  226. this->getFile.readsome(fileBuffer, max_data_length)) {
  227. fileBuffer[read] = 0;
  228. size -= read;
  229. int remaining = size / max_data_length +
  230. (size % max_data_length == 0 ? 0 : 1);
  231. // store binary data in vector because a string whould end with
  232. // '\0'
  233. std::vector<char> data;
  234. data.assign(fileBuffer, fileBuffer + read);
  235. answer["remaining"] = remaining;
  236. answer["cancel"] = false;
  237. answer["data"] = base64::encodeVector(data);
  238. sendJson(answer);
  239. }
  240. this->getFile.close();
  241. }
  242. }
  243. }
  244. } else if (root["command"].compare("close") == 0) {
  245. answer["command"] = "close";
  246. answer["response"] = "bye";
  247. // send answer
  248. sendJson(answer);
  249. // close connection
  250. sock.close();
  251. } else {
  252. // TODO handle error
  253. // close connection
  254. sock.close();
  255. }
  256. } else {
  257. std::cerr << "error: " << err.message() << std::endl;
  258. sock.close();
  259. }
  260. }
  261. void con_handler::handle_write(const boost::system::error_code &err,
  262. size_t bytes_transferred) {
  263. if (!err) {
  264. std::cout << "Hello World!" << std::endl;
  265. } else {
  266. std::cerr << "error: " << err.message() << std::endl;
  267. sock.close();
  268. }
  269. }
  270. void con_handler::read(void (con_handler::*handler)(
  271. const boost::system::error_code &err, size_t bytes_transferred)) {
  272. sock.async_read_some(buffer(data, max_length),
  273. boost::bind(handler, shared_from_this(),
  274. placeholders::error,
  275. placeholders::bytes_transferred));
  276. }
  277. void con_handler::sendJson(const Json::Value &json) {
  278. std::string jsonString = Json::writeString(jsonStringBuilder, json);
  279. jsonString.append("\n");
  280. sock.async_write_some(buffer(jsonString, max_length),
  281. boost::bind(&con_handler::handle_write,
  282. shared_from_this(), placeholders::error,
  283. placeholders::bytes_transferred));
  284. }
  285. /**********
  286. * Server *
  287. **********/
  288. void Server::start_accept() {
  289. auto executor = acceptor_.get_executor();
  290. con_handler::pointer connection = con_handler::create(executor);
  291. acceptor_.async_accept(connection->socket(),
  292. boost::bind(&Server::handle_accept, this, connection,
  293. placeholders::error));
  294. }
  295. Server::Server(io_service &io_service)
  296. : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
  297. start_accept();
  298. }
  299. Server::~Server() {}
  300. void Server::handle_accept(con_handler::pointer connection,
  301. const boost::system::error_code &err) {
  302. if (!err) {
  303. connection->start();
  304. }
  305. start_accept();
  306. }