Tranvick

ProxyServer

May 23rd, 2014
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.80 KB | None | 0 0
  1. #include <sys/socket.h>
  2. #include <sys/types.h>
  3. #include <sys/un.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <netdb.h>
  9. #include <arpa/inet.h>
  10. #include <stdexcept>
  11. #include <vector>
  12. #include <errno.h>
  13.  
  14. #include <iostream>
  15. #include <thread>
  16. #include <mutex>
  17. #include <chrono>
  18. #include <atomic>
  19. #include <memory>
  20. #include <vector>
  21. #include <list>
  22. #include <set>
  23. #include <cstdlib>
  24. #include <ctime>
  25. #include <string>
  26.  
  27.  
  28. typedef std::vector<char> Buffer;
  29.  
  30. void appendTo (Buffer *buffer, char *begin, size_t size) {
  31.     buffer->insert(buffer->end(), begin, begin + size);
  32. }
  33.  
  34. class OkOrException {
  35. private:
  36.     bool is_good_;
  37.     std::runtime_error exception_;
  38.  
  39. public:
  40.     OkOrException() :
  41.         is_good_(true),
  42.         exception_(std::runtime_error(""))
  43.         {}
  44.  
  45.     void setException(const std::runtime_error &exception) {
  46.         is_good_ = false;
  47.         exception_ = exception;
  48.     }
  49.  
  50.     void check() const {
  51.         if (!is_good_) {
  52.             throw exception_;
  53.         }
  54.     }
  55. };
  56.  
  57. typedef OkOrException Status;
  58.  
  59. struct InternetAddress {
  60. private:
  61.     std::string address_;
  62.     int port_;
  63.  
  64. public:
  65.     explicit InternetAddress(std::string address, int port) :
  66.         address_(address),
  67.         port_(port)
  68.         {}
  69.  
  70.     struct sockaddr getSocketAddress() const {
  71.         struct sockaddr_in address;
  72.         address.sin_family = AF_INET;
  73.         address.sin_port = htons(port_);
  74.         address.sin_addr.s_addr = inet_addr(address_.c_str());
  75.         memset(address.sin_zero, '\0', sizeof address.sin_zero);
  76.         return *((sockaddr *) &address);
  77.     }
  78.    
  79.     ~InternetAddress() {}
  80. };
  81.  
  82. class ConnectionSocket {
  83. private:
  84.     int connection_fd_;
  85.     Status status_;
  86.     bool have_resources_;
  87.     static constexpr int BUFFER_SIZE = 1024;
  88.  
  89. public:
  90.  
  91.     ConnectionSocket()
  92.         : have_resources_(true) {
  93.         connection_fd_ = ::socket(AF_INET, SOCK_STREAM, 0);
  94.     }
  95.  
  96.     ConnectionSocket(int connection_fd) :
  97.         connection_fd_(connection_fd),
  98.         have_resources_(true)
  99.         {}
  100.    
  101.     ConnectionSocket(ConnectionSocket &&other) {
  102.         connection_fd_ = other.connection_fd_;
  103.         status_ = std::move(other.status_);
  104.         other.have_resources_ = false;
  105.         have_resources_ = true;
  106.     }
  107.     ConnectionSocket(const ConnectionSocket &) = delete;
  108.     ConnectionSocket &operator=(const ConnectionSocket &) = delete;
  109.  
  110.     std::string getIP() const {
  111.         struct sockaddr_in addr;
  112.         socklen_t addrlen;
  113.         getpeername(connection_fd_, (sockaddr*) &addr, &addrlen);
  114.         return inet_ntoa(addr.sin_addr);
  115.     }
  116.  
  117.     Buffer read() {
  118.         char buffer[BUFFER_SIZE];
  119.         Buffer result;
  120.  
  121.         while (true) {
  122.             memset(buffer, 0, BUFFER_SIZE);
  123.             int readed = ::recv(connection_fd_, buffer, BUFFER_SIZE, 0);
  124.             appendTo(&result, buffer, BUFFER_SIZE);            
  125.             if (readed < BUFFER_SIZE) {
  126.                 break;
  127.             }
  128.         }
  129.  
  130.         return std::move(result);
  131.     }
  132.  
  133.     void write(Buffer buffer) {
  134.         send(connection_fd_, buffer.data(), buffer.size(), 0);
  135.         if (errno != 0) {
  136.             perror("Failed to write data");
  137.         }
  138.     }
  139.  
  140.     void readToSocket(ConnectionSocket &dest) {
  141.         char buf[BUFFER_SIZE];
  142.         while (true) {
  143.             int dataLength = recv(connection_fd_, buf, BUFFER_SIZE, 0);
  144.             if (dataLength <= 0) {
  145.                 break;
  146.             }
  147.             Buffer output(buf, buf + dataLength);
  148.             dest.write(output);
  149.         }
  150.     }
  151.  
  152.     void connect(const std::string &host, int port) {
  153.             struct sockaddr_in address = { AF_INET, htons(port) };
  154.             struct hostent *h = gethostbyname(host.c_str());
  155.  
  156.             if (!h) {
  157.                 throw std::runtime_error("Failed to create socket");
  158.             }
  159.             if (inet_aton(inet_ntoa(*((struct in_addr *)h->h_addr)), &address.sin_addr) <= 0) {
  160.                  throw std::runtime_error("Failed to connect");
  161.             }
  162.             if (::connect(connection_fd_, (struct sockaddr *) &address, sizeof(address)) < 0) {
  163.                 throw std::runtime_error("Failed to connect");
  164.             }
  165.     }
  166.  
  167.     ~ConnectionSocket() {
  168.         if (have_resources_) {
  169.             ::close(connection_fd_);
  170.         }
  171.     }
  172. };
  173.  
  174. class ServerSocket {
  175. private:
  176.     int fd_;
  177.     Status status_;
  178.  
  179.     void initSocket() {
  180.         fd_ = ::socket(AF_INET, SOCK_STREAM, 0);
  181.         if (fd_ < 0) {
  182.             throw std::runtime_error("Failed to create socket");
  183.         }
  184.     }
  185.  
  186.     void bindToAddress(const InternetAddress &internet_address) {
  187.         struct sockaddr address = internet_address.getSocketAddress();
  188.         int bound = ::bind(fd_, (struct sockaddr *) &address, sizeof(address));
  189.         if (bound == -1) {
  190.             throw std::runtime_error("Failed to bind socket");
  191.         }
  192.     }
  193.  
  194.     void listenTo() {
  195.         int listen_result = ::listen(fd_, 10);
  196.         if (listen_result == -1) {
  197.             throw std::runtime_error("Failed to listen");
  198.         }
  199.     }
  200.  
  201.     void setReuseAddress() {
  202.         int yes = 1;
  203.         if (::setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 ) {
  204.             throw std::runtime_error("Failed to set socket options");
  205.         }
  206.     }
  207.  
  208.     void closeSocket() {
  209.         ::close(fd_);
  210.     }
  211.  
  212. public:
  213.     ServerSocket(const InternetAddress &internet_address) {
  214.         try {
  215.             initSocket();
  216.             setReuseAddress();
  217.             bindToAddress(internet_address);
  218.             listenTo();
  219.         } catch(const std::runtime_error &exception) {
  220.             status_.setException(exception);
  221.         }
  222.     }
  223.  
  224.     ConnectionSocket newConnection() {
  225.         int new_fd = ::accept(fd_, 0, 0);
  226.         if (new_fd < 0) {
  227.             throw std::runtime_error("Failed to accept socket");
  228.         }
  229.         return std::move(ConnectionSocket(new_fd));
  230.     }
  231.  
  232.     ServerSocket(const ServerSocket &) = delete;
  233.     ServerSocket &operator=(const ServerSocket &) = delete;
  234.  
  235.     void check() const {
  236.         status_.check();
  237.     }
  238.  
  239.     ~ServerSocket() {
  240.         closeSocket();
  241.     }
  242.  
  243. };
  244.  
  245. std::string getURL(const Buffer& buffer) {
  246.     std::string URL;
  247.     size_t index = 0;
  248.     while (buffer[index++] != ' ');
  249.     while (buffer[index] != ' ') {
  250.         URL += buffer[index];
  251.         index++;
  252.     }
  253.     return URL;
  254. }
  255.  
  256. std::string getHost(const std::string URL) {
  257.     char buffer[256];
  258.     sscanf(URL.c_str() + 7, "%[^/]", buffer);
  259.     return buffer;
  260. }
  261.  
  262.  
  263. class TTask {
  264.     public:
  265.         virtual ~TTask() {}
  266.         virtual void Do(std::atomic<bool> &stopFlag) = 0;
  267. };
  268.  
  269. class TThreadPool {
  270.     private:
  271.         typedef std::shared_ptr< std::thread > TThreadPtr;
  272.         typedef std::shared_ptr< TTask > TTaskPtr;
  273.         std::atomic<bool> StopFlag;
  274.         std::vector<TThreadPtr> Workers;
  275.         std::mutex Mutex;
  276.         std::condition_variable Condition;
  277.         std::list<TTaskPtr> Tasks;
  278.         std::atomic<size_t> ActiveTasks;
  279.  
  280.         void DoTopTask(std::unique_lock<std::mutex> &lock) {
  281.             TTaskPtr task = Tasks.front();
  282.             Tasks.pop_front();
  283.             ++ActiveTasks;
  284.             lock.unlock();
  285.             task->Do(StopFlag);
  286.             if (--ActiveTasks == 0)
  287.                 Condition.notify_all();
  288.         }
  289.  
  290.         void ThreadFunc() {
  291.             while (!StopFlag) {
  292.                 std::unique_lock<std::mutex> lock(Mutex);
  293.                 while (!StopFlag && Tasks.empty())
  294.                     Condition.wait(lock);
  295.                 if (!StopFlag && !Tasks.empty())
  296.                     DoTopTask(lock);
  297.             }
  298.         }
  299.  
  300.     public:
  301.         TThreadPool(size_t workersCount)
  302.             : StopFlag(false)
  303.             , ActiveTasks(0)
  304.         {
  305.             Workers.reserve(workersCount);
  306.             for (size_t i = 0; i < workersCount; ++i)
  307.                 Workers.push_back(TThreadPtr(new std::thread([this]() { ThreadFunc(); })));
  308.         }
  309.         ~TThreadPool() {
  310.             try {
  311.                 Stop(false);
  312.             } catch (...) {
  313.             }
  314.         }
  315.         void Stop(bool finishTasks) {
  316.             StopFlag.store(true);
  317.             Condition.notify_all();
  318.             if (finishTasks) {
  319.                 std::unique_lock<std::mutex> lock(Mutex);
  320.                 while (!Tasks.empty()) {
  321.                     DoTopTask(lock);
  322.                     lock.lock();
  323.                 }
  324.             }
  325.             for (auto w : Workers) {
  326.                 w->join();
  327.             }
  328.         }
  329.         bool AddTask(const TTaskPtr &task) {
  330.             if (StopFlag)
  331.                 return false;
  332.             std::lock_guard<std::mutex> lock(Mutex);
  333.             Tasks.push_back(task);
  334.             Condition.notify_one();
  335.             return true;
  336.         }
  337.         bool WaitAllTasks() {
  338.             std::unique_lock<std::mutex> lock(Mutex);
  339.             while (!StopFlag && (!Tasks.empty() || ActiveTasks)) {
  340.                 Condition.wait(lock);
  341.             }
  342.             return !StopFlag;
  343.         }
  344. };
  345.  
  346. class MyTask : public TTask {
  347.     private:
  348.         static constexpr int PORT = 80;
  349.         ConnectionSocket connectionSocket;
  350.        
  351.     public:
  352.         explicit MyTask(ConnectionSocket &&other)
  353.             : connectionSocket(std::move(other))
  354.         {}
  355.  
  356.         virtual void Do(std::atomic<bool> &stopFlag) {
  357.             try {
  358.                 Buffer buffer = connectionSocket.read();
  359.                 ConnectionSocket workSocket;
  360.                 std::string URL = getURL(buffer);
  361.                 std::string host = getHost(URL);
  362.  
  363.                 std::cout << "Client IP    : " << connectionSocket.getIP() << std::endl;
  364.                 std::cout << "Requested URL: " << URL << std::endl;
  365.  
  366.                 workSocket.connect(host, PORT);
  367.                 workSocket.write(buffer);
  368.                 workSocket.readToSocket(connectionSocket);
  369.             } catch (const std::exception &ex) {
  370.                 std::cerr << ex.what() << std::endl;
  371.             }
  372.         }
  373. };
  374.  
  375. int main() {
  376.  
  377.     static constexpr char LOCALHOST[] = "127.0.0.1";
  378.     static constexpr int DEFAULT_PORT = 8992;
  379.     static constexpr size_t POOL_SIZE = 128;
  380.     InternetAddress address = InternetAddress(LOCALHOST, DEFAULT_PORT);
  381.     ServerSocket serverSocket(address);
  382.  
  383.     try {
  384.         serverSocket.check();
  385.     } catch (const std::exception &ex) {
  386.         std::cerr << ex.what() << std::endl;
  387.         return 1;
  388.     }
  389.    
  390.     TThreadPool pool(POOL_SIZE);
  391.     try {
  392.         while (true) {
  393.             pool.AddTask(std::shared_ptr<TTask>(new MyTask(serverSocket.newConnection())));
  394.         }
  395.     } catch (const std::exception &ex) {
  396.         std::cerr << ex.what() << std::endl;
  397.         return 1;
  398.     }
  399.  
  400.     return 0;
  401. }
Advertisement
Add Comment
Please, Sign In to add comment