Server.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. #include "../include/Server.h"
  2. #include "../include/base64.h"
  3. #include <iostream>
  4. #include <json/json.h>
  5. using namespace boost::asio;
  6. using ip::tcp;
  7. /***************
  8. * con_handler *
  9. ***************/
  10. con_handler::con_handler(
  11. basic_socket_acceptor<ip::tcp>::executor_type &io_service)
  12. : sock(io_service) {}
  13. con_handler::~con_handler() {}
  14. con_handler::pointer
  15. con_handler::create(basic_socket_acceptor<ip::tcp>::executor_type &io_service) {
  16. return pointer(new con_handler(io_service));
  17. }
  18. tcp::socket &con_handler::socket() { return sock; }
  19. void con_handler::start() {
  20. sock.async_read_some(buffer(data, max_length),
  21. boost::bind(&con_handler::handle_read_version,
  22. shared_from_this(), placeholders::error,
  23. placeholders::bytes_transferred));
  24. }
  25. void con_handler::handle_read(const boost::system::error_code &err,
  26. size_t bytes_transferred) {
  27. if (!err) {
  28. std::cout << this->data << std::endl;
  29. } else {
  30. std::cerr << "error: " << err.message() << std::endl;
  31. sock.close();
  32. }
  33. }
  34. void con_handler::handle_read_version(const boost::system::error_code &err,
  35. size_t bytes_transferred) {
  36. if (!err) {
  37. // set up json stuff
  38. JSONCPP_STRING err;
  39. Json::Value root;
  40. Json::CharReaderBuilder builder;
  41. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  42. // parse data
  43. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  44. &err)) {
  45. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  46. sock.close();
  47. }
  48. // create answer
  49. Json::Value answer;
  50. Json::StreamWriterBuilder stringBuilder;
  51. answer["version"] = this->protocolVersion;
  52. // check version string
  53. if (root["version"].asString().compare(this->protocolVersion) == 0) {
  54. answer["accept"] = true;
  55. const std::string answerString = Json::writeString(stringBuilder, answer);
  56. // read next data
  57. sock.async_read_some(buffer(data, max_length),
  58. boost::bind(&con_handler::handle_read_login,
  59. shared_from_this(), placeholders::error,
  60. placeholders::bytes_transferred));
  61. // send answer
  62. sock.async_write_some(buffer(answerString, max_length),
  63. boost::bind(&con_handler::handle_write,
  64. shared_from_this(), placeholders::error,
  65. placeholders::bytes_transferred));
  66. } else {
  67. answer["accept"] = false;
  68. const std::string answerString = Json::writeString(stringBuilder, answer);
  69. // send answer
  70. sock.async_write_some(buffer(answerString, max_length),
  71. boost::bind(&con_handler::handle_write,
  72. shared_from_this(), placeholders::error,
  73. placeholders::bytes_transferred));
  74. // close connection
  75. sock.close();
  76. }
  77. } else {
  78. std::cerr << "error: " << err.message() << std::endl;
  79. sock.close();
  80. }
  81. }
  82. void con_handler::handle_read_login(const boost::system::error_code &err,
  83. size_t bytes_transferred) {
  84. if (!err) {
  85. // set up json stuff
  86. JSONCPP_STRING err;
  87. Json::Value root;
  88. Json::CharReaderBuilder builder;
  89. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  90. // parse data
  91. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  92. &err)) {
  93. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  94. sock.close();
  95. }
  96. Json::Value answer;
  97. Json::StreamWriterBuilder stringBuilder;
  98. // user credentials
  99. // TODO check user credentials!!!
  100. if (root["user"].asString().compare("user") == 0 &&
  101. root["pass"].asString().compare("pass") == 0) {
  102. answer["accept"] = true;
  103. const std::string answerString = Json::writeString(stringBuilder, answer);
  104. // read next data
  105. sock.async_read_some(buffer(data, max_length),
  106. boost::bind(&con_handler::handle_read_command,
  107. shared_from_this(), placeholders::error,
  108. placeholders::bytes_transferred));
  109. // send answer
  110. sock.async_write_some(buffer(answerString, max_length),
  111. boost::bind(&con_handler::handle_write,
  112. shared_from_this(), placeholders::error,
  113. placeholders::bytes_transferred));
  114. } else {
  115. answer["accept"] = false;
  116. const std::string answerString = Json::writeString(stringBuilder, answer);
  117. // send answer
  118. sock.async_write_some(buffer(answerString, max_length),
  119. boost::bind(&con_handler::handle_write,
  120. shared_from_this(), placeholders::error,
  121. placeholders::bytes_transferred));
  122. // close connection
  123. sock.close();
  124. }
  125. } else {
  126. std::cerr << "error: " << err.message() << std::endl;
  127. sock.close();
  128. }
  129. }
  130. void con_handler::handle_read_command(const boost::system::error_code &err,
  131. size_t bytes_transferred) {
  132. if (!err) {
  133. // set up json stuff
  134. JSONCPP_STRING err;
  135. Json::Value root;
  136. Json::CharReaderBuilder builder;
  137. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  138. // parse data
  139. if (!reader->parse(this->data, this->data + bytes_transferred, &root,
  140. &err)) {
  141. std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
  142. sock.close();
  143. }
  144. Json::Value answer;
  145. Json::StreamWriterBuilder stringBuilder;
  146. // check command
  147. if (root["command"].asString().compare("status") == 0) {
  148. // read next data
  149. sock.async_read_some(buffer(data, max_length),
  150. boost::bind(&con_handler::handle_read_command,
  151. shared_from_this(), placeholders::error,
  152. placeholders::bytes_transferred));
  153. answer["command"] = "status";
  154. // TODO answer a real status message
  155. std::string response;
  156. if (this->getFile.is_open() && this->putFile.is_open()) {
  157. response = "download and upload running";
  158. } else if (this->putFile.is_open()) {
  159. response = "upload running";
  160. } else if (this->getFile.is_open()) {
  161. response = "download running";
  162. } else {
  163. response = "ok";
  164. }
  165. answer["response"] = response;
  166. const std::string answerString = Json::writeString(stringBuilder, answer);
  167. // send answer
  168. sock.async_write_some(buffer(answerString, max_length),
  169. boost::bind(&con_handler::handle_write,
  170. shared_from_this(), placeholders::error,
  171. placeholders::bytes_transferred));
  172. } else if (root["command"].asString().compare("list") == 0) {
  173. // read next data
  174. sock.async_read_some(buffer(data, max_length),
  175. boost::bind(&con_handler::handle_read_command,
  176. shared_from_this(), placeholders::error,
  177. placeholders::bytes_transferred));
  178. answer["command"] = "list";
  179. // TODO look for real data
  180. Json::Value array;
  181. array.append("some");
  182. array.append("important");
  183. array.append("data");
  184. answer["names"] = array;
  185. answer["remaining"] = 0;
  186. const std::string answerString = Json::writeString(stringBuilder, answer);
  187. // send answer
  188. sock.async_write_some(buffer(answerString, max_length),
  189. boost::bind(&con_handler::handle_write,
  190. shared_from_this(), placeholders::error,
  191. placeholders::bytes_transferred));
  192. } else if (root["command"].asString().compare("put") == 0) {
  193. // read next data
  194. sock.async_read_some(buffer(data, max_length),
  195. boost::bind(&con_handler::handle_read_command,
  196. shared_from_this(), placeholders::error,
  197. placeholders::bytes_transferred));
  198. answer["command"] = "put";
  199. if (this->putFile.is_open() && root["cancel"].asBool() == true) {
  200. // cancel upload
  201. this->putFile.close();
  202. std::remove(this->putFileName.c_str());
  203. } else if (this->putFile.is_open() &&
  204. (this->putFile.tellp() == std::ios::beg ||
  205. root["remaining"].asInt() == this->putFileReceived - 1)) {
  206. // upload chunks
  207. // decode base64 string
  208. const std::vector<char> data =
  209. base64::decodeVector(root["data"].asString());
  210. // write the vector data to the output file
  211. std::ostream_iterator<char> output_iterator(putFile);
  212. std::copy(data.begin(), data.end(), output_iterator);
  213. this->putFileReceived = root["remaining"].asInt();
  214. // close file if put sends remaining = 0
  215. if (this->putFileReceived == 0) {
  216. this->putFile.close();
  217. }
  218. answer["cancel"] = false;
  219. answer["received"] = this->putFileReceived;
  220. const std::string answerString =
  221. Json::writeString(stringBuilder, answer);
  222. // send answer
  223. sock.async_write_some(
  224. buffer(answerString, max_length),
  225. boost::bind(&con_handler::handle_write, shared_from_this(),
  226. placeholders::error, placeholders::bytes_transferred));
  227. } else {
  228. // start upload
  229. const std::string filename = root["file"].asString();
  230. if (filename.find("/") != std::string::npos) {
  231. // slashes in file names are illegal
  232. answer["accept"] = false;
  233. const std::string answerString =
  234. Json::writeString(stringBuilder, answer);
  235. // send answer
  236. sock.async_write_some(buffer(answerString, max_length),
  237. boost::bind(&con_handler::handle_write,
  238. shared_from_this(),
  239. placeholders::error,
  240. placeholders::bytes_transferred));
  241. } else {
  242. // build file path
  243. this->putFileName = this->fileDirectory;
  244. this->putFileName.append(filename);
  245. // open file and test if it already exists
  246. this->putFile.open(this->putFileName,
  247. std::ios::app | std::ios::binary);
  248. if (this->putFile.tellp() != std::ios::beg &&
  249. root["file"].isString()) {
  250. // file already exists
  251. this->putFile.close();
  252. answer["accept"] = false;
  253. const std::string answerString =
  254. Json::writeString(stringBuilder, answer);
  255. // send answer
  256. sock.async_write_some(buffer(answerString, max_length),
  257. boost::bind(&con_handler::handle_write,
  258. shared_from_this(),
  259. placeholders::error,
  260. placeholders::bytes_transferred));
  261. } else {
  262. // accept file
  263. answer["accept"] = true;
  264. const std::string answerString =
  265. Json::writeString(stringBuilder, answer);
  266. // send answer
  267. sock.async_write_some(buffer(answerString, max_length),
  268. boost::bind(&con_handler::handle_write,
  269. shared_from_this(),
  270. placeholders::error,
  271. placeholders::bytes_transferred));
  272. }
  273. }
  274. }
  275. } else if (root["command"].asString().compare("get") == 0) {
  276. // read next data
  277. sock.async_read_some(buffer(data, max_length),
  278. boost::bind(&con_handler::handle_read_command,
  279. shared_from_this(), placeholders::error,
  280. placeholders::bytes_transferred));
  281. answer["command"] = "get";
  282. if (this->getFile.is_open()) {
  283. // a get request is already being progressed
  284. if (root["received"].asInt() == this->getFileRemaining) {
  285. if (root["cancel"].asBool()) {
  286. // cancel get
  287. this->getFile.close();
  288. } else if (this->getFileRemaining > 0) {
  289. char fileBuffer[max_data_length];
  290. size_t read = this->getFile.readsome(fileBuffer, max_data_length);
  291. this->getFileRemaining--;
  292. // store binary data in vector because a string whould end with
  293. // '\0'
  294. std::vector<char> data;
  295. data.assign(fileBuffer, fileBuffer + read);
  296. answer["remaining"] = this->getFileRemaining;
  297. answer["cancel"] = false;
  298. answer["data"] = base64::encodeVector(data);
  299. const std::string answerString =
  300. Json::writeString(stringBuilder, answer);
  301. sock.async_write_some(buffer(answerString, max_length),
  302. boost::bind(&con_handler::handle_write,
  303. shared_from_this(),
  304. placeholders::error,
  305. placeholders::bytes_transferred));
  306. } else {
  307. // remaining 0 and received by client so you can close the file
  308. this->getFile.close();
  309. }
  310. } else {
  311. answer["accept"] = false;
  312. const std::string answerString =
  313. Json::writeString(stringBuilder, answer);
  314. // send answer
  315. sock.async_write_some(buffer(answerString, max_length),
  316. boost::bind(&con_handler::handle_write,
  317. shared_from_this(),
  318. placeholders::error,
  319. placeholders::bytes_transferred));
  320. }
  321. } else {
  322. // open file
  323. const std::string filename = root["file"].asString();
  324. if (filename.find("/") != std::string::npos) {
  325. // slashes in file names are illegal
  326. answer["accept"] = false;
  327. const std::string answerString =
  328. Json::writeString(stringBuilder, answer);
  329. // send answer
  330. sock.async_write_some(buffer(answerString, max_length),
  331. boost::bind(&con_handler::handle_write,
  332. shared_from_this(),
  333. placeholders::error,
  334. placeholders::bytes_transferred));
  335. } else {
  336. std::string file = this->fileDirectory;
  337. file.append(filename);
  338. this->getFile = std::ifstream(file, std::ios::ate | std::ios::binary);
  339. if (this->getFile.is_open() == 0) {
  340. // file does not exist or cannot be opened
  341. answer["accept"] = false;
  342. const std::string answerString =
  343. Json::writeString(stringBuilder, answer);
  344. // send answer
  345. sock.async_write_some(buffer(answerString, max_length),
  346. boost::bind(&con_handler::handle_write,
  347. shared_from_this(),
  348. placeholders::error,
  349. placeholders::bytes_transferred));
  350. } else {
  351. answer["accept"] = true;
  352. std::string answerString = Json::writeString(stringBuilder, answer);
  353. sock.async_write_some(buffer(answerString, max_length),
  354. boost::bind(&con_handler::handle_write,
  355. shared_from_this(),
  356. placeholders::error,
  357. placeholders::bytes_transferred));
  358. answer = Json::Value();
  359. answer["command"] = "get";
  360. // get size of file
  361. size_t size = this->getFile.tellg();
  362. this->getFile.seekg(std::ios::beg);
  363. char fileBuffer[max_data_length];
  364. size_t read = this->getFile.readsome(fileBuffer, max_data_length);
  365. size -= read;
  366. this->getFileRemaining =
  367. size / max_data_length + (size % max_data_length == 0 ? 0 : 1);
  368. // store binary data in vector because a string whould end with
  369. // '\0'
  370. std::vector<char> data;
  371. data.assign(fileBuffer, fileBuffer + read);
  372. answer["remaining"] = this->getFileRemaining;
  373. answer["cancel"] = false;
  374. answer["data"] = base64::encodeVector(data);
  375. answerString = Json::writeString(stringBuilder, answer);
  376. sock.async_write_some(buffer(answerString, max_length),
  377. boost::bind(&con_handler::handle_write,
  378. shared_from_this(),
  379. placeholders::error,
  380. placeholders::bytes_transferred));
  381. }
  382. }
  383. }
  384. } else if (root["command"].asString().compare("close") == 0) {
  385. answer["command"] = "close";
  386. answer["response"] = "bye";
  387. const std::string answerString = Json::writeString(stringBuilder, answer);
  388. // send answer
  389. sock.async_write_some(buffer(answerString, max_length),
  390. boost::bind(&con_handler::handle_write,
  391. shared_from_this(), placeholders::error,
  392. placeholders::bytes_transferred));
  393. // close connection
  394. sock.close();
  395. } else {
  396. // TODO handle error
  397. // close connection
  398. sock.close();
  399. }
  400. } else {
  401. std::cerr << "error: " << err.message() << std::endl;
  402. sock.close();
  403. }
  404. }
  405. void con_handler::handle_write(const boost::system::error_code &err,
  406. size_t bytes_transferred) {
  407. if (!err) {
  408. std::cout << "Hello World!" << std::endl;
  409. } else {
  410. std::cerr << "error: " << err.message() << std::endl;
  411. sock.close();
  412. }
  413. }
  414. /**********
  415. * Server *
  416. **********/
  417. void Server::start_accept() {
  418. auto executor = acceptor_.get_executor();
  419. con_handler::pointer connection = con_handler::create(executor);
  420. acceptor_.async_accept(connection->socket(),
  421. boost::bind(&Server::handle_accept, this, connection,
  422. placeholders::error));
  423. }
  424. Server::Server(io_service &io_service)
  425. : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
  426. start_accept();
  427. }
  428. Server::~Server() {}
  429. void Server::handle_accept(con_handler::pointer connection,
  430. const boost::system::error_code &err) {
  431. if (!err) {
  432. connection->start();
  433. }
  434. start_accept();
  435. }