Server.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. #include "../include/Server.h"
  2. #include "../include/base64.h"
  3. #include <iostream>
  4. #include <jsoncpp/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"].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"].compare("user") == 0 &&
  101. root["pass"].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"].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"].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"].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. // upload chunks
  205. // decode base64 string
  206. const std::string data = base64::decode(root["data"].asString());
  207. this->putFile << data;
  208. // close file if put sends remaining = 0
  209. if (root["remaining"].asInt() == 0) {
  210. this->putFile.close();
  211. }
  212. } else {
  213. // start upload
  214. const std::string filename = root["file"].asString();
  215. if (filename.find("/") != std::string::npos) {
  216. // slashes in file names are illegal
  217. answer["accept"] = false;
  218. const std::string answerString =
  219. Json::writeString(stringBuilder, answer);
  220. // send answer
  221. sock.async_write_some(buffer(answerString, max_length),
  222. boost::bind(&con_handler::handle_write,
  223. shared_from_this(),
  224. placeholders::error,
  225. placeholders::bytes_transferred));
  226. } else {
  227. // build file path
  228. this->putFileName = this->fileDirectory;
  229. this->putFileName.append(filename);
  230. // open file and test if it already exists
  231. this->putFile.open(this->putFileName,
  232. std::ios::app | std::ios::binary);
  233. if (this->putFile.tellp() != std::ios::beg) {
  234. // file already exists
  235. this->putFile.close();
  236. answer["accept"] = false;
  237. const std::string answerString =
  238. Json::writeString(stringBuilder, answer);
  239. // send answer
  240. sock.async_write_some(buffer(answerString, max_length),
  241. boost::bind(&con_handler::handle_write,
  242. shared_from_this(),
  243. placeholders::error,
  244. placeholders::bytes_transferred));
  245. } else {
  246. // accept file
  247. answer["accept"] = true;
  248. const std::string answerString =
  249. Json::writeString(stringBuilder, answer);
  250. // send answer
  251. sock.async_write_some(buffer(answerString, max_length),
  252. boost::bind(&con_handler::handle_write,
  253. shared_from_this(),
  254. placeholders::error,
  255. placeholders::bytes_transferred));
  256. }
  257. }
  258. }
  259. } else if (root["command"].compare("get") == 0) {
  260. // read next data
  261. sock.async_read_some(buffer(data, max_length),
  262. boost::bind(&con_handler::handle_read_command,
  263. shared_from_this(), placeholders::error,
  264. placeholders::bytes_transferred));
  265. answer["command"] = "get";
  266. // a get request is already being progressed
  267. if (this->getFile.is_open()) {
  268. answer["accept"] = false;
  269. const std::string answerString =
  270. Json::writeString(stringBuilder, answer);
  271. // send answer
  272. sock.async_write_some(
  273. buffer(answerString, max_length),
  274. boost::bind(&con_handler::handle_write, shared_from_this(),
  275. placeholders::error, placeholders::bytes_transferred));
  276. } else {
  277. // open file
  278. const std::string filename = root["file"].asString();
  279. if (filename.find("/") != std::string::npos) {
  280. // slashes in file names are illegal
  281. answer["accept"] = false;
  282. const std::string answerString =
  283. Json::writeString(stringBuilder, answer);
  284. // send answer
  285. sock.async_write_some(buffer(answerString, max_length),
  286. boost::bind(&con_handler::handle_write,
  287. shared_from_this(),
  288. placeholders::error,
  289. placeholders::bytes_transferred));
  290. } else {
  291. std::string file = this->fileDirectory;
  292. file.append(filename);
  293. this->getFile = std::ifstream(file, std::ios::ate | std::ios::binary);
  294. if (this->getFile.is_open() == 0) {
  295. // file does not exist or cannot be opened
  296. answer["accept"] = false;
  297. const std::string answerString =
  298. Json::writeString(stringBuilder, answer);
  299. // send answer
  300. sock.async_write_some(buffer(answerString, max_length),
  301. boost::bind(&con_handler::handle_write,
  302. shared_from_this(),
  303. placeholders::error,
  304. placeholders::bytes_transferred));
  305. } else {
  306. answer["accept"] = true;
  307. const std::string answerString =
  308. Json::writeString(stringBuilder, answer);
  309. sock.async_write_some(buffer(answerString, max_length),
  310. boost::bind(&con_handler::handle_write,
  311. shared_from_this(),
  312. placeholders::error,
  313. placeholders::bytes_transferred));
  314. answer = Json::Value();
  315. answer["command"] = "get";
  316. // get size of file
  317. size_t size = this->getFile.tellg();
  318. this->getFile.seekg(std::ios::beg);
  319. char fileBuffer[9];
  320. while (size_t read = this->getFile.readsome(fileBuffer, 8)) {
  321. fileBuffer[read] = 0;
  322. size -= read;
  323. int remaining = size / 8 + (size % 8 == 0 ? 0 : 1);
  324. answer["remaining"] = remaining;
  325. answer["cancel"] = false;
  326. answer["data"] = base64::encode(fileBuffer);
  327. const std::string answerString =
  328. Json::writeString(stringBuilder, answer);
  329. sock.async_write_some(
  330. buffer(answerString, max_length),
  331. boost::bind(&con_handler::handle_write, shared_from_this(),
  332. placeholders::error,
  333. placeholders::bytes_transferred));
  334. }
  335. this->getFile.close();
  336. }
  337. }
  338. }
  339. } else if (root["command"].compare("close") == 0) {
  340. answer["command"] = "close";
  341. answer["response"] = "bye";
  342. const std::string answerString = Json::writeString(stringBuilder, answer);
  343. // send answer
  344. sock.async_write_some(buffer(answerString, max_length),
  345. boost::bind(&con_handler::handle_write,
  346. shared_from_this(), placeholders::error,
  347. placeholders::bytes_transferred));
  348. // close connection
  349. sock.close();
  350. } else {
  351. // TODO handle error
  352. // close connection
  353. sock.close();
  354. }
  355. } else {
  356. std::cerr << "error: " << err.message() << std::endl;
  357. sock.close();
  358. }
  359. }
  360. void con_handler::handle_write(const boost::system::error_code &err,
  361. size_t bytes_transferred) {
  362. if (!err) {
  363. std::cout << "Hello World!" << std::endl;
  364. } else {
  365. std::cerr << "error: " << err.message() << std::endl;
  366. sock.close();
  367. }
  368. }
  369. /**********
  370. * Server *
  371. **********/
  372. void Server::start_accept() {
  373. auto executor = acceptor_.get_executor();
  374. con_handler::pointer connection = con_handler::create(executor);
  375. acceptor_.async_accept(connection->socket(),
  376. boost::bind(&Server::handle_accept, this, connection,
  377. placeholders::error));
  378. }
  379. Server::Server(io_service &io_service)
  380. : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
  381. start_accept();
  382. }
  383. Server::~Server() {}
  384. void Server::handle_accept(con_handler::pointer connection,
  385. const boost::system::error_code &err) {
  386. if (!err) {
  387. connection->start();
  388. }
  389. start_accept();
  390. }