Advertisement
Guest User

Untitled

a guest
May 16th, 2017
524
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 42.32 KB | None | 0 0
  1. //  THIS IS FILE : server20k.cpp
  2. //////////////////////////////////////////////////////////////////////////////
  3.  
  4. //  To linker:
  5. //
  6. //Maybe you need threads and mutex/semaphores?
  7. //  -pthread
  8. //
  9. //It is more simple than search libraries on server...
  10. //  -static
  11. //
  12. //For MySQL:
  13. //  -lmysqlclient
  14. //  -lz
  15. //
  16. #include "mysql/mysql.h"
  17. #include "mysql/mysqld_error.h"
  18.  
  19.  
  20. //  libevent
  21. #include <event.h>
  22.  
  23. //  socket, bind, accept
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26.  
  27. //  unix socket
  28. #include <sys/un.h>
  29.  
  30. //  inet_ntop
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <arpa/inet.h>
  34.  
  35. //  errno
  36. #include <errno.h>
  37.  
  38. //  fcntl
  39. #include <fcntl.h>
  40.  
  41. //  memset
  42. #include <string.h>
  43.  
  44. //  getrlimit
  45. #include <sys/time.h>
  46. #include <sys/resource.h>
  47. #include <unistd.h>
  48.  
  49. //  exit
  50. #include <unistd.h>
  51. #include <stdlib.h>
  52.  
  53. //  signal
  54. #include <signal.h>
  55.  
  56. //  poll
  57. #include <sys/poll.h>
  58.  
  59.  
  60. #include <iostream>
  61. #include <iomanip>
  62. #include <list>
  63. using namespace std;
  64.  
  65.  
  66.  
  67. void daemon_init();
  68. void discriptors_setuping();
  69.  
  70.  
  71. #define _SOCKETS_ERRORS_RUS_TEXT_ 1
  72. //#define _SOCKETS_ERRORS_ENG_TEXT_ 1
  73. void PrintDetailedSocketError( int err );
  74. void PrintDetailedBindError( int err );
  75. void PrintDetailedGSAError( int err );
  76. void PrintDetailedNonblockingError( int err );
  77. void PrintDetailedListenError( int err );
  78.  
  79.  
  80. int       CreateSocket( int domain = AF_INET, int type = SOCK_STREAM, int protocol = 0 );
  81. void      BindSocket( int sockfd, const struct sockaddr * addr, socklen_t addrlen );
  82. socklen_t GetSocketAddr( int sockfd, struct sockaddr * addr, socklen_t namelen );
  83. void      SetSocketAsNoblocking( int sockfd );
  84. bool      SetSocketAsNoblocking_once( int sockfd );
  85. void      ListenSocket( int sockfd, int backlog );
  86.  
  87.  
  88. void MakeServer_IPv4( const char * addr_cstr_,  unsigned short port_, int backlog_ );
  89. void MakeServer_IPv6( const char * addr_cstr_,  unsigned short port_, int backlog_ );
  90.  
  91.  
  92.  
  93. void MySQL_Works();
  94.  
  95. int
  96. main( int argc, char ** argv)
  97. {
  98.     //daemon_init();
  99.     discriptors_setuping();
  100.  
  101.     MySQL_Works();
  102.  
  103.     //MakeServer_IPv6( "::1" /*=localhost*/,  5433 /*some port*/, 512 /*normal backlog*/ );
  104.     //MakeServer_IPv6( "::"  /*=INADDR_ANY*/, 5433 /*some port*/, 512 /*normal backlog*/  );
  105.     //MakeServer_IPv4( "127.0.0.1" /*=localhost*/, 5433 /*some port*/, 512 /*normal backlog*/  );
  106.     MakeServer_IPv4( "0.0.0.0" /*=INADDR_ANY*/, 5433 /*some port*/, 512 /*normal backlog*/  );
  107.  
  108.  
  109.     exit(EXIT_SUCCESS);
  110. }
  111.  
  112.  
  113.  
  114. void MySQL_Works()
  115. {
  116.     char *server = "localhost";
  117.     char *user = "sec-piler";
  118.     char *database = "databasename";
  119.     char *password = "psecpiler";
  120.  
  121.  
  122.     MYSQL mysql;
  123.  
  124.     mysql_init( &mysql );
  125.     //mysql_options( &mysql, MYSQL_READ_DEFAULT_GROUP, "your_prog_name" );
  126.  
  127.     cout << endl << "Try to connect." << endl;
  128.     int attempt = 0;
  129.     while( false == mysql_real_connect( &mysql,
  130.                                         server, //  IP or domain name of server.
  131.                                         user,
  132.                                         password,
  133.                                         database,
  134.                                         3306,   //  Port for network connections (localhost or other server in INET).
  135.                                         NULL,   //  Local unix socket, up performance to 8%. (unused only if param = NULL, used even if param is string like "" - Print error.)
  136.                                         0       //  Flags, something about SSL, etc...
  137.                                         )
  138.         )
  139.     {
  140.         cerr << "  (" << ++attempt << ") Erorr (#" << mysql_errno(&mysql) << "): " << mysql_error(&mysql) << '\r';
  141.         usleep( 1000 * 1000 - 1 );
  142.     }
  143.     cout << endl << "Successful done." << endl;
  144.  
  145.  
  146.     if( 0 != mysql_query( &mysql, "INSERT DELAYED INTO reports (username, repln) VALUES (\"\\\"The bob!\\\"\", \"\\\"23344122\\\"\")" ) )
  147.     {
  148.         cout << endl << "Error: Can't make query. Error(" << mysql_errno( &mysql ) << "): " << mysql_error( &mysql ) << endl;
  149.     }
  150. }
  151.  
  152. struct GrowBuff
  153. {
  154.     char * buff;
  155.     size_t buffSize;
  156.     size_t buffUsed;
  157.     static const size_t STD_BUFF_SIZE = 4096;
  158.  
  159.     GrowBuff()
  160.     {
  161.         buff = new char [STD_BUFF_SIZE];
  162.         buffSize = STD_BUFF_SIZE;
  163.         buffUsed = 0;
  164.     }
  165.  
  166.     ~GrowBuff()
  167.     {
  168.         if( NULL != buff ) delete [] buff;
  169.     }
  170.  
  171.     void AddSize( size_t add_size_ )
  172.     {
  173.         char * temp = new char [buffSize + add_size_];
  174.         memcpy( temp, buff, buffUsed );
  175.         delete [] buff;
  176.         buff = temp;
  177.         buffSize += add_size_;
  178.     }
  179.  
  180.     void SureGotFreeSpace()
  181.     {
  182.         if( buffSize - buffUsed < STD_BUFF_SIZE )
  183.         {
  184.             AddSize( buffSize );
  185.         }
  186.     }
  187.  
  188.     void AddData( const char * data_, size_t data_size_ )
  189.     {
  190.         if( buffSize - buffUsed < data_size_ ) AddSize( buffUsed + data_size_ );    //  I need mnogo i srazu! )
  191.         memcpy( buff + buffUsed, data_, data_size_ );
  192.         buffUsed += data_size_;
  193.     }
  194.  
  195. };
  196.  
  197.  
  198. struct ConnectionData
  199. {
  200.     int sock;
  201.     int number;
  202.     GrowBuff buff_in;
  203.     GrowBuff buff_out;
  204.     pollfd mypoll;
  205.     size_t writed;
  206.  
  207.     ConnectionData()
  208.     {
  209.         mypoll.revents = 0;
  210.         writed = 0;
  211.     }
  212.  
  213.     void OnWrite_WithTest()
  214.     {
  215.         if( mypoll.revents & (POLLOUT) )
  216.         {
  217.             size_t snd = 0;
  218.             //cout << "OnWrite in connection #" << number << endl;
  219.             if( writed < buff_out.buffUsed )
  220.             {
  221.                 snd = send( sock,
  222.                             buff_out.buff     + writed,
  223.                             buff_out.buffUsed - writed,
  224.                             0 );
  225.                 cout << "snd = " << snd << endl;
  226.                 if( snd > 0 ) writed += snd;
  227.  
  228.                 if( writed == buff_out.buffUsed )
  229.                 {
  230.                     cout << "writed = " << writed << "; buff used = " << buff_out.buffUsed << endl;
  231.                     writed = 0;
  232.                     buff_out.buffUsed = 0;
  233.                     mypoll.events = mypoll.events & (~POLLOUT);
  234.                 }
  235.             }
  236.         }
  237.     }
  238.  
  239.     void OnRead()
  240.     {
  241.         size_t rcv = 1;
  242.         while( -1 != rcv )
  243.         {
  244.             buff_in.SureGotFreeSpace();
  245.  
  246.             rcv = recv( sock,
  247.                         buff_in.buff,
  248.                         buff_in.buffSize - buff_in.buffUsed,
  249.                         0 );
  250.  
  251.             if(  0 == rcv ) //  If connection was closed.
  252.             {
  253.                 mypoll.revents = POLLHUP;
  254.                 break;
  255.                 //  We have close connection when will test it for errors <if( (...revent) & (POLLHUP|...) )>
  256.             }
  257.  
  258.             //  If we read something.
  259.             if( -1 != rcv ) buff_in.buffUsed += rcv;
  260.             else
  261.             {
  262.                 if( EAGAIN != errno ) mypoll.revents = POLLHUP;
  263.                 break;
  264.             }
  265.         }
  266.     }
  267.  
  268. };
  269.  
  270.  
  271.  
  272.  
  273.  
  274. void MakeServer_IPv4( const char * addr_cstr_,  unsigned short port_, int backlog_ )
  275. {
  276.  
  277.     int srv_sock;   //  listening socket
  278.  
  279.     char            saddr[sizeof(sockaddr_un)];     //  buffer for address of listening socket (very big buffer))
  280.     socklen_t       saddr_len   = sizeof(saddr);    //  size of address
  281.  
  282.     sockaddr     * psaddr       = (sockaddr    *)&saddr;    //  pointer for standart functions
  283.     sockaddr_in  * psaddr4      = (sockaddr_in *)&saddr;    //  poinetr for hand-filling of address
  284.  
  285.  
  286.  
  287.  
  288.     memset( &saddr, 0, saddr_len );
  289.  
  290.  
  291.  
  292.     psaddr4->sin_family = AF_INET;
  293.     psaddr4->sin_port   = htons( port_ );   //  convertion <Host TO Network> byte order in <Short> variable
  294.     if( 0 >= inet_pton( AF_INET, addr_cstr_, &(psaddr4->sin_addr) ) )
  295.     {
  296.         cerr << endl << " Error. Can't convert the character string \""<< addr_cstr_ <<"\" into a network address structure" << endl;
  297.         exit(EXIT_FAILURE);
  298.     }
  299.  
  300.     srv_sock = CreateSocket( AF_INET, SOCK_STREAM, 0 );
  301.     BindSocket( srv_sock, psaddr, saddr_len );
  302.     if( 0 == port_ )
  303.     {
  304.         saddr_len = GetSocketAddr( srv_sock, psaddr, saddr_len );
  305.         port_ = ntohs( psaddr4->sin_port );
  306.         cout << "System give me port #" << port_ << endl;
  307.     }
  308.  
  309.     SetSocketAsNoblocking( srv_sock );
  310.     ListenSocket( srv_sock, backlog_ );
  311.     //  Server socket done.
  312.  
  313.  
  314.  
  315.     //  Poll.
  316.  
  317.     ConnectionData * cd;
  318.     std::list<ConnectionData*> ConnectionsList;
  319.     std::list<ConnectionData*>::iterator iList;
  320.  
  321.     size_t   fdArrSize = 32;
  322.     size_t   fdArrUsed = 1;
  323.     pollfd * fdArr = new pollfd[fdArrSize];
  324.     fdArr[0].fd = srv_sock;    //  There always will be a server listening socket.
  325.     fdArr[0].events = POLLIN;
  326.  
  327.  
  328.     int conn = -1;
  329.     sockaddr aconn;
  330.     socklen_t slen = sizeof(aconn);
  331.  
  332.     const static size_t BUFF_SIZE = 1024;
  333.     char   buff[BUFF_SIZE];
  334.     int res = 0;
  335.  
  336.     int number = 0;
  337.  
  338.     while( true )
  339.     {
  340.         cout << " > > >   Poll go! " << endl;
  341.         res = poll( fdArr, fdArrUsed, -1 /* timout off, wait forever event */ );
  342.  
  343.         if( -1 == res ) //  Some error on poll()
  344.         {
  345.             //  Oh man... In fact, i don't know what to do...
  346.             //  But it seems it never happens with Collector.
  347.             continue;
  348.         }
  349.  
  350.         //  Copy poll results to lists elements, before we (maybe) accept new connections and list grown up.
  351.         res = 1;
  352.         for( iList = ConnectionsList.begin(); iList != ConnectionsList.end(); iList++)
  353.         {
  354.             (*iList)->mypoll = fdArr[res++];
  355.         }
  356.  
  357.  
  358.  
  359.         //////////////////////////////////////////////////////////////////////////////
  360.         //  Accepting connections.
  361.         if( fdArr[0].revents & (POLLIN) )   //  We have new connection on listening socket.
  362.         {
  363.             conn = 0;
  364.             while( -1 != conn )
  365.             {
  366.                 conn = accept( srv_sock, &aconn, &slen );
  367.                 if( -1 != conn )
  368.                 {
  369.                     cout << "New connection socket discriptor = " << conn << endl;
  370.                     if( false == SetSocketAsNoblocking_once( conn ) )
  371.                     {
  372.                         cerr << endl << " Error. Can't set connected socket as nonblocking." << endl;
  373.                         close( conn );
  374.                         continue;
  375.                     }
  376.  
  377.                     cd = new ConnectionData;
  378.                     cd->sock = conn;
  379.  
  380.                     cd->mypoll.fd = conn;
  381.                     cd->mypoll.events = POLLIN; // POLLIN|POLLOUT
  382.  
  383.                     cd->number = ++number;
  384.  
  385.                     ConnectionsList.push_back( cd );
  386.                 }
  387.                 else cout << "Have no more connections." << endl;
  388.             }
  389.         }
  390.         //////////////////////////////////////////////////////////////////////////////
  391.  
  392.  
  393.         if(fdArrSize+1 < ConnectionsList.size() )
  394.         {
  395.             delete [] fdArr;
  396.             fdArrSize += fdArrSize/2;
  397.             fdArr = new pollfd[fdArrSize];
  398.             fdArr[0].fd = srv_sock;
  399.             fdArr[0].events = POLLIN;
  400.         }
  401.         fdArrUsed = 1;
  402.  
  403.         //////////////////////////////////////////////////////////////////////////////
  404.         //  Look for data and errors on every socket.
  405.         for( iList = ConnectionsList.begin(); iList != ConnectionsList.end(); )
  406.         {
  407.             cd = *(iList);
  408.             cout << "Look at connection #" << fdArrUsed << ", disriptor " << cd->sock << "; revents = " << cd->mypoll.revents << endl;
  409.  
  410.             //  Look for data...
  411.             if( cd->mypoll.revents & (POLLIN) ) //  If we have new data on this socket.
  412.             {
  413.                 cout << "Got data on socket: " << cd->sock << "; conn#" << cd->number << ") Buff used = " << cd->buff_in.buffUsed << endl;
  414.                 cd->OnRead();
  415.                 cout << "Now buff used = " << cd->buff_in.buffUsed << endl;
  416.             }
  417.  
  418.             //  Look for errors...
  419.             if( cd->mypoll.revents & (POLLERR|POLLHUP|POLLNVAL) )   //  If we have some error on this socket.
  420.             {
  421.                 close( cd->sock );
  422.                 delete cd;
  423.                 cd = NULL;
  424.                 iList = ConnectionsList.erase( iList );
  425.             }
  426.             else
  427.             {
  428.                 iList++;
  429.             }
  430.  
  431.             //////////////////////////////////////////////////////////////////////////////
  432.             // Work may be here, or in other thread.
  433.             if( NULL != cd )
  434.                 if( cd->buff_in.buffUsed > 100 )
  435.                 {
  436.                     cd->buff_out.AddSize( 1231232 );
  437.                     char test_text[] = "[Test text] ";
  438.                     size_t ttsize = strlen(test_text)+1;
  439.                     for( size_t i = 0; i < cd->buff_out.buffSize; i++)
  440.                     {
  441.                         cd->buff_out.buff[i] = test_text[i%ttsize];
  442.                     }
  443.                     cd->buff_out.buffUsed = cd->buff_out.buffSize;
  444.                     cd->mypoll.events |= POLLOUT;
  445.                     cd->buff_in.buffUsed = 0;
  446.                 }
  447.             //////////////////////////////////////////////////////////////////////////////
  448.  
  449.  
  450.  
  451.             //////////////////////////////////////////////////////////////////////////////
  452.             // Work may be here, or in other thread.
  453.             if( NULL != cd )
  454.                 if( cd->buff_in.buffUsed > 10 )
  455.                 {
  456.                     memcpy( cd->buff_out.buff,
  457.                             "Ok, we have more than 10 bytes, and i answer you...\n",
  458.                             strlen("Ok, we have more than 10 bytes, and i answer you...\n")
  459.                             );
  460.                     cd->buff_out.buffUsed = strlen("Ok, we have more than 10 bytes, and i answer you...\n");
  461.                     cd->mypoll.events |= POLLOUT;
  462.                     //cd->buff_in.buffUsed = 0;
  463.                 }
  464.             //////////////////////////////////////////////////////////////////////////////
  465.  
  466.  
  467.             //  If we can write something into socket, and have data to write
  468.             if( NULL != cd )
  469.             {
  470.                 cd->OnWrite_WithTest();
  471.                 fdArr[fdArrUsed++] = cd->mypoll;
  472.             }
  473.  
  474.         }//for( iList = ConnectionsList.begin(); iList != ConnectionsList.end(); )
  475.         //////////////////////////////////////////////////////////////////////////////
  476.  
  477. //   ^  Next loop of server work.
  478. //   |      |
  479. //   +------+
  480.  
  481.     }//while( true )
  482. }
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494. //  Simple echo server.
  495. void MakeServer_IPv6( const char * addr_cstr_,  unsigned short port_, int backlog_ )
  496. {
  497.     int sock;   //  listening socket
  498.  
  499.     char            saddr[sizeof(sockaddr_un)];     //  buffer for address of listening socket (very big buffer))
  500.     socklen_t       saddr_len   = sizeof(saddr);    //  size of address
  501.  
  502.     sockaddr     * psaddr       = (sockaddr    *)&saddr;    //  pointer for standart functions
  503.     sockaddr_in6 * psaddr6      = (sockaddr_in6*)&saddr;    //  poinetr for hand-filling of address
  504.  
  505.  
  506.  
  507.  
  508.     memset( &saddr, 0, saddr_len );
  509.  
  510.  
  511.  
  512.     psaddr6->sin6_family = AF_INET6;
  513.     psaddr6->sin6_port   = htons( port_ );   //  convertion <Host TO Network> byte order in <Short> variable
  514.     if( 0 >= inet_pton( AF_INET6, addr_cstr_, &(psaddr6->sin6_addr) ) )
  515.     {
  516.         cerr << endl << " Error. Can't convert the character string \""<< addr_cstr_ <<"\" into a network address structure" << endl;
  517.         exit(EXIT_FAILURE);
  518.     }
  519.  
  520.     sock = CreateSocket( AF_INET6, SOCK_STREAM, 0 );
  521.     BindSocket( sock, psaddr, saddr_len );
  522.     if( 0 == port_ )
  523.     {
  524.         saddr_len = GetSocketAddr( sock, psaddr, saddr_len );
  525.         port_ = ntohs( psaddr6->sin6_port );
  526.         cout << "System give me port #" << port_ << endl;
  527.     }
  528.  
  529.     //SetSocketAsNoblocking( sock );
  530.     ListenSocket( sock, backlog_ );
  531.  
  532.  
  533.     int conn = -1;
  534.     sockaddr_in6    aconn;
  535.     sockaddr     * paconn = (sockaddr*)&aconn;
  536.     socklen_t slen = sizeof(aconn);
  537.     while( true )
  538.     {
  539.         conn = accept( sock, paconn, &slen );
  540.         cout << "New connection socket discriptor = " << conn << endl;
  541.         if( -1 != conn )
  542.         {
  543.             if( false == SetSocketAsNoblocking_once( conn ) )
  544.             {
  545.                 cerr << endl << " Error. Can't set connected socket as nonblocking." << endl;
  546.                 close( conn );
  547.                 continue;
  548.             }
  549.  
  550.             char buff[4096];
  551.             size_t rcv = 1;
  552.             while( (-1 != rcv) && (0 != rcv) )
  553.             {
  554.                 rcv = recv( conn, buff, 4096, 0 );
  555.  
  556.                 cout << "Received " << rcv << " bytes: ";
  557.                 cout.write( buff, rcv );
  558.                 cout << endl;
  559.  
  560.                 send( conn, buff, rcv, 0 );
  561.             }
  562.             close( conn );
  563.         }
  564.  
  565.     }//while( true )
  566.  
  567. }
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592. void daemon_init()
  593. {
  594.     pid_t pid;
  595.  
  596.     if( 0 != (pid = fork()) )
  597.     //  Parent exit.
  598.         exit(0);
  599.     //  Child now work...
  600.  
  601.     //  Create new session without binded terminal
  602.     //  and become a main process in session.
  603.     setsid();
  604.  
  605.     //  Ignore signal of terminating main session process (i.e. me)
  606.     //  on next <fork() exit(0)> for new child.
  607.     signal(SIGHUP, SIG_IGN);
  608.  
  609.     if( 0 != (pid = fork()) )
  610.     //  First child exit (main session process).
  611.         exit(0);
  612.     //  second child now work...
  613.  
  614.  
  615.     //  Change work directory path for unbinding from
  616.     //  device (~directory) where from was started application.
  617.     chdir( "/" );
  618.  
  619.     //  Mask of file creation mode.
  620.     //  (Premission of created files, ...)
  621.     umask(  0  );
  622.  
  623.  
  624.     //  Closing default file discriptors.
  625.     //  stdin
  626.     close(0);
  627.     open("/dev/null", O_RDONLY);
  628.  
  629.     //  stdout
  630.     close(1);
  631.     open("/dev/null", O_RDWR);
  632.  
  633.     //  stderr
  634.     close(2);
  635.     open("/dev/null", O_RDWR);
  636.  
  637.     //  Done! We are full daemon now.
  638. }
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646. #define FILE_LIMIT_CUR 100000
  647. #define FILE_LIMIT_MAX 100000
  648. void discriptors_setuping()
  649. {
  650.     rlimit ret;     ret.rlim_max = 0;   ret.rlim_cur = 0;
  651.     rlimit ret_bu;  //  ret back up.
  652.  
  653.     //getrlimit( RLIMIT_LOCKS, &ret );
  654.     getrlimit( RLIMIT_NOFILE, &ret );
  655.     ret_bu = ret;
  656.  
  657.  
  658.     if( ret.rlim_cur < FILE_LIMIT_CUR || ret.rlim_max < FILE_LIMIT_MAX )
  659.     {
  660.         cout << endl
  661.              << "File(=socket) discriptors limits: current = " << setw(7) << ret.rlim_cur << "; max = " << setw(7) << ret.rlim_max << endl;
  662.         cout << "                      Try to set: ";
  663.     }
  664.     if( ret.rlim_cur < FILE_LIMIT_CUR )
  665.     {
  666.         cout << "current = " << setw(7) << FILE_LIMIT_CUR << "; ";
  667.         ret.rlim_cur = FILE_LIMIT_CUR;
  668.     }
  669.     else cout<< "current = ok; ";
  670.     if( ret.rlim_max < FILE_LIMIT_MAX )
  671.     {
  672.         cout << "max = " << setw(7) << FILE_LIMIT_MAX << endl;
  673.         ret.rlim_max = FILE_LIMIT_MAX;
  674.     }
  675.     else cout << "max = ok" << endl;
  676.     setrlimit( RLIMIT_NOFILE, &ret );
  677.     getrlimit( RLIMIT_NOFILE, &ret );
  678.     cout << " * * *                New limits: current = " << setw(7) << ret.rlim_cur << "; max = " << setw(7) << ret.rlim_max << endl;
  679.     if( ret.rlim_cur == ret_bu.rlim_cur &&
  680.         ret.rlim_max == ret_bu.rlim_cur    ) cout << "WARNING: Hm. It's seems you are not root. It's better to run application as root to change this limits, if you have big workload there." << endl;
  681. }
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714. //  socket
  715. //#include <sys/types.h>
  716. //#include <sys/socket.h>
  717. int CreateSocket( int domain, int type, int protocol)
  718. {
  719.     int sock;
  720.     int attempt = 0;
  721.  
  722.     sock = socket( domain, type, protocol );
  723.  
  724.     while( -1 == sock )
  725.     {
  726.         if( 0 == attempt ) cerr << " ERROR. Can't create socket." << endl;
  727.  
  728.         cerr << "  (" << ++attempt << ") errno = " << errno << " = ";
  729.         PrintDetailedSocketError( errno );
  730.         cerr << "\r";
  731.  
  732.         sleep(1);
  733.         sock = socket( domain, type, protocol );
  734.     }
  735.  
  736.     cout << endl << "Socket successful created (discriptor = " << sock << ")" << endl;
  737.  
  738.     return sock;
  739. }
  740.  
  741.  
  742. //  bind
  743. //#include <sys/types.h>
  744. //#include <sys/socket.h>
  745. //  inet_ntop
  746. //#include <arpa/inet.h>
  747. void BindSocket( int sockfd, const struct sockaddr * addr, socklen_t addrlen )
  748. {
  749.     int attempt = 0;
  750.     char addr_cstr[INET6_ADDRSTRLEN+1];
  751.     //addr_cstr[0] = '\0';
  752.  
  753.     if( AF_INET  == addr->sa_family )
  754.     {
  755.         if( NULL == inet_ntop( AF_INET , (void*)&(((sockaddr_in*)addr)->sin_addr), addr_cstr, INET6_ADDRSTRLEN+1 ) )
  756.             addr_cstr[0] = '\0';
  757.     }
  758.     if( AF_INET6 == addr->sa_family )
  759.     {
  760.         if( NULL == inet_ntop( AF_INET6, (void*)&(((sockaddr_in6*)addr)->sin6_addr), addr_cstr, INET6_ADDRSTRLEN+1 ) )
  761.             addr_cstr[0] = '\0';
  762.     }
  763.  
  764.  
  765.     while( -1 == bind( sockfd, addr, addrlen ) )
  766.     {
  767.         if( 0 == attempt )
  768.         {
  769.             cerr << " ERROR. Can't bind socket(" << sockfd << ")";
  770.             if( NULL != addr_cstr )
  771.             {
  772.                 cerr << " to address [" << addr_cstr << "]:";
  773.                 if( AF_INET  == addr->sa_family ) cerr << ntohs(((sockaddr_in*) addr)->sin_port );
  774.                 if( AF_INET6 == addr->sa_family ) cerr << ntohs(((sockaddr_in6*)addr)->sin6_port);
  775.             }
  776.             cerr << "." << endl;
  777.         }
  778.  
  779.         cerr << "  (" << ++attempt << ") errno = " << errno << " = ";
  780.         PrintDetailedBindError( errno );
  781.         cerr << "\r";
  782.  
  783.         sleep(1);
  784.     }
  785.  
  786.  
  787.     cout << endl << "Socket(" << sockfd << ") successful binded";
  788.     if( NULL != addr_cstr )
  789.     {
  790.         cout << " to address [" << addr_cstr << "]:";
  791.         if( AF_INET  == addr->sa_family ) cout << ntohs(((sockaddr_in*) addr)->sin_port );
  792.         if( AF_INET6 == addr->sa_family ) cout << ntohs(((sockaddr_in6*)addr)->sin6_port);
  793.     }
  794.     cout << "." << endl;
  795. }
  796.  
  797.  
  798.  
  799. //  #include <sys/socket.h>
  800. socklen_t GetSocketAddr( int sockfd, struct sockaddr * addr, socklen_t namelen )
  801. {
  802.     int attempt = 0;
  803.     //cout << endl << "namelen = " << namelen;
  804.     socklen_t socklen = namelen;
  805.  
  806.     while( -1 == getsockname( sockfd, addr, &socklen ) )
  807.     {
  808.         if( 0 == attempt ) cerr << " Error. Can't get socket(" << sockfd << ") address." << endl;
  809.  
  810.         cerr << "  (" << ++attempt << ") errno = " << errno << " = ";
  811.         PrintDetailedGSAError( errno );
  812.         cerr << "\r";
  813.  
  814.         sleep(1);
  815.     }
  816.     //cout << "new namelen = " << socklen;
  817.     return socklen;
  818. }
  819.  
  820.  
  821. //#include <fcntl.h>
  822. bool      SetSocketAsNoblocking_once( int sockfd )
  823. {
  824.     return (-1 != fcntl( sockfd, F_SETFL, O_NONBLOCK ) );
  825. }
  826.  
  827. //#include <fcntl.h>
  828. void SetSocketAsNoblocking( int sockfd )
  829. {
  830.     int attempt = 0;
  831.  
  832.     while( -1 == fcntl( sockfd, F_SETFL, O_NONBLOCK )  )
  833.     {
  834.          if( 0 == attempt ) cerr << " Error. Can't set socket(" << sockfd <<") as nonblocking." << endl;
  835.  
  836.          cerr << "  (" << ++attempt << ") errno = " << errno << " = ";
  837.          PrintDetailedNonblockingError( errno );
  838.          cerr << "\r" << endl;
  839.  
  840.          sleep(1);
  841.     }
  842.     cout << endl << "Socket(" << sockfd << ") set as nonblocking successful" << endl;
  843. }
  844.  
  845.  
  846.  
  847.  
  848. void ListenSocket( int sockfd, int backlog )
  849. {
  850.     int attempt = 0;
  851.  
  852.     while( -1 == listen( sockfd, backlog ) )
  853.     {
  854.         if( 0 == attempt ) cerr << " ERROR. Can't set socket as listening." << endl;
  855.  
  856.         cerr << "  (" << ++attempt << ") errno = " << errno << " = ";
  857.         PrintDetailedListenError( errno );
  858.         cerr << "\r";
  859.  
  860.         sleep(1);
  861.     }
  862.  
  863.     cout << endl << "Socket(" << sockfd << ") set as listening successful." << endl;
  864. }
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873. void PrintDetailedSocketError( int err )
  874. {
  875. #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  876.     switch( err )
  877.     {
  878.         case EPROTONOSUPPORT : cerr << "EPROTONOSUPPORT = Тип протокола или указанный протокол не поддерживаются в этом домене."; break;
  879.         case EAFNOSUPPORT    : cerr << "EAFNOSUPPORT = Реализация не поддерживает указанное семейства адресов. "; break;
  880.         case ENFILE          : cerr << "ENFILE = Недостаточно памяти, чтобы создать новый сокет. "; break;
  881.         case EMFILE          : cerr << "EMFILE = Переполнение таблицы с файлами процесса."; break;
  882.         case EACCES          : cerr << "EACCES = Нет доступа к созданию сокета указанного типа и/или протокола."; break;
  883.         case ENOBUFS         : cerr << "ENOBUFS = ENOMEM = Недостаточно памяти для создания сокета."; break;
  884.         case EINVAL          : cerr << "EINVAL = Неизвестный протокол или недоступный набор протоколов."; break;
  885.         default              : cerr << "<UNKNOWN ERROR> = Неизвестная ошибка создания сокета."; break;
  886.     }
  887. #else
  888. #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  889.     switch( err )
  890.     {
  891.         case EACCES          : cerr << "EACCES = Permission to create a socket of the specified type and/or protocol is denied."; break;
  892.         case EAFNOSUPPORT    : cerr << "EAFNOSUPPORT = The implementation does not support the specified address family."; break;
  893.         case EINVAL          : cerr << "EINVAL = Unknown protocol, or protocol family not available. (OR) Invalid flags in type."; break;
  894.         case EMFILE          : cerr << "EMFILE = Process file table overflow."; break;
  895.         case ENFILE          : cerr << "ENFILE = The system limit on the total number of open files has been reached."; break;
  896.         case ENOBUFS         : cerr << "ENOBUFS = ENOMEM = Insufficient memory is available. The socket cannot be created until sufficient resources are freed."; break;
  897.         case EPROTONOSUPPORT : cerr << "EPROTONOSUPPORT = The protocol type or the specified protocol is not supported within this domain."; break;
  898.         default              : cerr << "<UNKNOWN ERROR> = Unknown error while socket creating."; break;
  899.     }
  900. #endif  //  #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  901. #endif  //  #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  902. }
  903.  
  904.  
  905.  
  906. void PrintDetailedBindError( int err )
  907. {
  908. #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  909.     switch( err )
  910.     {
  911.         case EBADF      : cerr << "EBADF = sockfd не является правильным дескриптором."; break;
  912.         case EINVAL     : cerr << "EINVAL = Сокет уже привязан к какому-то адресу. Эта ошибка в будущем может не выдаваться, смотри linux/unix/sock.c, где описаны детали."; break;
  913.         case EACCES     : cerr << "EACCES = Адрес защищен, или пользователь не является суперпользователем."; break;
  914.         case ENOTSOCK   : cerr << "ENOTSOCK = Аргумент системного вызова является дескриптором файла, а не сокета."; break;
  915.         case EADDRINUSE : cerr << "EADDRINUSE = Адрес уже используется."; break;
  916.         default         : cerr << "<UNKNOWN ERROR> = Неизвестная ошибка привязки сокета к адресу."; break;
  917. /*
  918. Нижеследующие ошибки специфичны для сокетов домена UNIX (AF_UNIX):
  919.  
  920. EINVAL
  921.     Параметр addrlen неверен, или сокет не был найден в семействе адресов AF_UNIX.
  922. EROFS
  923.     Попытка создания inode сокета на файловой системе "только для чтения".
  924. EFAULT
  925.     my_addr указывает за пределы доступного адресного пространства.
  926. ENAMETOOLONG
  927.     my_addr слишком длинно.
  928. ENOENT
  929.     Файл не существует.
  930. ENOMEM
  931.     Ядру не хватило памяти.
  932. ENOTDIR
  933.     Компонент пути, использованный как каталог, в действительности таковым не является.
  934. EACCES
  935.     Не разрешен поиск в одном из компонентов пути.
  936. ELOOP
  937.     my_addr является зацикленной символической ссылкой, то есть при подстановке возникает ссылка на неё саму.
  938. */
  939.     }
  940. #else
  941. #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  942.     switch( err )
  943.     {
  944.         case EACCES     : cerr << "EACCES = The address is protected, and the user is not the superuser."; break;
  945.         case EADDRINUSE : cerr << "EADDRINUSE = The given address is already in use."; break;
  946.         case EBADF      : cerr << "EBADF = sockfd is not a valid descriptor."; break;
  947.         case EINVAL     : cerr << "EINVAL = The socket is already bound to an address."; break;
  948.         case ENOTSOCK   : cerr << "ENOTSOCK = sockfd is a descriptor for a file, not a socket."; break;
  949.         default         : cerr << "<UNKNOWN ERROR> = Unknown error while socket binding to address."; break;
  950. /*
  951. The following errors are specific to Unix domain (AF_UNIX) sockets:
  952.  
  953. EACCES
  954.     Search permission is denied on a component of the path prefix. (See also path_resolution(7).)
  955. EADDRNOTAVAIL
  956.     A nonexistent interface was requested or the requested address was not local.
  957. EFAULT
  958.     addr points outside the user's accessible address space.
  959. EINVAL
  960.     The addrlen is wrong, or the socket was not in the AF_UNIX family.
  961. ELOOP
  962.     Too many symbolic links were encountered in resolving addr.
  963. ENAMETOOLONG
  964.     addr is too long.
  965. ENOENT
  966.     The file does not exist.
  967. ENOMEM
  968.     Insufficient kernel memory was available.
  969. ENOTDIR
  970.     A component of the path prefix is not a directory.
  971. EROFS
  972.     The socket inode would reside on a read-only file system.
  973. */
  974.     }
  975. #endif  //  #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  976. #endif  //  #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  977. }
  978.  
  979.  
  980. void PrintDetailedGSAError( int err )
  981. {
  982. #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  983.     switch( err )
  984.     {
  985.         case EBADF    : cerr << "EBADF = Неверный файловый дескриптор s."; break;
  986.         case ENOTSOCK : cerr << "ENOTSOCK = Аргумент -- это файл, а не сокет."; break;
  987.         case EINVAL   : cerr << "EINVAL = Неверное значение namelen (возможно отрицательное)."; break;
  988.         case ENOBUFS  : cerr << "ENOBUFS = В системе недостаточно ресурсов для выполнения операции."; break;
  989.         case EFAULT   : cerr << "EFAULT = name указывает за пределы доступного адресного пространства."; break;
  990.         default       : cerr << "<UNKNOWN ERROR> = Неизвестная ошибка взятия адреса сокета."; break;
  991.     }
  992. #else
  993. #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  994.     switch( err )
  995.     {
  996.         case EBADF    : cerr << "EBADF = The argument sockfd is not a valid descriptor."; break;
  997.         case EFAULT   : cerr << "EFAULT = The name argument points to memory not in a valid part of the process address space."; break;
  998.         case EINVAL   : cerr << "EINVAL = namelen is invalid (e.g., is negative)."; break;
  999.         case ENOBUFS  : cerr << "ENOBUFS = Insufficient resources were available in the system to perform the operation."; break;
  1000.         case ENOTSOCK : cerr << "ENOTSOCK = The argument s is a file, not a socket."; break;
  1001.         default       : cerr << "<UNKNOWN ERROR> = Unknown error while getting socket address."; break;
  1002.     }
  1003. #endif  //  #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  1004. #endif  //  #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  1005. }
  1006.  
  1007.  
  1008. void PrintDetailedNonblockingError( int err )
  1009. {
  1010. #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  1011.     switch( err )
  1012.     {
  1013.         case EACCES  : cout << "EACCES = "; // not break
  1014.         case EAGAIN  : cout << "EAGAIN = Операция запрещена блокировками, которые удерживаются другими процессами. (ИЛИ) Операция запрещена, потому что для этого файла другой процесс использует механизм отображения в память (memory-map). " << endl; break;
  1015.         case EBADF   : cout << "EBADF = fd не является открытым файловым дескриптором или команда была F_SETLK или F_SETLKW и режим открытия файлового дескриптора не совпадает с типом запрошенной блокировки." << endl; break;
  1016.         case EDEADLK : cout << "EDEADLK = Было обнаружено, что указанная команда F_SETLKW должна вызывать мёртвую блокировку (deadlock)." << endl; break;
  1017.         case EFAULT  : cout << "EFAULT = lock находится за пределами доступного адресного пространства." << endl; break;
  1018.         case EINTR   : cout << "EINTR = Выполнение команды F_SETLKW, было прервана сигналом. Или выполнение команд F_GETLK и F_SETLK, было прервано сигналом перед тем как была блокировка была проверка или установлена. Большинство таких ошибок случается при блокировке удалённого файла (например, блокировка через NFS), но иногда такое может случаться и на локальных файлах." << endl; break;
  1019.         case EINVAL  : cout << "EINVAL = Для F_DUPFD,значение arg отрицательное или же больше, чем максимально возможное значение. Для F_SETSIG,значение arg не содержит допустимый номер сигнала." << endl; break;
  1020.         case EMFILE  : cout << "EMFILE = Для F_DUPFD, процесс достиг максимального количества открытых файловых дескрипторов." << endl; break;
  1021.         case ENOLCK  : cout << "ENOLCK = Открыто слишком много блокировок сегментов, таблица блокировок заполнена или ошибка протокола удалённой блокировки (например, при блокировке через NFS)." << endl; break;
  1022.         case EPERM   : cout << "EPERM = Попытка сбросить флаг O_APPEND на файле, который открыт с атрибутом только для добавления." << endl; break;
  1023.         default      : cout << "<UNKNOWN ERROR> = Неизвестная ошибка при установлении сокета неблокирующим." << endl;
  1024.     }
  1025. #else
  1026. #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  1027.     switch( err )
  1028.     {
  1029.         case EACCES  : cout << "EACCES = "; // not break
  1030.         case EAGAIN  : cout << "EAGAIN = Operation is prohibited by locks held by other processes. (OR) The operation is prohibited because the file has been memory-mapped by another process." << endl; break;
  1031.         case EBADF   : cout << "EBADF = fd is not an open file descriptor, or the command was F_SETLK or F_SETLKW and the file descriptor open mode doesn't match with the type of lock requested." << endl; break;
  1032.         case EDEADLK : cout << "EDEADLK = It was detected that the specified F_SETLKW command would cause a deadlock." << endl; break;
  1033.         case EFAULT  : cout << "EFAULT = lock is outside your accessible address space." << endl; break;
  1034.         case EINTR   : cout << "EINTR = For F_SETLKW, the command was interrupted by a signal; see signal(7). For F_GETLK and F_SETLK, the command was interrupted by a signal before the lock was checked or acquired. Most likely when locking a remote file (e.g., locking over NFS), but can sometimes happen locally." << endl; break;
  1035.         case EINVAL  : cout << "EINVAL = For F_DUPFD, arg is negative or is greater than the maximum allowable value. For F_SETSIG, arg is not an allowable signal number." << endl; break;
  1036.         case EMFILE  : cout << "EMFILE = For F_DUPFD, the process already has the maximum number of file descriptors open." << endl; break;
  1037.         case ENOLCK  : cout << "ENOLCK = Too many segment locks open, lock table is full, or a remote locking protocol failed (e.g., locking over NFS)." << endl; break;
  1038.         case EPERM   : cout << "EPERM = Attempted to clear the O_APPEND flag on a file that has the append-only attribute set." << endl; break;
  1039.         default       : cerr << "<UNKNOWN ERROR> = Unknown error while setup socket as nonblocking."; break;
  1040.     }
  1041. #endif  //  #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  1042. #endif  //  #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  1043. }
  1044.  
  1045.  
  1046.  
  1047. void PrintDetailedListenError( int err )
  1048. {
  1049. #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  1050.     switch( err )
  1051.     {
  1052.         case EADDRINUSE : cerr << "EADDRINUSE = Другой сокет уже слушает на этом же порту."; break;
  1053.         case EBADF      : cerr << "EBADF = Аргумент sockfd не является правильным дескриптором."; break;
  1054.         case ENOTSOCK   : cerr << "ENOTSOCK = Аргумент sockfd не является сокетом."; break;
  1055.         case EOPNOTSUPP : cerr << "EOPNOTSUPP = Тип сокета не поддерживает операцию listen."; break;
  1056.         default       : cerr << "<UNKNOWN ERROR> = Неизвестная ошибка при установлении сокета слушающим."; break;
  1057.     }
  1058. #else
  1059. #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  1060.     switch( err )
  1061.     {
  1062.         case EADDRINUSE : cerr << "EADDRINUSE = Another socket is already listening on the same port."; break;
  1063.         case EBADF      : cerr << "EBADF = The argument sockfd is not a valid descriptor."; break;
  1064.         case ENOTSOCK   : cerr << "ENOTSOCK = The argument sockfd is not a socket."; break;
  1065.         case EOPNOTSUPP : cerr << "EOPNOTSUPP = The socket is not of a type that supports the listen() operation."; break;
  1066.         default         : cerr << "<UNKNOWN ERROR> = Unknown error while setting socket as listening."; break;
  1067.     }
  1068. #endif  //  #ifdef _SOCKETS_ERRORS_ENG_TEXT_
  1069. #endif  //  #ifdef _SOCKETS_ERRORS_RUS_TEXT_
  1070. }
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079. //  F  O  R       M  Y   S  Q  L
  1080. //  Useful for inserting binary data into blob field in table.
  1081. /*
  1082.         unsigned long temp = 0;
  1083.         for( unsigned long i = 0; i < dataSize; i++ )
  1084.         {
  1085.             if( '\0' == data[i] || '\\' == data[i] || '\'' == data[i] || '\"' == data[i] )
  1086.                 temp++;
  1087.         }
  1088.         char * slashed_data = new char [dataSize + temp];
  1089.         dataToBlobQuery( data, dataSize, slashed_data, dataSize + temp );
  1090. */
  1091.  
  1092. //  Экранизация символов.
  1093. unsigned int dataToBlobQuery(const char * data, unsigned int data_size, char * res, unsigned int res_size)
  1094. {
  1095.     unsigned int data_new_len = 0;
  1096.     while(  data_size > 0 && res_size > 0  )
  1097.     {
  1098.         switch( *data )
  1099.         {
  1100.             //  0x00 -> \0
  1101.             case '\0' :
  1102.                 if( res_size < 2 ) break;
  1103.                 *res++ = '\\';  res_size--; //  '\'
  1104.                 *res++ = '0' ;  res_size--; //  '0'
  1105.                 data_new_len++;
  1106.                 break;
  1107.  
  1108.             //  \ -> \\     ( without this text -- next `case' would be in this commentary ... my sweet, sweet bug)) )
  1109.             case '\\' :
  1110.                 if( res_size < 2 ) break;
  1111.                 *res++ = '\\';  res_size--; //  '\'
  1112.                 *res++ = '\\';  res_size--; //  '\'
  1113.                 data_new_len++;
  1114.                 break;
  1115.  
  1116.             //  ' -> \'
  1117.             case '\'' :
  1118.                 if( res_size < 2 ) break;
  1119.                 *res++ = '\\';  res_size--; //  '\'
  1120.                 *res++ = '\'';  res_size--; //  "'"
  1121.                 data_new_len++;
  1122.                 break;
  1123.  
  1124.             //  " -> \"
  1125.             case '\"' :
  1126.                 if( res_size < 2 ) break;
  1127.                 *res++ = '\\';  res_size--; //  '\'
  1128.                 *res++ = '\"';  res_size--; //  '"'
  1129.                 data_new_len++;
  1130.                 break;
  1131.  
  1132.             //  alpha -> alpha
  1133.             default:
  1134.                 *res++ = *data; res_size--;
  1135.         }
  1136.         *data        ++;
  1137.          data_size   --;
  1138.          data_new_len++;
  1139.     }
  1140.     return data_new_len;
  1141. }
  1142.  
  1143.  
  1144. struct PilerData
  1145. {
  1146.     MYSQL *pMySql;
  1147. };
  1148.  
  1149. void connectToMySql(PilerData * pPD)
  1150. {
  1151.     return;
  1152. }
  1153.  
  1154. int getHostBanList(PilerData * pPD)
  1155. {
  1156.     const unsigned int query_max_size = 512;
  1157.     char query[query_max_size];
  1158.  
  1159.     unsigned int q_size = strlen("SELECT * FROM `");
  1160.     memcpy( query, "SELECT * FROM `" , q_size );
  1161.  
  1162.     memcpy( query + q_size, "hostban", strlen("hostban") );
  1163.     q_size += strlen("hostban");
  1164.     query[q_size++] = '`';
  1165.  
  1166.  
  1167.     int attempt = 1;
  1168.     while( 0 != mysql_real_query(pPD->pMySql, query, q_size) )
  1169.     {
  1170.         cout << " ERROR. > writeToMySql function > mysql_query > getTablesFields ->- Can't process query: " << endl;
  1171.         cout << query << endl;
  1172.  
  1173.         cout << "MySQL (#" << mysql_errno(pPD->pMySql) << "): " << mysql_error( pPD->pMySql ) << endl;
  1174.         int i_mysql_errno = mysql_errno( pPD->pMySql );
  1175.         cout << "MySQL error code = " << i_mysql_errno << endl;
  1176.         //  ER_NO_SUCH_TABLE 1146
  1177.         if( ER_NO_SUCH_TABLE == i_mysql_errno ) return 1;
  1178.         if( 2006 == i_mysql_errno ) //  Server lost.
  1179.         {
  1180.             connectToMySql( pPD );   //  Reconnect to MySQL server.
  1181.         }
  1182.         else if( attempt++ > 5 ) return 2;
  1183.     }
  1184.  
  1185.     MYSQL_RES * pMySqlRes = mysql_store_result( pPD->pMySql );
  1186.  
  1187.     if( NULL != pMySqlRes )
  1188.     {
  1189.         //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //
  1190.         //  Обрабатываем результаты запроса.
  1191.  
  1192.         unsigned int fields = mysql_num_fields( pMySqlRes );
  1193.         if( fields < 2 )
  1194.         {
  1195.             mysql_free_result( pMySqlRes );
  1196.             return 1;
  1197.         }
  1198.  
  1199.         my_ulonglong rows_count = mysql_num_rows( pMySqlRes );
  1200.  
  1201.  
  1202.         MYSQL_ROW row;
  1203.  
  1204.  
  1205.     //  //  //  //  //  //  //
  1206.         int options = 0;
  1207.         const char *error;
  1208.         int erroffset;
  1209.     //  //  //  //  //  //  //
  1210.         //cout << " : rows_count = " << rows_count << endl;
  1211.         for( my_ulonglong i = 0; i < rows_count; i++ )
  1212.         {
  1213.             row = mysql_fetch_row(pMySqlRes);
  1214.             if( NULL != row )
  1215.             {
  1216.                 cout << (char *) row[1] << endl;
  1217.             }
  1218.         }
  1219.  
  1220.         mysql_free_result( pMySqlRes );
  1221.     }   //  if( NULL != pMySqlRes )
  1222.  
  1223.  
  1224.  
  1225.     return 0;
  1226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement