Server.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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[max_data_length + 1];
  320. while (size_t read =
  321. this->getFile.readsome(fileBuffer, max_data_length)) {
  322. fileBuffer[read] = 0;
  323. size -= read;
  324. int remaining = size / max_data_length +
  325. (size % max_data_length == 0 ? 0 : 1);
  326. answer["remaining"] = remaining;
  327. answer["cancel"] = false;
  328. answer["data"] = base64::encode(fileBuffer);
  329. const std::string answerString =
  330. Json::writeString(stringBuilder, answer);
  331. sock.async_write_some(
  332. buffer(answerString, max_length),
  333. boost::bind(&con_handler::handle_write, shared_from_this(),
  334. placeholders::error,
  335. placeholders::bytes_transferred));
  336. }
  337. this->getFile.close();
  338. }
  339. }
  340. }
  341. } else if (root["command"].compare("close") == 0) {
  342. answer["command"] = "close";
  343. answer["response"] = "bye";
  344. const std::string answerString = Json::writeString(stringBuilder, answer);
  345. // send answer
  346. sock.async_write_some(buffer(answerString, max_length),
  347. boost::bind(&con_handler::handle_write,
  348. shared_from_this(), placeholders::error,
  349. placeholders::bytes_transferred));
  350. // close connection
  351. sock.close();
  352. } else {
  353. // TODO handle error
  354. // close connection
  355. sock.close();
  356. }
  357. } else {
  358. std::cerr << "error: " << err.message() << std::endl;
  359. sock.close();
  360. }
  361. }
  362. void con_handler::handle_write(const boost::system::error_code &err,
  363. size_t bytes_transferred) {
  364. if (!err) {
  365. std::cout << "Hello World!" << std::endl;
  366. } else {
  367. std::cerr << "error: " << err.message() << std::endl;
  368. sock.close();
  369. }
  370. }
  371. /**********
  372. * Server *
  373. **********/
  374. void Server::start_accept() {
  375. auto executor = acceptor_.get_executor();
  376. con_handler::pointer connection = con_handler::create(executor);
  377. acceptor_.async_accept(connection->socket(),
  378. boost::bind(&Server::handle_accept, this, connection,
  379. placeholders::error));
  380. }
  381. Server::Server(io_service &io_service)
  382. : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
  383. start_accept();
  384. }
  385. Server::~Server() {}
  386. void Server::handle_accept(con_handler::pointer connection,
  387. const boost::system::error_code &err) {
  388. if (!err) {
  389. connection->start();
  390. }
  391. start_accept();
  392. }