Forráskód Böngészése

implement cli machine put get and save work

Missingmew 5 éve
szülő
commit
90faea947a
5 módosított fájl, 176 hozzáadás és 52 törlés
  1. 3 13
      cli/include/iomanager.hpp
  2. 1 1
      cli/src/base64.cpp
  3. 6 3
      cli/src/commands.cpp
  4. 4 12
      cli/src/iomanager.cpp
  5. 162 23
      cli/src/machineiomanager.cpp

+ 3 - 13
cli/include/iomanager.hpp

@@ -5,7 +5,8 @@
 
 #include <string>
 #include <boost/asio.hpp>
-#include <json/json.h>
+
+#define BLOCKSIZE 8
 
 using boost::asio::ip::tcp;
 
@@ -14,19 +15,8 @@ protected:
 	boost::asio::io_service ios;
 	tcp::socket *tcpsock;
 	boost::system::error_code errcode;
-	std::string ipstring;
+	std::string *ipstring;
 	int port;
-
-	      std::string jsonerror;
-
-	      Json::CharReaderBuilder rbuilder;
-	      Json::CharReader *reader;
-	      Json::StreamWriterBuilder wbuilder;
-
-	bool sendJson(Json::Value root);
-	bool receiveJson(boost::asio::streambuf &recvbuf);
-	bool parseJson(Json::Value *root, boost::asio::streambuf &recvbuf);
-	
 public:
 	// Basic constructor
 	IoManager(char *ipcstring);

+ 1 - 1
cli/src/base64.cpp

@@ -1,4 +1,4 @@
-#include "../include/base64.h"
+#include "../include/base64.hpp"
 
 #include <boost/algorithm/string.hpp>
 #include <boost/archive/iterators/base64_from_binary.hpp>

+ 6 - 3
cli/src/commands.cpp

@@ -9,7 +9,7 @@ CMD commands[]{
 
     /* TODO
     {CMD_REMOVE	, "remove", "remove file from IP and queue (stops xfer
-    if required)"}, 
+    if required)"},
     {CMD_SETUP	, "setup", "configure server at IP"},
     {CMD_LOG	, "log", "show log from IP"}
     */
@@ -18,9 +18,12 @@ CMD commands[]{
 COMMANDID getCmdIdFromString(const char *str) {
   COMMANDID ret = CMD_UNKNOWN;
   char temp[COMMANDLEN + 1] = {0};
-  if (std::strlen(str) > COMMANDLEN)
+  int len = COMMANDLEN;
+  if (std::strlen(str) > COMMANDLEN) {
     return ret;
-  for (int i = 0; i < COMMANDLEN; i++)
+  }
+  else len = std::strlen(str);
+  for (int i = 0; i < len; i++)
     temp[i] = std::tolower(str[i]);
 
   for (int i = 0; i < sizeofarr(commands); i++) {

+ 4 - 12
cli/src/iomanager.cpp

@@ -8,6 +8,9 @@ IoManager::IoManager(char *ipcstring) {
   ipstring = std::string(ipcstring);
   port = 1234;
   tcpsock = new tcp::socket(ios);
+  wbuilder["indentation"] = ""; // If you want whitespace-less output
+  rbuilder["indentation"] = ""; // If you want whitespace-less output
+  // const std::string output = Json::writeString(wbuilder, root);
   reader = rbuilder.newCharReader();
 }
 
@@ -42,6 +45,7 @@ bool IoManager::parseJson(Json::Value *root, boost::asio::streambuf &recvbuf) {
               << jsonerror << std::endl;
     return false;
   }
+  recvbuf.consume(recvbuf.size());
   return true;
 }
 
@@ -51,9 +55,6 @@ bool IoManager::connect() {
   Json::Value root, checkok;
   bool bcheckok;
 
-  // builder["indentation"] = ""; // If you want whitespace-less output
-  // const std::string output = Json::writeString(wbuilder, root);
-
   ep =
       new tcp::endpoint(boost::asio::ip::address::from_string(ipstring), 1234);
 
@@ -76,9 +77,6 @@ bool IoManager::connect() {
   if(!receiveJson(recvbuf)) return false;
   if(!parseJson(&root, recvbuf)) return false;
 
-  // remove processed data from recvbuf
-  recvbuf.consume(recvbuf.size());
-
   std::cout << root << std::endl;
 
   // check if version check was ok
@@ -110,9 +108,6 @@ bool IoManager::connect() {
   if(!receiveJson(recvbuf)) return false;
   if(!parseJson(&root, recvbuf)) return false;
 
-  // remove processed data from recvbuf
-  recvbuf.consume(recvbuf.size());
-
   std::cout << root << std::endl;
   /* */
 
@@ -144,9 +139,6 @@ IoManager::~IoManager() {
   // recieve answer to disconnect
   receiveJson(recvbuf);
   parseJson(&root, recvbuf);
-  
-  // remove processed data from recvbuf
-  recvbuf.consume(recvbuf.size());
 
   std::cout << root << std::endl;
   /* */

+ 162 - 23
cli/src/machineiomanager.cpp

@@ -1,7 +1,12 @@
 #include "../include/machineiomanager.hpp"
 #include "../include/commands.hpp"
+#include "../include/base64.hpp"
 
+#include <fstream>
 #include <iostream>
+#include <vector>
+#include <limits>
+#include <boost/algorithm/string.hpp>
 
 #include <readline/readline.h>
 
@@ -11,19 +16,32 @@ void MachineIoManager::run() {
   std::cout << "MachineIoManager::run() says hello!" << std::endl;
 
   boost::asio::streambuf recvbuf;
-  boost::system::error_code errcode;
 
-  Json::Value root;
+  Json::Value root, recv;
   const char *recvjson;
 
-  Json::StreamWriterBuilder wbuilder;
-
   bool keep_reading = true;
   COMMANDID cmd;
   char *line = NULL;
+  
+  std::vector<std::string> tokens, pathtemp;
+	
+  std::fstream fs;
+	
+  // .open(path, mode; mode std::fstream::in, out, binary, trunc(ate))
+  // .read(char* dest, int size)
+  // .write(char* src, int size)
+  // .eof()
+  // .seekg(offset, ios_base::beg, cur, end)
+  // .tellg()
+  // .close()
+  
   while (keep_reading) {
+	  // clean up
     free(line);
     root = Json::Value();
+    recv = Json::Value();
+	  recvbuf.consume(recvbuf.size());
 
     // read an input line
     line = readline("");
@@ -32,8 +50,20 @@ void MachineIoManager::run() {
     if (strlen(line) == 0) {
       continue;
     }
+    
+    boost::algorithm::split(tokens, std::string(line), boost::algorithm::is_any_of(" "), boost::algorithm::token_compress_on);
+    
+    std::cerr << "tokens are: [ ";
+    for(int i = 0; i < tokens.size(); i++) {
+	    std::cerr << tokens[i] << " ";
+    }
+    std::cerr << "]" << std::endl;
+    
+    if(tokens.size() < 1) {
+	    continue;
+    }
 
-    cmd = getCmdIdFromString(line);
+    cmd = getCmdIdFromString(tokens[0].c_str());
 
     switch (cmd) {
     case CMD_DISCONNECT: {
@@ -45,36 +75,145 @@ void MachineIoManager::run() {
       root["command"] = "status";
 
       // send request
-      boost::asio::write(*tcpsock, buffer(Json::writeString(wbuilder, root)),
-                         errcode);
-      if (errcode) {
-        std::cerr << "couldnt send version check" << std::endl
-                  << errcode.message() << std::endl;
-        break;
-      }
-
+	sendJson(root);
       // receive answer
-      // using transfer_at_least(1) to avoid lockup with transfer_all()
-      boost::asio::read(*tcpsock, recvbuf, boost::asio::transfer_at_least(1),
-                        errcode);
-      if (errcode && errcode != boost::asio::error::eof) {
-        std::cerr << "couldnt recieve version check" << std::endl
-                  << errcode.message() << std::endl;
-        break;
-      }
+	receiveJson(recvbuf);
+      //
+	    parseJson(&recv, recvbuf);
 
       // dump received data to stdout for gui to handle
-      recvjson = boost::asio::buffer_cast<const char *>(recvbuf.data());
-      std::cout << recvjson;
+	    std::cout << recv;
+      //~ recvjson = boost::asio::buffer_cast<const char *>(recvbuf.data());
+      //~ std::cout << recvjson;
 
       break;
     }
+    case CMD_PUT: {
+	    int size, chunks, haveread;
+	    char rbuf[BLOCKSIZE];
+	    if(tokens.size() < 2) {
+		    std::cerr << "no files specified" << std::endl;
+		    break;
+	    }
+	    fs.open(tokens[1], std::fstream::in | std::fstream::binary);
+	    if(!fs.is_open()) {
+		    std::cerr << "couldnt open file " << tokens[1] << std::endl;
+		    break;
+	    }
+	    fs.seekg(0, fs.end);
+	    size = fs.tellg();
+	    fs.seekg(0, fs.beg);
+	    chunks = size / BLOCKSIZE + ((size % BLOCKSIZE)?1:0);
+	    std::cout << "size is " << size << " chunks are " << chunks << std::endl;
+	    
+	    if(!size) {
+		    std::cerr << "not sending empty file" << std::endl;
+		    break;
+	    }
+	    
+	    boost::algorithm::split(pathtemp, tokens[1], boost::algorithm::is_any_of("/"), boost::algorithm::token_compress_on);
+	    
+	    root["command"] = "put";
+	    root["file"] = pathtemp.back();
+	    root["size"] = size;
+	    
+	    std::cout << root;
+	    
+	    if(!sendJson(root) | !receiveJson(recvbuf) | !parseJson(&recv, recvbuf)) {
+		    // error occured, stop working
+		    break;
+	    }
+	    // dump to stdout for GUI
+	    std::cout << recv;
+	    
+	    // check correct command once asychronous
+	    if(recv["accept"].asBool()) {
+		    // request ok, start sending...
+		    root = Json::Value();
+		    root["command"] = "put";
+		    root["cancel"] = false;
+		    
+		    std::cout << root;
+		    
+		    while(chunks) {
+			haveread = fs.readsome(rbuf, BLOCKSIZE);
+			chunks--;
+			root["data"] = base64::encodeVector(std::vector<char>(rbuf, rbuf+haveread*sizeof(char)));
+			root["remaining"] = chunks;
+			if(!sendJson(root) | !receiveJson(recvbuf) | !parseJson(&recv, recvbuf)) {
+				// error occured, stop working
+				break;
+			}
+			if(recv["cancel"].asBool()) {
+				// transfer cancelled by server
+				break;
+			}
+			std::cout << root;
+			std::this_thread::sleep_for (std::chrono::seconds(1));
+		    }
+		    if(chunks) std::cerr << "not all data sent, remain chunks " << chunks << std::endl;
+	    }
+	    break;
+    }
+    case CMD_GET: {
+	    int chunks;
+	    std::vector<char> wtmp;
+	    char wbuf[BLOCKSIZE];
+	    if(tokens.size() < 2) {
+		    std::cerr << "no files specified" << std::endl;
+		    break;
+	    }
+	    fs.open(tokens[1], std::fstream::out | std::fstream::binary | std::fstream::trunc);
+	    if(!fs.is_open()) {
+		    std::cerr << "couldnt open file " << tokens[1] << std::endl;
+		    break;
+	    }
+	    
+	    root["command"] = "get";
+	    root["file"] = tokens[1];
+	    
+	    if(!sendJson(root) | !receiveJson(recvbuf) | !parseJson(&recv, recvbuf)) {
+		    // error occured, stop working
+		    break;
+	    }
+	    
+	    std::cout << recv << std::endl;
+	    
+	    if(recv["accept"].asBool()) {
+		    // for ACK
+		    root["command"] = "get";
+		    root["remaining"] = 0;
+		    root["cancel"] = false;
+		    // request ok, start receiving
+		    chunks = std::numeric_limits<int>::max();
+		    std::cout << "survive" << std::endl;
+		    while(chunks) {
+			    std::cout << "survive" << std::endl;
+			    if(!receiveJson(recvbuf) | !parseJson(&recv, recvbuf)) break;
+			    std::cout << "survive" << std::endl;
+			    std::cout << recv << std::endl;
+			    wtmp = base64::decodeVector(recv["data"].asString());
+			    fs.write(wtmp.data(), wtmp.size());
+			    chunks = recv["remaining"].asInt();
+			    if(!sendJson(root)) {
+				// couldnt ACK
+				break;
+			    }
+		    }
+	    }
+	    if(recv["cancel"].asBool()) std::cerr << "transfer was cancelled" << std::endl;
+	    if(recv["remaining"].asInt()) std::cerr << "not all data received, remain chunks " << recv["remaining"].asInt();
+	    break;
+    }
     default: {
       std::cerr << "unknown command " << line << "\n";
       break;
     }
     }
     std::printf("\n");
+    
+    // if a command used fs, close it now
+    if(fs.is_open()) fs.close();
   }
   free(line);