From 9897394d944821cdd492e333554343e52609fc6b Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Tue, 1 Oct 2024 15:10:51 +0200
Subject: [PATCH 01/11] change actions

---
 .github/workflows/debian-dev.yml | 12 ++++++------
 .github/workflows/debian.yml     | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/.github/workflows/debian-dev.yml b/.github/workflows/debian-dev.yml
index 44a05a8..3e332ce 100644
--- a/.github/workflows/debian-dev.yml
+++ b/.github/workflows/debian-dev.yml
@@ -29,17 +29,17 @@ jobs:
           cd ..
           mkdir -p nipovpn/usr/bin/
           cp build/core/nipovpn nipovpn/usr/bin/nipovpn
-          dpkg-deb --build nipovpn/ build/nipovpn-stage.deb
+          dpkg-deb --build nipovpn/ build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
       - name: Upload the Debian nipovpn as an artifact
         uses: actions/upload-artifact@v3
         with:
           name: nipovpn
-          path: build/nipovpn-stage.deb
+          path: build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
       - name: Show nipovpn information
         run: |
-          dpkg -I build/nipovpn-stage.deb
+          dpkg -I build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
   release:
     needs: build
@@ -59,7 +59,7 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           tag_name: 'v1.0.${{ github.run_number }}'
-          release_name: Release ${{ github.run_number }}
+          release_name: Staging v1.0.${{ github.run_number }}
           draft: false
           prerelease: true
 
@@ -69,6 +69,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           upload_url: ${{ steps.create_release.outputs.upload_url }}
-          asset_path: ./nipovpn-stage.deb
-          asset_name: nipovpn-stage.deb
+          asset_path: ./nipovpn_staging_v1-0-${{ github.run_number }}.deb
+          asset_name: nipovpn_staging_v1-0-${{ github.run_number }}.deb
           asset_content_type: application/octet-stream
diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml
index 011d1b7..2e0ae90 100644
--- a/.github/workflows/debian.yml
+++ b/.github/workflows/debian.yml
@@ -29,17 +29,17 @@ jobs:
           cd ..
           mkdir -p nipovpn/usr/bin/
           cp build/core/nipovpn nipovpn/usr/bin/nipovpn
-          dpkg-deb --build nipovpn/ build/nipovpn.deb
+          dpkg-deb --build nipovpn/ build/nipovpn_v1-0-${{ github.run_number }}.deb
 
       - name: Upload the Debian nipovpn as an artifact
         uses: actions/upload-artifact@v3
         with:
           name: nipovpn
-          path: build/nipovpn.deb
+          path: build/nipovpn_v1-0-${{ github.run_number }}.deb
 
       - name: Show nipovpn information
         run: |
-          dpkg -I build/nipovpn.deb
+          dpkg -I build/nipovpn_v1-0-${{ github.run_number }}.deb
 
   release:
     needs: build
@@ -59,7 +59,7 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           tag_name: 'v1.0.${{ github.run_number }}'
-          release_name: Release ${{ github.run_number }}
+          release_name: Version v1.0.${{ github.run_number }}
           draft: false
           prerelease: false
 
@@ -69,6 +69,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           upload_url: ${{ steps.create_release.outputs.upload_url }}
-          asset_path: ./nipovpn.deb
-          asset_name: nipovpn.deb
+          asset_path: ./nipovpn_v1-0-${{ github.run_number }}.deb
+          asset_name: nipovpn_v1-0-${{ github.run_number }}.deb
           asset_content_type: application/octet-stream

From 57c64563cad7cfa2c84337b82ab1bd0e9904d26f Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Tue, 1 Oct 2024 15:10:51 +0200
Subject: [PATCH 02/11] change actions

---
 .github/workflows/debian-dev.yml | 13 +++++++------
 .github/workflows/debian.yml     | 12 ++++++------
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/.github/workflows/debian-dev.yml b/.github/workflows/debian-dev.yml
index 44a05a8..6064a97 100644
--- a/.github/workflows/debian-dev.yml
+++ b/.github/workflows/debian-dev.yml
@@ -6,6 +6,7 @@ on:
       - dev
     paths:
       - 'core/src/**'
+      - '.github/workflows/**'
 
 jobs:
   build:
@@ -29,17 +30,17 @@ jobs:
           cd ..
           mkdir -p nipovpn/usr/bin/
           cp build/core/nipovpn nipovpn/usr/bin/nipovpn
-          dpkg-deb --build nipovpn/ build/nipovpn-stage.deb
+          dpkg-deb --build nipovpn/ build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
       - name: Upload the Debian nipovpn as an artifact
         uses: actions/upload-artifact@v3
         with:
           name: nipovpn
-          path: build/nipovpn-stage.deb
+          path: build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
       - name: Show nipovpn information
         run: |
-          dpkg -I build/nipovpn-stage.deb
+          dpkg -I build/nipovpn_staging_v1-0-${{ github.run_number }}.deb
 
   release:
     needs: build
@@ -59,7 +60,7 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           tag_name: 'v1.0.${{ github.run_number }}'
-          release_name: Release ${{ github.run_number }}
+          release_name: Staging v1.0.${{ github.run_number }}
           draft: false
           prerelease: true
 
@@ -69,6 +70,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           upload_url: ${{ steps.create_release.outputs.upload_url }}
-          asset_path: ./nipovpn-stage.deb
-          asset_name: nipovpn-stage.deb
+          asset_path: ./nipovpn_staging_v1-0-${{ github.run_number }}.deb
+          asset_name: nipovpn_staging_v1-0-${{ github.run_number }}.deb
           asset_content_type: application/octet-stream
diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml
index 011d1b7..2e0ae90 100644
--- a/.github/workflows/debian.yml
+++ b/.github/workflows/debian.yml
@@ -29,17 +29,17 @@ jobs:
           cd ..
           mkdir -p nipovpn/usr/bin/
           cp build/core/nipovpn nipovpn/usr/bin/nipovpn
-          dpkg-deb --build nipovpn/ build/nipovpn.deb
+          dpkg-deb --build nipovpn/ build/nipovpn_v1-0-${{ github.run_number }}.deb
 
       - name: Upload the Debian nipovpn as an artifact
         uses: actions/upload-artifact@v3
         with:
           name: nipovpn
-          path: build/nipovpn.deb
+          path: build/nipovpn_v1-0-${{ github.run_number }}.deb
 
       - name: Show nipovpn information
         run: |
-          dpkg -I build/nipovpn.deb
+          dpkg -I build/nipovpn_v1-0-${{ github.run_number }}.deb
 
   release:
     needs: build
@@ -59,7 +59,7 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           tag_name: 'v1.0.${{ github.run_number }}'
-          release_name: Release ${{ github.run_number }}
+          release_name: Version v1.0.${{ github.run_number }}
           draft: false
           prerelease: false
 
@@ -69,6 +69,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
         with:
           upload_url: ${{ steps.create_release.outputs.upload_url }}
-          asset_path: ./nipovpn.deb
-          asset_name: nipovpn.deb
+          asset_path: ./nipovpn_v1-0-${{ github.run_number }}.deb
+          asset_name: nipovpn_v1-0-${{ github.run_number }}.deb
           asset_content_type: application/octet-stream

From 7517c329fd4933e7816fe20960a57490d8031f08 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Wed, 2 Oct 2024 13:30:20 +0200
Subject: [PATCH 03/11] Implement chunkSize in config

---
 core/src/config.cpp             |  4 +++-
 core/src/config.hpp             |  1 +
 core/src/general.hpp            | 12 ++++++++++++
 nipovpn/etc/nipovpn/config.yaml |  5 ++++-
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/core/src/config.cpp b/core/src/config.cpp
index 34151d4..2ce7705 100644
--- a/core/src/config.cpp
+++ b/core/src/config.cpp
@@ -11,7 +11,8 @@ Config::Config(const RunMode &mode, const std::string &filePath)
                 configYaml_["general"]["method"].as<std::string>(),
                 configYaml_["general"]["timeWait"].as<unsigned int>(),
                 configYaml_["general"]["timeout"].as<unsigned short>(),
-                configYaml_["general"]["repeatWait"].as<unsigned short>()}),
+                configYaml_["general"]["repeatWait"].as<unsigned short>(),
+                configYaml_["general"]["chunkSize"].as<unsigned short>()}),
       log_({configYaml_["log"]["logLevel"].as<std::string>(),
             configYaml_["log"]["logFile"].as<std::string>()}),
       server_({configYaml_["server"]["threads"].as<unsigned short>(),
@@ -62,6 +63,7 @@ std::string Config::toString() const {
        << "   timeWait: " << general_.timeWait << "\n"
        << "   timeout: " << general_.timeout << "\n"
        << "   repeatWait: " << general_.repeatWait << "\n"
+       << "   chunkSize: " << general_.chunkSize << "\n"
        << " Log :\n"
        << "   logLevel: " << log_.level << "\n"
        << "   logFile: " << log_.file << "\n"
diff --git a/core/src/config.hpp b/core/src/config.hpp
index 7266d6a..7d1e8c6 100644
--- a/core/src/config.hpp
+++ b/core/src/config.hpp
@@ -19,6 +19,7 @@ class Config : private Uncopyable {
         unsigned int timeWait;
         unsigned short timeout;
         unsigned short repeatWait;
+        unsigned short chunkSize;
     };
 
     struct Log {
diff --git a/core/src/general.hpp b/core/src/general.hpp
index 7affc79..8aa59d8 100644
--- a/core/src/general.hpp
+++ b/core/src/general.hpp
@@ -309,6 +309,18 @@ inline BoolStr validateConfig(int argc, const char *argv[]) {
         return result;
     }
 
+    try {
+        configYaml["general"]["fakeUrl"].as<std::string>();
+        configYaml["general"]["method"].as<std::string>();
+        configYaml["general"]["timeWait"].as<unsigned int>();
+        configYaml["general"]["timeout"].as<unsigned short>();
+        configYaml["general"]["repeatWait"].as<unsigned short>();
+        configYaml["general"]["chunkSize"].as<unsigned short>();
+    } catch (const std::exception &e) {
+        result.message = std::string("Error in 'general' block: ") + e.what() + "\n";
+        return result;
+    }
+
     try {
         configYaml["log"]["logFile"].as<std::string>();
         configYaml["log"]["logLevel"].as<std::string>();
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index 85dada9..cdcb61d 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -18,11 +18,14 @@ general:
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
   repeatWait: 10
+  # chunkSize: unsigned short(1-65,635)
+  # Defines the chunk size that you want to read from socket.
+  chunkSize: 512
 
 # This block is to define log directives
 log:
   # logLevel: "INFO|TRACE|DEBUG"
-  logLevel: "INFO"
+  logLevel: "DEBUG"
   # logFile: "/var/log/nipo/nipo.log"
   #   Path of log file
   logFile: "/var/log/nipovpn/nipovpn.log"

From 9a26b01667bf5a49082f1fb5c67f106c121e945f Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Fri, 4 Oct 2024 15:41:28 +0200
Subject: [PATCH 04/11] problem with reading from socket when data is big

---
 core/src/agenthandler.cpp       | 88 ++++++++++++++++++++++-----------
 core/src/agenthandler.hpp       |  3 ++
 core/src/config.cpp             |  2 +
 core/src/config.hpp             |  1 +
 core/src/general.hpp            |  1 +
 core/src/http.cpp               | 19 ++++++-
 core/src/http.hpp               |  3 ++
 core/src/serverhandler.cpp      | 69 +++++++++++++++++++-------
 core/src/serverhandler.hpp      |  4 +-
 core/src/tcpclient.cpp          | 26 ++++++++--
 core/src/tcpclient.hpp          | 19 +------
 core/src/tcpconnection.cpp      | 52 ++++++++++---------
 core/src/tcpconnection.hpp      |  3 +-
 nipovpn/etc/nipovpn/config.yaml |  9 ++--
 14 files changed, 202 insertions(+), 97 deletions(-)

diff --git a/core/src/agenthandler.cpp b/core/src/agenthandler.cpp
index 1cd8470..643592c 100644
--- a/core/src/agenthandler.cpp
+++ b/core/src/agenthandler.cpp
@@ -14,7 +14,10 @@ AgentHandler::AgentHandler(boost::asio::streambuf &readBuffer,
       writeBuffer_(writeBuffer),
       request_(HTTP::create(config, log, readBuffer, uuid)),
       clientConnStr_(clientConnStr),
-      uuid_(uuid) {}
+      uuid_(uuid) {
+    FUCK("TCPClient END");
+    end_ = false;
+}
 
 AgentHandler::~AgentHandler() {}
 
@@ -28,14 +31,12 @@ void AgentHandler::handle() {
 
     if (encryption.ok) {
         log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Encryption Done]", Log::Level::DEBUG);
-
         std::string newReq(
                 request_->genHttpPostReqString(encode64(encryption.message)));
 
         if (request_->detectType()) {
             log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Request] : " + request_->toString(),
                         Log::Level::DEBUG);
-
             if (request_->parsedHttpRequest().target().length() > 0) {
                 log_->write("[" + to_string(uuid_) + "] [CONNECT] [SRC " + clientConnStr_ + "]" + " [DST " +
                                     boost::lexical_cast<std::string>(
@@ -43,13 +44,10 @@ void AgentHandler::handle() {
                                     "]",
                             Log::Level::INFO);
             }
-
             if (!client_->socket().is_open() ||
                 request_->httpType() == HTTP::HttpType::http ||
                 request_->httpType() == HTTP::HttpType::connect) {
                 boost::system::error_code ec;
-                ;
-
                 if (!client_->doConnect(config_->agent().serverIp,
                                         config_->agent().serverPort)) {
                     log_->write(std::string("[" + to_string(uuid_) + "] [CONNECT] [ERROR] [To Server] [SRC ") +
@@ -58,7 +56,6 @@ void AgentHandler::handle() {
                                         std::to_string(config_->agent().serverPort) + "]",
                                 Log::Level::INFO);
                 }
-
                 if (ec) {
                     log_->write(std::string("[" + to_string(uuid_) + "] [AgentHandler handle] Connection error: ") +
                                         ec.message(),
@@ -68,43 +65,33 @@ void AgentHandler::handle() {
             }
 
             copyStringToStreambuf(newReq, readBuffer_);
-
             log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Request To Server] : \n" + newReq,
                         Log::Level::DEBUG);
 
-
             client_->doWrite(readBuffer_);
             client_->doRead();
 
-
             if (client_->readBuffer().size() > 0) {
-
                 if (request_->httpType() != HTTP::HttpType::connect) {
-
                     HTTP::pointer response =
                             HTTP::create(config_, log_, client_->readBuffer(), uuid_);
-
-
                     if (response->parseHttpResp()) {
-
                         log_->write(
                                 "[" + to_string(uuid_) + "] [AgentHandler handle] [Response] : " + response->restoString(),
                                 Log::Level::DEBUG);
-
-
                         BoolStr decryption{false, std::string("FAILED")};
                         decryption =
                                 aes256Decrypt(decode64(boost::lexical_cast<std::string>(
                                                       response->parsedHttpResponse().body())),
                                               config_->agent().token);
-
-
+                        if (boost::lexical_cast<std::string>(response->parsedHttpResponse()[config_->general().chunkHeader]) == "yes") {
+                            FUCK("AgentHandler END");
+                            end_ = true;
+                        }
                         if (decryption.ok) {
-
                             copyStringToStreambuf(decryption.message, writeBuffer_);
                             log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Done]", Log::Level::DEBUG);
                         } else {
-
                             log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : [ " +
                                                 decryption.message + "] ",
                                         Log::Level::DEBUG);
@@ -114,7 +101,6 @@ void AgentHandler::handle() {
                             client_->socket().close();
                         }
                     } else {
-
                         log_->write(
                                 "[AgentHandler handle] [NOT HTTP Response] "
                                 "[Response] : " +
@@ -122,21 +108,17 @@ void AgentHandler::handle() {
                                 Log::Level::DEBUG);
                     }
                 } else {
-
+                    end_ = true;
                     log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Response to connect] : \n" +
                                         streambufToString(client_->readBuffer()),
                                 Log::Level::DEBUG);
-
-
                     moveStreambuf(client_->readBuffer(), writeBuffer_);
                 }
             } else {
-
                 client_->socket().close();
                 return;
             }
         } else {
-
             log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [NOT HTTP Request] [Request] : " +
                                 streambufToString(readBuffer_),
                         Log::Level::DEBUG);
@@ -145,7 +127,6 @@ void AgentHandler::handle() {
             return;
         }
     } else {
-
         log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Encryption Failed] : [ " +
                             encryption.message + "] ",
                     Log::Level::DEBUG);
@@ -154,7 +135,58 @@ void AgentHandler::handle() {
                         client_->socket().remote_endpoint().address().to_string() + ":" +
                         std::to_string(client_->socket().remote_endpoint().port()) + "] ",
                 Log::Level::INFO);
+        client_->socket().close();
+        return;
+    }
+}
 
+void AgentHandler::continueRead() {
+    FUCK("AgentHandler::continueRead");
+    std::lock_guard<std::mutex> lock(mutex_);
+    client_->doRead();
+    if (client_->readBuffer().size() > 0) {
+        if (request_->httpType() != HTTP::HttpType::connect) {
+            HTTP::pointer response =
+                    HTTP::create(config_, log_, client_->readBuffer(), uuid_);
+            if (response->parseHttpResp()) {
+                log_->write(
+                        "[" + to_string(uuid_) + "] [AgentHandler handle] [Response] : " + response->restoString(),
+                        Log::Level::DEBUG);
+                BoolStr decryption{false, std::string("FAILED")};
+                decryption =
+                        aes256Decrypt(decode64(boost::lexical_cast<std::string>(
+                                              response->parsedHttpResponse().body())),
+                                      config_->agent().token);
+                if (boost::lexical_cast<std::string>(response->parsedHttpResponse()[config_->general().chunkHeader]) == "yes") {
+                    FUCK("AgentHandler continueRead END");
+                    end_ = true;
+                }
+                if (decryption.ok) {
+                    copyStringToStreambuf(decryption.message, writeBuffer_);
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Done]", Log::Level::DEBUG);
+                } else {
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : [ " +
+                                        decryption.message + "] ",
+                                Log::Level::DEBUG);
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : " +
+                                        request_->toString(),
+                                Log::Level::INFO);
+                    client_->socket().close();
+                }
+            } else {
+                log_->write(
+                        "[AgentHandler handle] [NOT HTTP Response] "
+                        "[Response] : " +
+                                streambufToString(client_->readBuffer()),
+                        Log::Level::DEBUG);
+            }
+        } else {
+            log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Response to connect] : \n" +
+                                streambufToString(client_->readBuffer()),
+                        Log::Level::DEBUG);
+            moveStreambuf(client_->readBuffer(), writeBuffer_);
+        }
+    } else {
         client_->socket().close();
         return;
     }
diff --git a/core/src/agenthandler.hpp b/core/src/agenthandler.hpp
index 4812025..becbd8d 100644
--- a/core/src/agenthandler.hpp
+++ b/core/src/agenthandler.hpp
@@ -28,11 +28,14 @@ class AgentHandler : private Uncopyable {
     ~AgentHandler();
 
     void handle();
+    void continueRead();
 
     inline const HTTP::pointer &request() & { return request_; }
 
     inline const HTTP::pointer &&request() && { return std::move(request_); }
 
+    bool end_;
+
 private:
     AgentHandler(boost::asio::streambuf &readBuffer,
                  boost::asio::streambuf &writeBuffer,
diff --git a/core/src/config.cpp b/core/src/config.cpp
index 2ce7705..769bf17 100644
--- a/core/src/config.cpp
+++ b/core/src/config.cpp
@@ -12,6 +12,7 @@ Config::Config(const RunMode &mode, const std::string &filePath)
                 configYaml_["general"]["timeWait"].as<unsigned int>(),
                 configYaml_["general"]["timeout"].as<unsigned short>(),
                 configYaml_["general"]["repeatWait"].as<unsigned short>(),
+                configYaml_["general"]["chunkHeader"].as<std::string>(),
                 configYaml_["general"]["chunkSize"].as<unsigned short>()}),
       log_({configYaml_["log"]["logLevel"].as<std::string>(),
             configYaml_["log"]["logFile"].as<std::string>()}),
@@ -63,6 +64,7 @@ std::string Config::toString() const {
        << "   timeWait: " << general_.timeWait << "\n"
        << "   timeout: " << general_.timeout << "\n"
        << "   repeatWait: " << general_.repeatWait << "\n"
+       << "   chunkHeader: " << general_.chunkHeader << "\n"
        << "   chunkSize: " << general_.chunkSize << "\n"
        << " Log :\n"
        << "   logLevel: " << log_.level << "\n"
diff --git a/core/src/config.hpp b/core/src/config.hpp
index 7d1e8c6..cf6ba97 100644
--- a/core/src/config.hpp
+++ b/core/src/config.hpp
@@ -19,6 +19,7 @@ class Config : private Uncopyable {
         unsigned int timeWait;
         unsigned short timeout;
         unsigned short repeatWait;
+        std::string chunkHeader;
         unsigned short chunkSize;
     };
 
diff --git a/core/src/general.hpp b/core/src/general.hpp
index 8aa59d8..ab6b820 100644
--- a/core/src/general.hpp
+++ b/core/src/general.hpp
@@ -315,6 +315,7 @@ inline BoolStr validateConfig(int argc, const char *argv[]) {
         configYaml["general"]["timeWait"].as<unsigned int>();
         configYaml["general"]["timeout"].as<unsigned short>();
         configYaml["general"]["repeatWait"].as<unsigned short>();
+        configYaml["general"]["chunkHeader"].as<std::string>();
         configYaml["general"]["chunkSize"].as<unsigned short>();
     } catch (const std::exception &e) {
         result.message = std::string("Error in 'general' block: ") + e.what() + "\n";
diff --git a/core/src/http.cpp b/core/src/http.cpp
index f736018..676309b 100644
--- a/core/src/http.cpp
+++ b/core/src/http.cpp
@@ -8,7 +8,9 @@ HTTP::HTTP(const std::shared_ptr<Config> &config,
       parsedHttpRequest_(),
       httpType_(HTTP::HttpType::https),
       parsedTlsRequest_{"", "", TlsTypes::TLSHandshake},
-      uuid_(uuid) {}
+      uuid_(uuid) {
+    chunkHeader_ = "no";
+}
 
 HTTP::HTTP(const HTTP &http)
     : config_(http.config_),
@@ -16,7 +18,9 @@ HTTP::HTTP(const HTTP &http)
       buffer_(http.buffer_),
       parsedHttpRequest_(http.parsedHttpRequest_),
       parsedTlsRequest_(http.parsedTlsRequest_),
-      uuid_(http.uuid_) {}
+      uuid_(http.uuid_) {
+    chunkHeader_ = "no";
+}
 
 HTTP::~HTTP() {}
 
@@ -138,10 +142,21 @@ const std::string HTTP::genHttpPostReqString(const std::string &body) const {
            "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + body;
 }
 
+const std::string HTTP::genHttpRestPostReqString() const {
+    return std::string(config_->general().method + " " +
+                       config_->general().fakeUrl + " HTTP/" +
+                       config_->agent().httpVersion + "\r\n") +
+           "Host: " + config_->general().fakeUrl + "\r\n" +
+           "User-Agent: " + config_->agent().userAgent + "\r\n" +
+           "Accept: */*\r\n" + "Connection: keep-alive\r\n" +
+           "Rest: yes\r\n";
+}
+
 const std::string HTTP::genHttpOkResString(const std::string &body) const {
     return std::string("HTTP/1.1 200 OK\r\n") +
            "Content-Type: application/x-www-form-urlencoded\r\n" +
            "Content-Length: " + std::to_string(body.length()) + "\r\n" +
+           config_->general().chunkHeader + ": " + chunkHeader_ + "\r\n" +
            "Connection: keep-alive\r\n" + "Cache-Control: no-cache\r\n" +
            "Pragma: no-cache\r\n" + "\r\n" + body;
 }
diff --git a/core/src/http.hpp b/core/src/http.hpp
index 30402a9..c165879 100644
--- a/core/src/http.hpp
+++ b/core/src/http.hpp
@@ -52,6 +52,8 @@ class HTTP {
 
     const std::string genHttpPostReqString(const std::string &body) const;
 
+    const std::string genHttpRestPostReqString() const;
+
     const std::string genHttpOkResString(const std::string &body) const;
 
     inline const boost::beast::http::request<boost::beast::http::string_body> &
@@ -76,6 +78,7 @@ class HTTP {
 
     const std::string toString() const;
     const std::string restoString() const;
+    std::string chunkHeader_;
 
 private:
     explicit HTTP(const std::shared_ptr<Config> &config,
diff --git a/core/src/serverhandler.cpp b/core/src/serverhandler.cpp
index f70ccbf..a1d097c 100644
--- a/core/src/serverhandler.cpp
+++ b/core/src/serverhandler.cpp
@@ -14,28 +14,22 @@ ServerHandler::ServerHandler(boost::asio::streambuf &readBuffer,
       writeBuffer_(writeBuffer),
       request_(HTTP::create(config, log, readBuffer, uuid)),
       clientConnStr_(clientConnStr),
-      uuid_(uuid) {}
+      uuid_(uuid) { end_ = false; }
 
 ServerHandler::~ServerHandler() {}
 
 void ServerHandler::handle() {
     std::lock_guard<std::mutex> lock(mutex_);
-
-
     if (request_->detectType()) {
-
         log_->write(
                 "[" + to_string(uuid_) + "] [ServerHandler handle] [Request From Agent] : " + request_->toString(),
                 Log::Level::DEBUG);
-
-
         BoolStr decryption{false, std::string("FAILED")};
         decryption = aes256Decrypt(decode64(boost::lexical_cast<std::string>(
                                            request_->parsedHttpRequest().body())),
                                    config_->agent().token);
 
         if (decryption.ok) {
-
             log_->write(
                     "[" + to_string(uuid_) + "] [ServerHandler handle] [Token Valid] : " + request_->toString(),
                     Log::Level::DEBUG);
@@ -43,14 +37,13 @@ void ServerHandler::handle() {
             std::string tempHexArrStr(tempHexArr.begin(), tempHexArr.end());
             copyStringToStreambuf(tempHexArrStr, readBuffer_);
 
-
             if (request_->detectType()) {
                 log_->write(
                         "[" + to_string(uuid_) + "] [ServerHandler handle] [Request] : " + request_->toString(),
                         Log::Level::DEBUG);
                 switch (request_->httpType()) {
                     case HTTP::HttpType::connect: {
-
+                        end_ = true;
                         boost::asio::streambuf tempBuff;
                         std::iostream os(&tempBuff);
                         if (client_->doConnect(request_->dstIP(), request_->dstPort())) {
@@ -77,7 +70,6 @@ void ServerHandler::handle() {
                     } break;
                     case HTTP::HttpType::http:
                     case HTTP::HttpType::https: {
-
                         if (request_->httpType() == HTTP::HttpType::http) {
                             if (client_->doConnect(request_->dstIP(), request_->dstPort())) {
                                 log_->write("[" + to_string(uuid_) + "] [CONNECT] [SRC " + clientConnStr_ + "] [DST " +
@@ -97,13 +89,17 @@ void ServerHandler::handle() {
                         }
                         client_->doWrite(readBuffer_);
                         client_->doRead();
+                        end_ = client_->end_;
                         if (client_->readBuffer().size() > 0) {
-
                             BoolStr encryption{false, std::string("FAILED")};
                             encryption =
                                     aes256Encrypt(streambufToString(client_->readBuffer()),
                                                   config_->agent().token);
                             if (encryption.ok) {
+                                if (end_) {
+                                    FUCK("serverHandler END");
+                                    request_->chunkHeader_ = "yes";
+                                }
                                 std::string newRes(
                                         request_->genHttpOkResString(encode64(encryption.message)));
                                 copyStringToStreambuf(newRes, writeBuffer_);
@@ -116,12 +112,11 @@ void ServerHandler::handle() {
                                     }
                                 }
                             } else {
-
                                 log_->write(
                                         "[" + to_string(uuid_) +
                                                 "] [ServerHandler handle] [Encryption "
                                                 "Failed] : [ " +
-                                                decryption.message + "] ",
+                                                encryption.message + "] ",
                                         Log::Level::DEBUG);
                                 log_->write("[" + to_string(uuid_) + "] [ServerHandler handle] [Encryption Failed] : " +
                                                     request_->toString(),
@@ -129,14 +124,12 @@ void ServerHandler::handle() {
                                 client_->socket().close();
                             }
                         } else {
-
                             client_->socket().close();
                             return;
                         }
                     } break;
                 }
             } else {
-
                 log_->write("[" + to_string(uuid_) + "] [ServerHandler handle] [NOT HTTP Request] [Request] : " +
                                     streambufToString(readBuffer_),
                             Log::Level::DEBUG);
@@ -145,7 +138,6 @@ void ServerHandler::handle() {
                 return;
             }
         } else {
-
             log_->write("[" + to_string(uuid_) + "] [ServerHandler handle] [Decryption Failed] : [ " +
                                 decryption.message + "] ",
                         Log::Level::DEBUG);
@@ -157,7 +149,6 @@ void ServerHandler::handle() {
             return;
         }
     } else {
-
         log_->write(
                 "[" + to_string(uuid_) + "] [ServerHandler handle] [NOT HTTP Request From Agent] [Request] : " +
                         streambufToString(readBuffer_),
@@ -167,3 +158,47 @@ void ServerHandler::handle() {
         return;
     }
 }
+
+void ServerHandler::continueRead() {
+    FUCK("ServerHandler::continueRead");
+    std::lock_guard<std::mutex> lock(mutex_);
+    client_->doRead();
+    end_ = client_->end_;
+    if (client_->readBuffer().size() > 0) {
+        BoolStr encryption{false, std::string("FAILED")};
+        encryption =
+                aes256Encrypt(streambufToString(client_->readBuffer()),
+                              config_->agent().token);
+        if (encryption.ok) {
+            if (end_) {
+                FUCK("serverHandler continueRead END");
+                request_->chunkHeader_ = "yes";
+            }
+            std::string newRes(
+                    request_->genHttpOkResString(encode64(encryption.message)));
+            copyStringToStreambuf(newRes, writeBuffer_);
+            if (request_->httpType() == HTTP::HttpType::http) {
+                client_->socket().close();
+            } else {
+                if (request_->parsedTlsRequest().type ==
+                    HTTP::TlsTypes::ApplicationData) {
+                    client_->socket().close();
+                }
+            }
+        } else {
+            log_->write(
+                    "[" + to_string(uuid_) +
+                            "] [ServerHandler handle] [Encryption "
+                            "Failed] : [ " +
+                            encryption.message + "] ",
+                    Log::Level::DEBUG);
+            log_->write("[" + to_string(uuid_) + "] [ServerHandler handle] [Encryption Failed] : " +
+                                request_->toString(),
+                        Log::Level::INFO);
+            client_->socket().close();
+        }
+    } else {
+        client_->socket().close();
+        return;
+    }
+}
\ No newline at end of file
diff --git a/core/src/serverhandler.hpp b/core/src/serverhandler.hpp
index 9e94626..d3363ab 100644
--- a/core/src/serverhandler.hpp
+++ b/core/src/serverhandler.hpp
@@ -28,10 +28,12 @@ class ServerHandler : private Uncopyable {
     ~ServerHandler();
 
     void handle();
+    void continueRead();
 
     inline const HTTP::pointer &request() & { return request_; }
 
     inline const HTTP::pointer &&request() && { return std::move(request_); }
+    bool end_;
 
 private:
     explicit ServerHandler(boost::asio::streambuf &readBuffer,
@@ -51,8 +53,6 @@ class ServerHandler : private Uncopyable {
     HTTP::pointer request_;
     const std::string
             &clientConnStr_;
-
     boost::uuids::uuid uuid_;
-
     std::mutex mutex_;
 };
diff --git a/core/src/tcpclient.cpp b/core/src/tcpclient.cpp
index 06f71c3..f42610c 100644
--- a/core/src/tcpclient.cpp
+++ b/core/src/tcpclient.cpp
@@ -10,7 +10,9 @@ TCPClient::TCPClient(boost::asio::io_context &io_context,
       io_context_(io_context),
       socket_(io_context),
       resolver_(io_context),
-      timeout_(io_context) {}
+      timeout_(io_context) {
+    end_ = false;
+}
 
 boost::asio::ip::tcp::socket &TCPClient::socket() {
     std::lock_guard<std::mutex> lock(mutex_);
@@ -26,12 +28,10 @@ bool TCPClient::doConnect(const std::string &dstIP,
                           const unsigned short &dstPort) {
     std::lock_guard<std::mutex> lock(mutex_);
     try {
-
         log_->write("[" + to_string(uuid_) + "] [TCPClient doConnect] [DST " + dstIP + ":" +
                             std::to_string(dstPort) + "]",
                     Log::Level::DEBUG);
 
-
         boost::system::error_code error_code;
         auto endpoint = resolver_.resolve(dstIP.c_str(), std::to_string(dstPort).c_str(), error_code);
         if (error_code) {
@@ -93,8 +93,13 @@ void TCPClient::doWrite(boost::asio::streambuf &buffer) {
 }
 
 void TCPClient::doRead() {
+    FUCK("TCPClient::doRead");
+    end_ = false;
     std::lock_guard<std::mutex> lock(mutex_);
     try {
+        unsigned short headerSize{0};
+        if (config_->runMode() == RunMode::agent)
+            headerSize = 512;
 
         readBuffer_.consume(readBuffer_.size());
         boost::system::error_code error;
@@ -113,6 +118,9 @@ void TCPClient::doRead() {
                     socketShutdown();
                     return;
                 }
+                if (readBuffer_.size() >= config_->general().chunkSize + headerSize) {
+                    break;
+                }
                 if (socket_.available() == 0) break;
                 resetTimeout();
                 boost::asio::read(socket_, readBuffer_,
@@ -133,6 +141,18 @@ void TCPClient::doRead() {
             }
             timer.expires_after(std::chrono::milliseconds(config_->general().timeWait));
             timer.wait();
+            if (readBuffer_.size() >= config_->general().chunkSize + headerSize) {
+                FUCK(readBuffer_.size());
+                FUCK("CHUNK END");
+                break;
+            }
+        }
+
+        FUCK(readBuffer_.size());
+
+        if (socket_.available() == 0) {
+            FUCK("TCPClient END");
+            end_ = true;
         }
 
         if (readBuffer_.size() > 0) {
diff --git a/core/src/tcpclient.hpp b/core/src/tcpclient.hpp
index 9773bbd..bd6a1b8 100644
--- a/core/src/tcpclient.hpp
+++ b/core/src/tcpclient.hpp
@@ -14,50 +14,35 @@
 class TCPClient : public boost::enable_shared_from_this<TCPClient> {
 public:
     using pointer = boost::shared_ptr<TCPClient>;
-
     static pointer create(boost::asio::io_context &io_context,
                           const std::shared_ptr<Config> &config,
                           const std::shared_ptr<Log> &log) {
         return pointer(new TCPClient(io_context, config, log));
     }
-
     boost::asio::ip::tcp::socket &socket();
-
     void writeBuffer(boost::asio::streambuf &buffer);
-
     inline boost::asio::streambuf &writeBuffer() & { return writeBuffer_; }
     inline boost::asio::streambuf &&writeBuffer() && {
         return std::move(writeBuffer_);
     }
-
     inline boost::asio::streambuf &readBuffer() & { return readBuffer_; }
     inline boost::asio::streambuf &&readBuffer() && {
         return std::move(readBuffer_);
     }
-
     bool doConnect(const std::string &dstIP, const unsigned short &dstPort);
-
     void doWrite(boost::asio::streambuf &buffer);
-
     void doRead();
-
     void socketShutdown();
-
     boost::uuids::uuid uuid_;
+    bool end_;
 
 private:
     explicit TCPClient(boost::asio::io_context &io_context,
                        const std::shared_ptr<Config> &config,
                        const std::shared_ptr<Log> &log);
-
-
     void resetTimeout();
-
     void cancelTimeout();
-
     void onTimeout(const boost::system::error_code &error);
-
-
     const std::shared_ptr<Config>
             &config_;
     const std::shared_ptr<Log> &log_;
@@ -67,7 +52,5 @@ class TCPClient : public boost::enable_shared_from_this<TCPClient> {
     boost::asio::streambuf readBuffer_;
     boost::asio::ip::tcp::resolver resolver_;
     boost::asio::deadline_timer timeout_;
-
-
     mutable std::mutex mutex_;
 };
diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index 0486460..7b9faa9 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -12,6 +12,7 @@ TCPConnection::TCPConnection(boost::asio::io_context &io_context,
       timeout_(io_context),
       strand_(boost::asio::make_strand(io_context_)) {
     uuid_ = boost::uuids::random_generator()();
+    end_ = false;
 }
 
 boost::asio::ip::tcp::socket &TCPConnection::socket() {
@@ -113,6 +114,12 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
                                 std::to_string(socket_.remote_endpoint().port()),
                         uuid_);
                 agentHandler_->handle();
+                end_ = agentHandler_->end_;
+                if (writeBuffer_.size() > 0) {
+                    doWrite(agentHandler_);
+                } else {
+                    socketShutdown();
+                }
             } else if (config_->runMode() == RunMode::server) {
                 ServerHandler::pointer serverHandler_ = ServerHandler::create(
                         readBuffer_, writeBuffer_, config_, log_, client_,
@@ -120,12 +127,12 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
                                 std::to_string(socket_.remote_endpoint().port()),
                         uuid_);
                 serverHandler_->handle();
-            }
-
-            if (writeBuffer_.size() > 0) {
-                doWrite();
-            } else {
-                socketShutdown();
+                end_ = serverHandler_->end_;
+                if (writeBuffer_.size() > 0) {
+                    doWrite(serverHandler_);
+                } else {
+                    socketShutdown();
+                }
             }
         }
     } catch (std::exception &error) {
@@ -136,7 +143,8 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
     }
 }
 
-void TCPConnection::doWrite() {
+void TCPConnection::doWrite(auto handlerPointer) {
+    boost::system::error_code error;
     std::lock_guard<std::mutex> lock(mutex_);
     try {
         log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [DST " +
@@ -145,11 +153,20 @@ void TCPConnection::doWrite() {
                             "] [Bytes " + std::to_string(writeBuffer_.size()) + "] ",
                     Log::Level::DEBUG);
         resetTimeout();
-        boost::asio::async_write(socket_, writeBuffer_,
-                                 boost::asio::bind_executor(strand_,
-                                                            [self = shared_from_this()](const boost::system::error_code &error, std::size_t /*bytes_transferred*/) {
-                                                                self->handleWrite(error);
-                                                            }));
+        boost::asio::write(socket_, writeBuffer_, error);
+        cancelTimeout();
+        if (!error) {
+            if (end_) {
+                FUCK("tcpconnection END");
+                doRead();
+            } else {
+                handlerPointer->continueRead();
+            }
+        } else {
+            log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [error] " + error.message(),
+                        Log::Level::ERROR);
+            socketShutdown();
+        }
     } catch (std::exception &error) {
         log_->write(
                 std::string("[" + to_string(uuid_) + "] [TCPConnection doWrite] [catch] ") + error.what(),
@@ -158,17 +175,6 @@ void TCPConnection::doWrite() {
     }
 }
 
-void TCPConnection::handleWrite(const boost::system::error_code &error) {
-    cancelTimeout();
-    if (!error) {
-        doRead();
-    } else {
-        log_->write("[" + to_string(uuid_) + "] [TCPConnection handleWrite] [error] " + error.message(),
-                    Log::Level::ERROR);
-        socketShutdown();
-    }
-}
-
 void TCPConnection::resetTimeout() {
     if (!config_->general().timeout)
         return;
diff --git a/core/src/tcpconnection.hpp b/core/src/tcpconnection.hpp
index b7350cf..a3f3ff1 100644
--- a/core/src/tcpconnection.hpp
+++ b/core/src/tcpconnection.hpp
@@ -39,9 +39,10 @@ class TCPConnection : public boost::enable_shared_from_this<TCPConnection> {
     void doRead();
     void handleRead(const boost::system::error_code &error,
                     size_t bytes_transferred);
+    void doWrite(auto handlerPointer);
     void doWrite();
-    void handleWrite(const boost::system::error_code &error);
     void socketShutdown();
+    bool end_;
 
 private:
     explicit TCPConnection(boost::asio::io_context &io_context,
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index cdcb61d..d39429d 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -13,14 +13,17 @@ general:
   # timeout: unsigned short
   # Defines the timeout for I/O Operation in seconds. 0 indicates no timeout.
   #   Useful to automatically close stalled connections.
-  timeout: 5
+  timeout: 500
   # repeatWait: unsigned short(1-65,635)
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
   repeatWait: 10
-  # chunkSize: unsigned short(1-65,635)
+  # chunkHeader: String
+  # Defines the chunk header that you want to inform Agent/Server if it is end or not.
+  chunkHeader: "END"
+  # chunkSize: unsigned short(512-65,635)
   # Defines the chunk size that you want to read from socket.
-  chunkSize: 512
+  chunkSize: 5120
 
 # This block is to define log directives
 log:

From c0aed5adce4a081eae77fb59903c16816775e8ca Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Wed, 9 Oct 2024 12:38:07 +0200
Subject: [PATCH 05/11] chunk done till end of handshake

---
 core/src/agenthandler.cpp       |  26 +++++---
 core/src/agenthandler.hpp       |   2 +-
 core/src/serverhandler.cpp      |  11 +--
 core/src/serverhandler.hpp      |   2 +-
 core/src/tcpclient.cpp          |   7 +-
 core/src/tcpconnection.cpp      | 115 +++++++++++++++++++++++++++-----
 core/src/tcpconnection.hpp      |   6 +-
 nipovpn/etc/nipovpn/config.yaml |   4 +-
 8 files changed, 126 insertions(+), 47 deletions(-)

diff --git a/core/src/agenthandler.cpp b/core/src/agenthandler.cpp
index 643592c..62a5e2c 100644
--- a/core/src/agenthandler.cpp
+++ b/core/src/agenthandler.cpp
@@ -15,8 +15,8 @@ AgentHandler::AgentHandler(boost::asio::streambuf &readBuffer,
       request_(HTTP::create(config, log, readBuffer, uuid)),
       clientConnStr_(clientConnStr),
       uuid_(uuid) {
-    FUCK("TCPClient END");
     end_ = false;
+    connect_ = false;
 }
 
 AgentHandler::~AgentHandler() {}
@@ -47,6 +47,7 @@ void AgentHandler::handle() {
             if (!client_->socket().is_open() ||
                 request_->httpType() == HTTP::HttpType::http ||
                 request_->httpType() == HTTP::HttpType::connect) {
+                connect_ = true;
                 boost::system::error_code ec;
                 if (!client_->doConnect(config_->agent().serverIp,
                                         config_->agent().serverPort)) {
@@ -85,7 +86,6 @@ void AgentHandler::handle() {
                                                       response->parsedHttpResponse().body())),
                                               config_->agent().token);
                         if (boost::lexical_cast<std::string>(response->parsedHttpResponse()[config_->general().chunkHeader]) == "yes") {
-                            FUCK("AgentHandler END");
                             end_ = true;
                         }
                         if (decryption.ok) {
@@ -108,7 +108,7 @@ void AgentHandler::handle() {
                                 Log::Level::DEBUG);
                     }
                 } else {
-                    end_ = true;
+                    connect_ = true;
                     log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Response to connect] : \n" +
                                         streambufToString(client_->readBuffer()),
                                 Log::Level::DEBUG);
@@ -141,8 +141,12 @@ void AgentHandler::handle() {
 }
 
 void AgentHandler::continueRead() {
-    FUCK("AgentHandler::continueRead");
+    FUCK("gentHandler::continueRead()");
     std::lock_guard<std::mutex> lock(mutex_);
+    std::string newReq(
+            request_->genHttpRestPostReqString());
+    copyStringToStreambuf(newReq, readBuffer_);
+    client_->doWrite(readBuffer_);
     client_->doRead();
     if (client_->readBuffer().size() > 0) {
         if (request_->httpType() != HTTP::HttpType::connect) {
@@ -150,7 +154,7 @@ void AgentHandler::continueRead() {
                     HTTP::create(config_, log_, client_->readBuffer(), uuid_);
             if (response->parseHttpResp()) {
                 log_->write(
-                        "[" + to_string(uuid_) + "] [AgentHandler handle] [Response] : " + response->restoString(),
+                        "[" + to_string(uuid_) + "] [AgentHandler continueRead handle] [Response] : " + response->restoString(),
                         Log::Level::DEBUG);
                 BoolStr decryption{false, std::string("FAILED")};
                 decryption =
@@ -158,30 +162,30 @@ void AgentHandler::continueRead() {
                                               response->parsedHttpResponse().body())),
                                       config_->agent().token);
                 if (boost::lexical_cast<std::string>(response->parsedHttpResponse()[config_->general().chunkHeader]) == "yes") {
-                    FUCK("AgentHandler continueRead END");
                     end_ = true;
                 }
                 if (decryption.ok) {
                     copyStringToStreambuf(decryption.message, writeBuffer_);
-                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Done]", Log::Level::DEBUG);
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler continueRead handle] [Decryption Done]", Log::Level::DEBUG);
                 } else {
-                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : [ " +
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler continueRead handle] [Decryption Failed] : [ " +
                                         decryption.message + "] ",
                                 Log::Level::DEBUG);
-                    log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : " +
+                    log_->write("[" + to_string(uuid_) + "] [AgentHandler continueRead handle] [Decryption Failed] : " +
                                         request_->toString(),
                                 Log::Level::INFO);
                     client_->socket().close();
                 }
             } else {
                 log_->write(
-                        "[AgentHandler handle] [NOT HTTP Response] "
+                        "[AgentHandler continueRead handle] [NOT HTTP Response] "
                         "[Response] : " +
                                 streambufToString(client_->readBuffer()),
                         Log::Level::DEBUG);
             }
         } else {
-            log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Response to connect] : \n" +
+            connect_ = true;
+            log_->write("[" + to_string(uuid_) + "] [AgentHandler continueRead handle] [Response to connect] : \n" +
                                 streambufToString(client_->readBuffer()),
                         Log::Level::DEBUG);
             moveStreambuf(client_->readBuffer(), writeBuffer_);
diff --git a/core/src/agenthandler.hpp b/core/src/agenthandler.hpp
index becbd8d..578cb7a 100644
--- a/core/src/agenthandler.hpp
+++ b/core/src/agenthandler.hpp
@@ -34,7 +34,7 @@ class AgentHandler : private Uncopyable {
 
     inline const HTTP::pointer &&request() && { return std::move(request_); }
 
-    bool end_;
+    bool end_, connect_;
 
 private:
     AgentHandler(boost::asio::streambuf &readBuffer,
diff --git a/core/src/serverhandler.cpp b/core/src/serverhandler.cpp
index a1d097c..c099649 100644
--- a/core/src/serverhandler.cpp
+++ b/core/src/serverhandler.cpp
@@ -14,7 +14,10 @@ ServerHandler::ServerHandler(boost::asio::streambuf &readBuffer,
       writeBuffer_(writeBuffer),
       request_(HTTP::create(config, log, readBuffer, uuid)),
       clientConnStr_(clientConnStr),
-      uuid_(uuid) { end_ = false; }
+      uuid_(uuid) {
+    end_ = false;
+    connect_ = false;
+}
 
 ServerHandler::~ServerHandler() {}
 
@@ -43,7 +46,7 @@ void ServerHandler::handle() {
                         Log::Level::DEBUG);
                 switch (request_->httpType()) {
                     case HTTP::HttpType::connect: {
-                        end_ = true;
+                        connect_ = true;
                         boost::asio::streambuf tempBuff;
                         std::iostream os(&tempBuff);
                         if (client_->doConnect(request_->dstIP(), request_->dstPort())) {
@@ -97,7 +100,6 @@ void ServerHandler::handle() {
                                                   config_->agent().token);
                             if (encryption.ok) {
                                 if (end_) {
-                                    FUCK("serverHandler END");
                                     request_->chunkHeader_ = "yes";
                                 }
                                 std::string newRes(
@@ -160,7 +162,7 @@ void ServerHandler::handle() {
 }
 
 void ServerHandler::continueRead() {
-    FUCK("ServerHandler::continueRead");
+    FUCK("ServerHandler::continueRead()");
     std::lock_guard<std::mutex> lock(mutex_);
     client_->doRead();
     end_ = client_->end_;
@@ -171,7 +173,6 @@ void ServerHandler::continueRead() {
                               config_->agent().token);
         if (encryption.ok) {
             if (end_) {
-                FUCK("serverHandler continueRead END");
                 request_->chunkHeader_ = "yes";
             }
             std::string newRes(
diff --git a/core/src/serverhandler.hpp b/core/src/serverhandler.hpp
index d3363ab..847bacd 100644
--- a/core/src/serverhandler.hpp
+++ b/core/src/serverhandler.hpp
@@ -33,7 +33,7 @@ class ServerHandler : private Uncopyable {
     inline const HTTP::pointer &request() & { return request_; }
 
     inline const HTTP::pointer &&request() && { return std::move(request_); }
-    bool end_;
+    bool end_, connect_;
 
 private:
     explicit ServerHandler(boost::asio::streambuf &readBuffer,
diff --git a/core/src/tcpclient.cpp b/core/src/tcpclient.cpp
index f42610c..dd18145 100644
--- a/core/src/tcpclient.cpp
+++ b/core/src/tcpclient.cpp
@@ -93,7 +93,7 @@ void TCPClient::doWrite(boost::asio::streambuf &buffer) {
 }
 
 void TCPClient::doRead() {
-    FUCK("TCPClient::doRead");
+    FUCK("TCPClient::doRead()");
     end_ = false;
     std::lock_guard<std::mutex> lock(mutex_);
     try {
@@ -142,16 +142,11 @@ void TCPClient::doRead() {
             timer.expires_after(std::chrono::milliseconds(config_->general().timeWait));
             timer.wait();
             if (readBuffer_.size() >= config_->general().chunkSize + headerSize) {
-                FUCK(readBuffer_.size());
-                FUCK("CHUNK END");
                 break;
             }
         }
 
-        FUCK(readBuffer_.size());
-
         if (socket_.available() == 0) {
-            FUCK("TCPClient END");
             end_ = true;
         }
 
diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index 7b9faa9..ef9549c 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -13,6 +13,7 @@ TCPConnection::TCPConnection(boost::asio::io_context &io_context,
       strand_(boost::asio::make_strand(io_context_)) {
     uuid_ = boost::uuids::random_generator()();
     end_ = false;
+    connect_ = false;
 }
 
 boost::asio::ip::tcp::socket &TCPConnection::socket() {
@@ -28,18 +29,22 @@ void TCPConnection::start() {
 
 void TCPConnection::doRead() {
     try {
-        readBuffer_.consume(readBuffer_.size());
-        writeBuffer_.consume(writeBuffer_.size());
-        resetTimeout();
-        boost::asio::async_read(
-                socket_, readBuffer_, boost::asio::transfer_exactly(1),
-                boost::asio::bind_executor(
-                        strand_,
-                        boost::bind(&TCPConnection::handleRead, shared_from_this(),
-                                    boost::asio::placeholders::error,
-                                    boost::asio::placeholders::
-                                            bytes_transferred)));
-
+        if (!end_) {
+            readBuffer_.consume(readBuffer_.size());
+            writeBuffer_.consume(writeBuffer_.size());
+            resetTimeout();
+            boost::asio::async_read(
+                    socket_, readBuffer_, boost::asio::transfer_exactly(1),
+                    boost::asio::bind_executor(
+                            strand_,
+                            boost::bind(&TCPConnection::handleRead, shared_from_this(),
+                                        boost::asio::placeholders::error,
+                                        boost::asio::placeholders::
+                                                bytes_transferred)));
+        } else {
+            FUCK("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEND");
+            socketShutdown();
+        }
     } catch (std::exception &error) {
         log_->write(std::string("[" + to_string(uuid_) + "] [TCPConnection doRead] [catch] ") + error.what(),
                     Log::Level::ERROR);
@@ -49,9 +54,7 @@ void TCPConnection::doRead() {
 
 void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
     try {
-
         cancelTimeout();
-
         if (error) {
             if (error == boost::asio::error::eof) {
                 log_->write(
@@ -115,6 +118,7 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
                         uuid_);
                 agentHandler_->handle();
                 end_ = agentHandler_->end_;
+                connect_ = agentHandler_->connect_;
                 if (writeBuffer_.size() > 0) {
                     doWrite(agentHandler_);
                 } else {
@@ -128,6 +132,7 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
                         uuid_);
                 serverHandler_->handle();
                 end_ = serverHandler_->end_;
+                connect_ = serverHandler_->connect_;
                 if (writeBuffer_.size() > 0) {
                     doWrite(serverHandler_);
                 } else {
@@ -143,9 +148,81 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
     }
 }
 
+void TCPConnection::doReadRest() {
+    try {
+        FUCK("TCPConnection::doReadRest()");
+        readBuffer_.consume(readBuffer_.size());
+        boost::system::error_code error;
+        resetTimeout();
+
+        boost::asio::read(socket_, readBuffer_, boost::asio::transfer_at_least(1),
+                          error);
+        cancelTimeout();
+
+        boost::asio::steady_timer timer(io_context_);
+        for (auto i = 0; i <= config_->general().repeatWait; i++) {
+            while (true) {
+                if (!socket_.is_open()) {
+                    log_->write("[" + to_string(uuid_) + "] [TCPConnection doReadRest] Socket is not OPEN",
+                                Log::Level::DEBUG);
+                    socketShutdown();
+                    return;
+                }
+                if (socket_.available() == 0) break;
+                resetTimeout();
+                boost::asio::read(socket_, readBuffer_,
+                                  boost::asio::transfer_at_least(1), error);
+                cancelTimeout();
+                if (error == boost::asio::error::eof) {
+                    log_->write("[" + to_string(uuid_) + "] [TCPConnection doReadRest] [EOF] Connection closed by peer.",
+                                Log::Level::TRACE);
+                    socketShutdown();
+                    return;
+                } else if (error) {
+                    log_->write(
+                            std::string("[" + to_string(uuid_) + "] [TCPConnection doReadRest] [error] ") + error.message(),
+                            Log::Level::ERROR);
+                    socketShutdown();
+                    return;
+                }
+            }
+            timer.expires_after(std::chrono::milliseconds(config_->general().timeWait));
+            timer.wait();
+        }
+
+        if (readBuffer_.size() > 0) {
+            try {
+
+                log_->write("[" + to_string(uuid_) + "] [TCPConnection doReadRest] [SRC " +
+                                    socket_.remote_endpoint().address().to_string() + ":" +
+                                    std::to_string(socket_.remote_endpoint().port()) +
+                                    "] [Bytes " + std::to_string(readBuffer_.size()) + "] ",
+                            Log::Level::DEBUG);
+                log_->write("[" + to_string(uuid_) + "] [Read from] [SRC " +
+                                    socket_.remote_endpoint().address().to_string() + ":" +
+                                    std::to_string(socket_.remote_endpoint().port()) +
+                                    "] " + "[Bytes " + std::to_string(readBuffer_.size()) +
+                                    "] ",
+                            Log::Level::TRACE);
+            } catch (std::exception &error) {
+
+                log_->write(
+                        std::string("[" + to_string(uuid_) + "] [TCPConnection doReadRest] [catch log] ") + error.what(),
+                        Log::Level::DEBUG);
+            }
+        } else {
+            socketShutdown();
+            return;
+        }
+    } catch (std::exception &error) {
+        log_->write(std::string("[" + to_string(uuid_) + "] [TCPConnection doReadRest] [catch] ") + error.what(),
+                    Log::Level::ERROR);
+        socketShutdown();
+    }
+}
+
 void TCPConnection::doWrite(auto handlerPointer) {
     boost::system::error_code error;
-    std::lock_guard<std::mutex> lock(mutex_);
     try {
         log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [DST " +
                             socket_.remote_endpoint().address().to_string() + ":" +
@@ -156,11 +233,13 @@ void TCPConnection::doWrite(auto handlerPointer) {
         boost::asio::write(socket_, writeBuffer_, error);
         cancelTimeout();
         if (!error) {
-            if (end_) {
-                FUCK("tcpconnection END");
+            if (end_ || connect_) {
                 doRead();
             } else {
+                if (config_->runMode() == RunMode::server)
+                    doReadRest();
                 handlerPointer->continueRead();
+                doWrite(handlerPointer);
             }
         } else {
             log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [error] " + error.message(),
@@ -205,7 +284,7 @@ void TCPConnection::socketShutdown() {
         socket_.close();
     } catch (std::exception &error) {
         log_->write(
-                std::string("[" + to_string(uuid_) + "] [TCPClient socketShutdown] [catch] ") + error.what(),
+                std::string("[" + to_string(uuid_) + "] [TCPConnection socketShutdown] [catch] ") + error.what(),
                 Log::Level::DEBUG);
     }
 }
\ No newline at end of file
diff --git a/core/src/tcpconnection.hpp b/core/src/tcpconnection.hpp
index a3f3ff1..d26b67e 100644
--- a/core/src/tcpconnection.hpp
+++ b/core/src/tcpconnection.hpp
@@ -12,8 +12,7 @@
 class TCPConnection : public boost::enable_shared_from_this<TCPConnection> {
 public:
     using pointer =
-            boost::shared_ptr<TCPConnection>;// Define a type alias for a shared
-                                             // pointer to TCPConnection
+            boost::shared_ptr<TCPConnection>;
 
     static pointer create(boost::asio::io_context &io_context,
                           const std::shared_ptr<Config> &config,
@@ -39,10 +38,11 @@ class TCPConnection : public boost::enable_shared_from_this<TCPConnection> {
     void doRead();
     void handleRead(const boost::system::error_code &error,
                     size_t bytes_transferred);
+    void doReadRest();
     void doWrite(auto handlerPointer);
     void doWrite();
     void socketShutdown();
-    bool end_;
+    bool end_, connect_;
 
 private:
     explicit TCPConnection(boost::asio::io_context &io_context,
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index d39429d..1620c65 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -13,7 +13,7 @@ general:
   # timeout: unsigned short
   # Defines the timeout for I/O Operation in seconds. 0 indicates no timeout.
   #   Useful to automatically close stalled connections.
-  timeout: 500
+  timeout: 10
   # repeatWait: unsigned short(1-65,635)
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
@@ -23,7 +23,7 @@ general:
   chunkHeader: "END"
   # chunkSize: unsigned short(512-65,635)
   # Defines the chunk size that you want to read from socket.
-  chunkSize: 5120
+  chunkSize: 512
 
 # This block is to define log directives
 log:

From 432bc34e5b5fac09891314a00ad16d387501fc09 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Thu, 10 Oct 2024 11:07:11 +0200
Subject: [PATCH 06/11] single request done

---
 core/src/tcpconnection.cpp | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index ef9549c..91efa94 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -29,22 +29,17 @@ void TCPConnection::start() {
 
 void TCPConnection::doRead() {
     try {
-        if (!end_) {
-            readBuffer_.consume(readBuffer_.size());
-            writeBuffer_.consume(writeBuffer_.size());
-            resetTimeout();
-            boost::asio::async_read(
-                    socket_, readBuffer_, boost::asio::transfer_exactly(1),
-                    boost::asio::bind_executor(
-                            strand_,
-                            boost::bind(&TCPConnection::handleRead, shared_from_this(),
-                                        boost::asio::placeholders::error,
-                                        boost::asio::placeholders::
-                                                bytes_transferred)));
-        } else {
-            FUCK("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEND");
-            socketShutdown();
-        }
+        readBuffer_.consume(readBuffer_.size());
+        writeBuffer_.consume(writeBuffer_.size());
+        resetTimeout();
+        boost::asio::async_read(
+                socket_, readBuffer_, boost::asio::transfer_exactly(1),
+                boost::asio::bind_executor(
+                        strand_,
+                        boost::bind(&TCPConnection::handleRead, shared_from_this(),
+                                    boost::asio::placeholders::error,
+                                    boost::asio::placeholders::
+                                            bytes_transferred)));
     } catch (std::exception &error) {
         log_->write(std::string("[" + to_string(uuid_) + "] [TCPConnection doRead] [catch] ") + error.what(),
                     Log::Level::ERROR);
@@ -239,6 +234,7 @@ void TCPConnection::doWrite(auto handlerPointer) {
                 if (config_->runMode() == RunMode::server)
                     doReadRest();
                 handlerPointer->continueRead();
+                end_ = handlerPointer->end_;
                 doWrite(handlerPointer);
             }
         } else {

From 47ddd936cbe14a4f0332c6ae7c5bc4a1854b1ce9 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Sun, 13 Oct 2024 17:00:33 +0200
Subject: [PATCH 07/11] fix agent read, no need to read chunk by chunk in agent
 from server

---
 core/src/agenthandler.cpp       |  1 -
 core/src/serverhandler.cpp      |  1 -
 core/src/tcpclient.cpp          | 11 +++------
 core/src/tcpconnection.cpp      | 40 ++++++++++++++++++---------------
 nipovpn/etc/nipovpn/config.yaml |  4 ++--
 5 files changed, 27 insertions(+), 30 deletions(-)

diff --git a/core/src/agenthandler.cpp b/core/src/agenthandler.cpp
index 62a5e2c..8c6572f 100644
--- a/core/src/agenthandler.cpp
+++ b/core/src/agenthandler.cpp
@@ -141,7 +141,6 @@ void AgentHandler::handle() {
 }
 
 void AgentHandler::continueRead() {
-    FUCK("gentHandler::continueRead()");
     std::lock_guard<std::mutex> lock(mutex_);
     std::string newReq(
             request_->genHttpRestPostReqString());
diff --git a/core/src/serverhandler.cpp b/core/src/serverhandler.cpp
index c099649..c31474c 100644
--- a/core/src/serverhandler.cpp
+++ b/core/src/serverhandler.cpp
@@ -162,7 +162,6 @@ void ServerHandler::handle() {
 }
 
 void ServerHandler::continueRead() {
-    FUCK("ServerHandler::continueRead()");
     std::lock_guard<std::mutex> lock(mutex_);
     client_->doRead();
     end_ = client_->end_;
diff --git a/core/src/tcpclient.cpp b/core/src/tcpclient.cpp
index dd18145..9c360e1 100644
--- a/core/src/tcpclient.cpp
+++ b/core/src/tcpclient.cpp
@@ -93,14 +93,9 @@ void TCPClient::doWrite(boost::asio::streambuf &buffer) {
 }
 
 void TCPClient::doRead() {
-    FUCK("TCPClient::doRead()");
     end_ = false;
     std::lock_guard<std::mutex> lock(mutex_);
     try {
-        unsigned short headerSize{0};
-        if (config_->runMode() == RunMode::agent)
-            headerSize = 512;
-
         readBuffer_.consume(readBuffer_.size());
         boost::system::error_code error;
         resetTimeout();
@@ -118,7 +113,7 @@ void TCPClient::doRead() {
                     socketShutdown();
                     return;
                 }
-                if (readBuffer_.size() >= config_->general().chunkSize + headerSize) {
+                if (config_->runMode() == RunMode::server && readBuffer_.size() >= config_->general().chunkSize) {
                     break;
                 }
                 if (socket_.available() == 0) break;
@@ -141,12 +136,12 @@ void TCPClient::doRead() {
             }
             timer.expires_after(std::chrono::milliseconds(config_->general().timeWait));
             timer.wait();
-            if (readBuffer_.size() >= config_->general().chunkSize + headerSize) {
+            if (config_->runMode() == RunMode::server && readBuffer_.size() >= config_->general().chunkSize) {
                 break;
             }
         }
 
-        if (socket_.available() == 0) {
+        if (config_->runMode() == RunMode::server && socket_.available() == 0) {
             end_ = true;
         }
 
diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index 91efa94..99814d1 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -145,7 +145,6 @@ void TCPConnection::handleRead(const boost::system::error_code &error, size_t) {
 
 void TCPConnection::doReadRest() {
     try {
-        FUCK("TCPConnection::doReadRest()");
         readBuffer_.consume(readBuffer_.size());
         boost::system::error_code error;
         resetTimeout();
@@ -219,28 +218,33 @@ void TCPConnection::doReadRest() {
 void TCPConnection::doWrite(auto handlerPointer) {
     boost::system::error_code error;
     try {
-        log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [DST " +
-                            socket_.remote_endpoint().address().to_string() + ":" +
-                            std::to_string(socket_.remote_endpoint().port()) +
-                            "] [Bytes " + std::to_string(writeBuffer_.size()) + "] ",
-                    Log::Level::DEBUG);
         resetTimeout();
-        boost::asio::write(socket_, writeBuffer_, error);
-        cancelTimeout();
-        if (!error) {
-            if (end_ || connect_) {
-                doRead();
+        if (writeBuffer_.size() > 0) {
+            log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [DST " +
+                                socket_.remote_endpoint().address().to_string() + ":" +
+                                std::to_string(socket_.remote_endpoint().port()) +
+                                "] [Bytes " + std::to_string(writeBuffer_.size()) + "] ",
+                        Log::Level::DEBUG);
+            boost::asio::write(socket_, writeBuffer_, error);
+            cancelTimeout();
+            if (!error) {
+                if (end_ || connect_) {
+                    doRead();
+                } else {
+                    if (config_->runMode() == RunMode::server)
+                        doReadRest();
+                    handlerPointer->continueRead();
+                    end_ = handlerPointer->end_;
+                    doWrite(handlerPointer);
+                }
             } else {
-                if (config_->runMode() == RunMode::server)
-                    doReadRest();
-                handlerPointer->continueRead();
-                end_ = handlerPointer->end_;
-                doWrite(handlerPointer);
+                log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [error] " + error.message(),
+                            Log::Level::ERROR);
+                socketShutdown();
             }
         } else {
-            log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [error] " + error.message(),
-                        Log::Level::ERROR);
             socketShutdown();
+            return;
         }
     } catch (std::exception &error) {
         log_->write(
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index 1620c65..a8a926b 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -13,7 +13,7 @@ general:
   # timeout: unsigned short
   # Defines the timeout for I/O Operation in seconds. 0 indicates no timeout.
   #   Useful to automatically close stalled connections.
-  timeout: 10
+  timeout: 0
   # repeatWait: unsigned short(1-65,635)
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
@@ -23,7 +23,7 @@ general:
   chunkHeader: "END"
   # chunkSize: unsigned short(512-65,635)
   # Defines the chunk size that you want to read from socket.
-  chunkSize: 512
+  chunkSize: 1024
 
 # This block is to define log directives
 log:

From 3c27e562ce8f15cd6ffefa92b72fbf3129f8f1ff Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Sun, 13 Oct 2024 17:22:34 +0200
Subject: [PATCH 08/11] add \r\n to end of http responses

---
 core/src/http.cpp               | 4 ++--
 nipovpn/etc/nipovpn/config.yaml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/src/http.cpp b/core/src/http.cpp
index 676309b..e4c9d5c 100644
--- a/core/src/http.cpp
+++ b/core/src/http.cpp
@@ -139,7 +139,7 @@ const std::string HTTP::genHttpPostReqString(const std::string &body) const {
            "User-Agent: " + config_->agent().userAgent + "\r\n" +
            "Accept: */*\r\n" + "Connection: keep-alive\r\n" +
            "Content-Length: " + std::to_string(body.length()) + "\r\n" +
-           "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + body;
+           "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + body + "\r\n";
 }
 
 const std::string HTTP::genHttpRestPostReqString() const {
@@ -158,7 +158,7 @@ const std::string HTTP::genHttpOkResString(const std::string &body) const {
            "Content-Length: " + std::to_string(body.length()) + "\r\n" +
            config_->general().chunkHeader + ": " + chunkHeader_ + "\r\n" +
            "Connection: keep-alive\r\n" + "Cache-Control: no-cache\r\n" +
-           "Pragma: no-cache\r\n" + "\r\n" + body;
+           "Pragma: no-cache\r\n" + "\r\n" + body + "\r\n";
 }
 
 void HTTP::setIPPort() {
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index a8a926b..bee6ce7 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -23,7 +23,7 @@ general:
   chunkHeader: "END"
   # chunkSize: unsigned short(512-65,635)
   # Defines the chunk size that you want to read from socket.
-  chunkSize: 1024
+  chunkSize: 4096
 
 # This block is to define log directives
 log:

From 2f67f0b22194ca6e8c20d8e67094bf500dc44252 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Sun, 13 Oct 2024 17:31:51 +0200
Subject: [PATCH 09/11] add trace log to tcpconnection dowrite

---
 core/src/tcpconnection.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index 99814d1..bd4609a 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -225,6 +225,11 @@ void TCPConnection::doWrite(auto handlerPointer) {
                                 std::to_string(socket_.remote_endpoint().port()) +
                                 "] [Bytes " + std::to_string(writeBuffer_.size()) + "] ",
                         Log::Level::DEBUG);
+            log_->write("[" + to_string(uuid_) + "] [Write To] [DST " +
+                                socket_.remote_endpoint().address().to_string() + ":" +
+                                std::to_string(socket_.remote_endpoint().port()) +
+                                "] [Bytes " + std::to_string(writeBuffer_.size()) + "] ",
+                        Log::Level::TRACE);
             boost::asio::write(socket_, writeBuffer_, error);
             cancelTimeout();
             if (!error) {

From 22b1a71021398a7272fc76595b4334b078d523f5 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Sun, 13 Oct 2024 20:30:24 +0200
Subject: [PATCH 10/11] check socket status for error handling in tcpClient and
 tcpConnection

---
 core/src/tcpclient.cpp          | 12 ++++++------
 core/src/tcpconnection.cpp      |  5 +++++
 core/src/tcpconnection.hpp      |  1 -
 nipovpn/etc/nipovpn/config.yaml |  4 ++--
 4 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/core/src/tcpclient.cpp b/core/src/tcpclient.cpp
index 9c360e1..ed4557b 100644
--- a/core/src/tcpclient.cpp
+++ b/core/src/tcpclient.cpp
@@ -96,6 +96,12 @@ void TCPClient::doRead() {
     end_ = false;
     std::lock_guard<std::mutex> lock(mutex_);
     try {
+        if (!socket_.is_open()) {
+            log_->write("[" + to_string(uuid_) + "] [TCPClient doRead] Socket is not OPEN",
+                        Log::Level::DEBUG);
+            return;
+        }
+
         readBuffer_.consume(readBuffer_.size());
         boost::system::error_code error;
         resetTimeout();
@@ -107,12 +113,6 @@ void TCPClient::doRead() {
         boost::asio::steady_timer timer(io_context_);
         for (auto i = 0; i <= config_->general().repeatWait; i++) {
             while (true) {
-                if (!socket_.is_open()) {
-                    log_->write("[" + to_string(uuid_) + "] [TCPClient doRead] Socket is not OPEN",
-                                Log::Level::DEBUG);
-                    socketShutdown();
-                    return;
-                }
                 if (config_->runMode() == RunMode::server && readBuffer_.size() >= config_->general().chunkSize) {
                     break;
                 }
diff --git a/core/src/tcpconnection.cpp b/core/src/tcpconnection.cpp
index bd4609a..82ae39c 100644
--- a/core/src/tcpconnection.cpp
+++ b/core/src/tcpconnection.cpp
@@ -218,6 +218,11 @@ void TCPConnection::doReadRest() {
 void TCPConnection::doWrite(auto handlerPointer) {
     boost::system::error_code error;
     try {
+        if (!socket_.is_open()) {
+            log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] Socket is not OPEN",
+                        Log::Level::DEBUG);
+            return;
+        }
         resetTimeout();
         if (writeBuffer_.size() > 0) {
             log_->write("[" + to_string(uuid_) + "] [TCPConnection doWrite] [DST " +
diff --git a/core/src/tcpconnection.hpp b/core/src/tcpconnection.hpp
index d26b67e..11c9552 100644
--- a/core/src/tcpconnection.hpp
+++ b/core/src/tcpconnection.hpp
@@ -40,7 +40,6 @@ class TCPConnection : public boost::enable_shared_from_this<TCPConnection> {
                     size_t bytes_transferred);
     void doReadRest();
     void doWrite(auto handlerPointer);
-    void doWrite();
     void socketShutdown();
     bool end_, connect_;
 
diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index bee6ce7..949108b 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -13,7 +13,7 @@ general:
   # timeout: unsigned short
   # Defines the timeout for I/O Operation in seconds. 0 indicates no timeout.
   #   Useful to automatically close stalled connections.
-  timeout: 0
+  timeout: 10
   # repeatWait: unsigned short(1-65,635)
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
@@ -21,7 +21,7 @@ general:
   # chunkHeader: String
   # Defines the chunk header that you want to inform Agent/Server if it is end or not.
   chunkHeader: "END"
-  # chunkSize: unsigned short(512-65,635)
+  # chunkSize: unsigned short(512-65,535)
   # Defines the chunk size that you want to read from socket.
   chunkSize: 4096
 

From d8e5b559df3ee1681a53d350d46c53b3fe227d60 Mon Sep 17 00:00:00 2001
From: Morteza Bashsiz <morteza.bashsiz@gmail.com>
Date: Mon, 14 Oct 2024 10:06:04 +0200
Subject: [PATCH 11/11] change default config file

---
 nipovpn/etc/nipovpn/config.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/nipovpn/etc/nipovpn/config.yaml b/nipovpn/etc/nipovpn/config.yaml
index 949108b..38c5c0e 100644
--- a/nipovpn/etc/nipovpn/config.yaml
+++ b/nipovpn/etc/nipovpn/config.yaml
@@ -17,7 +17,7 @@ general:
   # repeatWait: unsigned short(1-65,635)
   # Defines the loop count which will try to repeat read from socket.
   #   Same as timeWait
-  repeatWait: 10
+  repeatWait: 3
   # chunkHeader: String
   # Defines the chunk header that you want to inform Agent/Server if it is end or not.
   chunkHeader: "END"
@@ -28,7 +28,7 @@ general:
 # This block is to define log directives
 log:
   # logLevel: "INFO|TRACE|DEBUG"
-  logLevel: "DEBUG"
+  logLevel: "TRACE"
   # logFile: "/var/log/nipo/nipo.log"
   #   Path of log file
   logFile: "/var/log/nipovpn/nipovpn.log"