Advertisement
Hauke

SyncHTTP Sources

Aug 11th, 2013
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.64 KB | None | 0 0
  1. /* all files copied together */
  2. #ifndef SOCKET_H
  3. #define SOCKET_H
  4.  
  5. #include <WinSock2.h>
  6.  
  7. #include <string>
  8.  
  9. enum TypeSocket {BlockingSocket, NonBlockingSocket};
  10.  
  11. class Socket {
  12. public:
  13.  
  14.   virtual ~Socket();
  15.   Socket(const Socket&);
  16.   Socket& operator=(Socket&);
  17.  
  18.   std::string ReceiveLine();
  19.   int Socket::ReceiveContent(std::string & result);
  20.   std::string ReceiveBytes();
  21.  
  22.   void   Close();
  23.   void   SendLine (std::string);
  24.   void   SendBytes(const std::string&);
  25.  
  26. protected:
  27.   friend class SocketServer;
  28.   friend class SocketSelect;
  29.  
  30.   Socket(SOCKET s);
  31.   Socket();
  32.  
  33.  
  34.   SOCKET s_;
  35.  
  36.   int* refCounter_;
  37.  
  38. private:
  39.   static void Start();
  40.   static void End();
  41.   static int  nofSockets_;
  42. };
  43.  
  44. class SocketClient : public Socket {
  45. public:
  46.   SocketClient(const std::string& host, int port);
  47. };
  48.  
  49. class SocketServer : public Socket {
  50. public:
  51.   SocketServer(int port, int connections, TypeSocket type=BlockingSocket);
  52.  
  53.   Socket* Accept();
  54. };
  55.  
  56. class SocketSelect {
  57.   public:
  58.     SocketSelect(Socket const * const s1, Socket const * const s2=NULL, TypeSocket type=BlockingSocket);
  59.  
  60.     bool Readable(Socket const * const s);
  61.  
  62.   private:
  63.     fd_set fds_;
  64. };
  65. #endif
  66.  
  67.  
  68.  
  69. #include "socket.h"
  70. #include <iostream>
  71.  
  72. using namespace std;
  73.  
  74. int Socket::nofSockets_= 0;
  75.  
  76. void Socket::Start() {
  77.   if (!nofSockets_) {
  78.     WSADATA info;
  79.     if (WSAStartup(MAKEWORD(2,0), &info)) {
  80.       throw "Could not start WSA";
  81.     }
  82.   }
  83.   ++nofSockets_;
  84. }
  85.  
  86. void Socket::End() {
  87.   WSACleanup();
  88. }
  89.  
  90. Socket::Socket() : s_(0) {
  91.   Start();
  92.   s_ = socket(AF_INET,SOCK_STREAM,0);
  93.  
  94.   if (s_ == INVALID_SOCKET) {
  95.       return;
  96.   }
  97.  
  98.   refCounter_ = new int(1);
  99. }
  100.  
  101. Socket::Socket(SOCKET s) : s_(s) {
  102.   Start();
  103.   refCounter_ = new int(1);
  104. };
  105.  
  106. Socket::~Socket() {
  107.   if (! --(*refCounter_)) {
  108.     Close();
  109.     delete refCounter_;
  110.   }
  111.  
  112.   --nofSockets_;
  113.   if (!nofSockets_) End();
  114. }
  115.  
  116. Socket::Socket(const Socket& o) {
  117.   refCounter_=o.refCounter_;
  118.   (*refCounter_)++;
  119.   s_         =o.s_;
  120.  
  121.   nofSockets_++;
  122. }
  123.  
  124. Socket& Socket::operator=(Socket& o) {
  125.   (*o.refCounter_)++;
  126.  
  127.   refCounter_=o.refCounter_;
  128.   s_         =o.s_;
  129.  
  130.   nofSockets_++;
  131.  
  132.   return *this;
  133. }
  134.  
  135. void Socket::Close() {
  136.   closesocket(s_);
  137. }
  138.  
  139. std::string Socket::ReceiveBytes() {
  140.   std::string ret;
  141.   char buf[1024];
  142.  
  143.   while (1) {
  144.     u_long arg = 0;
  145.     if (ioctlsocket(s_, FIONREAD, &arg) != 0)
  146.       break;
  147.  
  148.     if (arg == 0)
  149.       break;
  150.  
  151.     if (arg > 1024) arg = 1024;
  152.  
  153.     int rv = recv (s_, buf, arg, 0);
  154.     if (rv <= 0) break;
  155.  
  156.     std::string t;
  157.  
  158.     t.assign (buf, rv);
  159.     ret += t;
  160.   }
  161.  
  162.   return ret;
  163. }
  164.  
  165.  
  166. int Socket::ReceiveContent(std::string & result) {
  167.     std::string firstLine = Socket::ReceiveLine();
  168.     if (firstLine.find("302 Found") != std::string::npos)   //redirect
  169.     {
  170.         std::string lineBytes;
  171.         while(true)
  172.         {
  173.             while (true)
  174.             {
  175.                 char r;
  176.                 if(!recv(s_, &r, 1, 0))
  177.                     break;
  178.                 lineBytes += r;
  179.                 if (r == '\n')
  180.                     break;
  181.             }
  182.             if(lineBytes.empty())
  183.             {
  184.                 result = "";
  185.                 return 302;
  186.             }
  187.             if (lineBytes.find("Location:") != std::string::npos)
  188.                 break;
  189.         }
  190.         result = lineBytes.substr(10);
  191.         return 302;
  192.     }
  193.     else if (firstLine.find("200 OK") != std::string::npos)
  194.     {
  195.         while(true)
  196.         {
  197.             std::string lineBytes;
  198.             while (true)
  199.             {
  200.                 char r;
  201.                 if(!recv(s_, &r, 1, 0))
  202.                     break;
  203.                 lineBytes += r;
  204.                 if (r == '\n')
  205.                     break;
  206.             }
  207.             if(lineBytes.empty())
  208.                 break;
  209.             if(lineBytes.find("wbb_resp:") != std::string::npos)
  210.             {
  211.                 result = lineBytes.substr(10);
  212.                 break;
  213.             }
  214.         }
  215.         return 200;
  216.     }
  217.     else
  218.     {
  219.         result = "none";
  220.         return 0;
  221.     }
  222. }
  223.  
  224. std::string Socket::ReceiveLine() {
  225.   std::string ret;
  226.   while (1) {
  227.     char r;
  228.  
  229.     switch(recv(s_, &r, 1, 0)) {
  230.       case 0:
  231.         return ret;
  232.       case -1:
  233.         return "";
  234.     }
  235.  
  236.     ret += r;
  237.     if (r == '\n')
  238.         return ret;
  239.   }
  240. }
  241.  
  242. void Socket::SendLine(std::string s) {
  243.   s += '\n';
  244.   send(s_,s.c_str(),s.length(),0);
  245. }
  246.  
  247. void Socket::SendBytes(const std::string& s) {
  248.   send(s_,s.c_str(),s.length(),0);
  249. }
  250.  
  251. SocketServer::SocketServer(int port, int connections, TypeSocket type) {
  252.   sockaddr_in sa;
  253.  
  254.   memset(&sa, 0, sizeof(sa));
  255.  
  256.   sa.sin_family = PF_INET;            
  257.   sa.sin_port = htons(port);          
  258.   s_ = socket(AF_INET, SOCK_STREAM, 0);
  259.   if (s_ == INVALID_SOCKET) {
  260.     return;
  261.   }
  262.  
  263.   if(type==NonBlockingSocket) {
  264.     u_long arg = 1;
  265.     ioctlsocket(s_, FIONBIO, &arg);
  266.   }
  267.  
  268.   if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR) {
  269.     closesocket(s_);
  270.     return;
  271.   }
  272.  
  273.   listen(s_, connections);                              
  274. }
  275.  
  276. Socket* SocketServer::Accept() {
  277.   SOCKET new_sock = accept(s_, 0, 0);
  278.   if (new_sock == INVALID_SOCKET) {
  279.     int rc = WSAGetLastError();
  280.     if(rc==WSAEWOULDBLOCK) {
  281.       return 0;
  282.     }
  283.     else {
  284.       throw "Invalid Socket";
  285.     }
  286.   }
  287.  
  288.   Socket* r = new Socket(new_sock);
  289.   return r;
  290. }
  291.  
  292. SocketClient::SocketClient(const std::string& host, int port) : Socket() {
  293.   std::string error;
  294.  
  295.   hostent *he;
  296.   if ((he = gethostbyname(host.c_str())) == 0) {
  297.     error = strerror(errno);
  298.     throw error;
  299.   }
  300.  
  301.   sockaddr_in addr;
  302.   addr.sin_family = AF_INET;
  303.   addr.sin_port = htons(port);
  304.   addr.sin_addr = *((in_addr *)he->h_addr);
  305.   memset(&(addr.sin_zero), 0, 8);
  306.  
  307.   if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr))) {
  308.     error = strerror(WSAGetLastError());
  309.     throw error;
  310.   }
  311. }
  312.  
  313. SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type) {
  314.   FD_ZERO(&fds_);
  315.   FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
  316.   if(s2) {
  317.     FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
  318.   }    
  319.  
  320.   TIMEVAL tval;
  321.   tval.tv_sec  = 0;
  322.   tval.tv_usec = 1;
  323.  
  324.   TIMEVAL *ptval;
  325.   if(type==NonBlockingSocket) {
  326.     ptval = &tval;
  327.   }
  328.   else {
  329.     ptval = 0;
  330.   }
  331.  
  332.   if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR)
  333.     return;
  334. }
  335.  
  336. bool SocketSelect::Readable(Socket const* const s) {
  337.   if (FD_ISSET(s->s_,&fds_)) return true;
  338.   return false;
  339. }
  340.  
  341.  
  342.  
  343.  
  344. static cell AMX_NATIVE_CALL n_SynchronizedHTTP( AMX* amx, cell* params )
  345. {
  346.     /*
  347.     params[1]       char array          URL
  348.     params[2]       char array          Post data
  349.     params[3]       ref char array      Result string
  350.     params[4]       int                 Result string lenght
  351.     params[5]       int                 Method (1 = GET, 2 = POST)
  352.     params[6]       int                 Timeout in seconds
  353.     params[7]       bool                Debug
  354.     */
  355.  
  356.     std::string
  357.         paramURL = GetAMXString(amx, params[1]),
  358.         paramData = GetAMXString(amx, params[2]);
  359.  
  360.     int
  361.         method = params[5],
  362.         timeout = params[6];
  363.  
  364.     bool
  365.         debug = params[7];
  366.  
  367.     if(paramURL.length() < 3)
  368.         return 0;
  369.  
  370.     if(paramURL.find("http://") != 0)
  371.         paramURL = "http://" + paramURL;
  372.  
  373.     CURL *curlSession;
  374.     clock_t timeBegin, timeEnd;
  375.     double timeSpent;
  376.     curlSession = curl_easy_init();
  377.     if(curlSession)
  378.     {
  379.         CURLcode response;
  380.         std::string readBuffer;
  381.         long httpCode = 0;
  382.         timeBegin = clock();
  383.  
  384.         if(method == 1)
  385.         {
  386.             if(!paramData.empty())
  387.             {
  388.                 if(paramURL.find("?"))
  389.                     paramURL.append("&");
  390.                 else
  391.                     paramURL.append("?");
  392.             }
  393.             paramURL.append(paramData.data());
  394.             curl_easy_setopt(curlSession, CURLOPT_URL, paramURL);
  395.         }
  396.         else if(method == 2)
  397.         {
  398.             curl_easy_setopt(curlSession, CURLOPT_URL, paramURL.data());
  399.             curl_easy_setopt(curlSession, CURLOPT_POST, 1);
  400.             curl_easy_setopt(curlSession, CURLOPT_POSTFIELDS, paramData.data());
  401.         }
  402.         else
  403.         {
  404.             if(debug)
  405.                 logprintf(">> SyncHTTP Plugin Error: Unknown method");
  406.             return -1;
  407.         }
  408.  
  409.         curl_easy_setopt(curlSession, CURLOPT_WRITEFUNCTION, WriteCallback);
  410.         curl_easy_setopt(curlSession, CURLOPT_WRITEDATA, &readBuffer);
  411.         curl_easy_setopt(curlSession, CURLOPT_FORBID_REUSE, false);
  412.         curl_easy_setopt(curlSession, CURLOPT_TIMEOUT, timeout);
  413.         curl_easy_setopt(curlSession, CURLOPT_FOLLOWLOCATION, true);
  414.         curl_easy_setopt(curlSession, CURLOPT_MAXREDIRS, 50);
  415.        
  416.         response = curl_easy_perform(curlSession);
  417.  
  418.         curl_easy_getinfo (curlSession, CURLINFO_RESPONSE_CODE, &httpCode);
  419.        
  420.         if(response != CURLE_OK)
  421.         {
  422.             if(debug)
  423.                 logprintf(">> SyncHTTP Plugin Error: %s", curl_easy_strerror(response));
  424.             return -1;
  425.         }
  426.         if(debug)
  427.         {
  428.             timeEnd = clock();
  429.             timeSpent = (double)(timeEnd - timeBegin) / CLOCKS_PER_SEC;
  430.             logprintf(">> SyncHTTP Plugin\nRequest sent to: \"%s\"\nStatus: %d\nPost: \"%s\"\nTime spent to perform request: %f sec\nResponse: \"%s\"", paramURL.c_str(), (int)httpCode, method == 2 ? paramData.c_str() : "", timeSpent, readBuffer.c_str());
  431.         }
  432.  
  433.         SetAMXString(amx, params[3], (int)params[4], readBuffer);
  434.  
  435.         curl_easy_cleanup(curlSession);
  436.         return (int)httpCode;
  437.     }
  438.     return -1;
  439. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement