Guest User

Mickey_Libevent_WhyNoWorkie

a guest
Nov 18th, 2013
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.54 KB | None | 0 0
  1.  
  2. struct Connection
  3. {
  4.    Connection(): bev(NULL), isBusy( false ), needsService( false ) {}
  5.    bufferevent* bev;
  6.    char buffer[MAX_PATH];
  7.    bool isBusy;// should be a thread atomic, but whatever
  8.    bool needsService;
  9.  
  10.    void  SendBuffer()
  11.    {
  12.       assert ( isBusy == false );
  13.       isBusy = true;
  14.       struct evbuffer* outputBuffer = bufferevent_get_output( bev );
  15.       int length = strlen( buffer );
  16.       evbuffer_add( outputBuffer, buffer, length );
  17.  
  18.       needsService = false;
  19.       isBusy = false;
  20.    }
  21. };
  22.  
  23. //*************************************************
  24. //*************************************************
  25.  
  26. vector< Connection* > connections;  /// global... testing only... needs threading protections
  27.  
  28. //*************************************************
  29. //*************************************************
  30.  
  31. class MY_THREAD : public THREAD_CLASS
  32. {
  33.     int Num;
  34. protected:
  35.     void MainThreadLoop ()
  36.     {
  37.       // major threading issue here.. needs protections
  38.       vector< Connection* >::iterator it = connections.begin();
  39.       while( it != connections.end() )
  40.       {
  41.          Connection* conn = *it;
  42.          vector< Connection* >::iterator current = it++;
  43.          if( conn == NULL )
  44.          {
  45.             connections.erase( current );
  46.             continue;
  47.          }
  48.          if( conn->isBusy == false )
  49.          {
  50.             if( conn->needsService== true )
  51.             {
  52.                conn->SendBuffer();
  53.             }
  54.          }
  55.       }
  56.     }
  57. public:
  58.     MY_THREAD (bool CreateSuspended = true) : THREAD_CLASS (CreateSuspended)
  59.     {
  60.         Num = 0;
  61.     }  
  62. };
  63.  
  64. //-------------------------------------------------------------------
  65.  
  66. static void
  67. echo_read_cb(struct bufferevent *bufferEventObj, void *ctx)
  68. {
  69.    Connection* conn = static_cast< Connection * >( ctx );
  70.    assert ( conn->isBusy == false );
  71.  
  72.    vector< Connection* >::iterator it =  connections.begin();
  73.    bool found = false;
  74.    while( it != connections.end() )
  75.    {
  76.       if( conn == *it )
  77.       {
  78.          found = true;
  79.          break;
  80.       }
  81.       it++;
  82.    }
  83.    if( found == false )
  84.       assert( 0 );
  85.    
  86.    conn->isBusy = true;
  87.    int numBytesReceived = bufferevent_read( bufferEventObj, conn->buffer, sizeof( conn->buffer ) );
  88.    if( numBytesReceived > 0 )
  89.       conn->buffer[ numBytesReceived ] = 0;
  90.    conn->isBusy = false;
  91.    conn->needsService = true;
  92. }
  93.  
  94. static void
  95. echo_event_cb(struct bufferevent *bev, short events, void *ctx)
  96. {
  97.         if (events & BEV_EVENT_ERROR)
  98.                 perror("Error from bufferevent");
  99.         if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
  100.                 bufferevent_free(bev);
  101.             Connection* conn = static_cast< Connection * >( ctx );
  102.             vector< Connection* >::iterator it = connections.begin();
  103.             while( it != connections.end() )
  104.             {
  105.                if( *it == conn )
  106.                {
  107.                   *it = NULL;
  108.                }
  109.                it++;
  110.             }
  111.  
  112.         }
  113. }
  114.  
  115. static void
  116. accept_conn_cb(struct evconnlistener *listener,
  117.     evutil_socket_t fd, struct sockaddr *address, int socklen,
  118.     void *ctx)
  119. {
  120.         /* We got a new connection! Set up a bufferevent for it. */
  121.         struct event_base *base = evconnlistener_get_base(listener);
  122.         struct bufferevent *bev = bufferevent_socket_new(
  123.                 base, fd, BEV_OPT_CLOSE_ON_FREE);
  124.  
  125.         Connection* conn = new Connection;
  126.         conn->bev = bev;
  127.        
  128.         strcpy( conn->buffer, "ready" );
  129.         conn->needsService = true;
  130.         connections.push_back( conn );
  131.  
  132.         bufferevent_setcb( bev, echo_read_cb, NULL, echo_event_cb, conn );
  133.  
  134.         bufferevent_enable(bev, EV_READ|EV_WRITE);
  135. }
  136.  
  137. static void
  138. accept_error_cb(struct evconnlistener *listener, void *ctx)
  139. {
  140.         struct event_base *base = evconnlistener_get_base(listener);
  141.         int err = EVUTIL_SOCKET_ERROR();
  142.         fprintf(stderr, "Got an error %d (%s) on the listener. "
  143.                 "Shutting down.\n", err, evutil_socket_error_to_string(err));
  144.  
  145.         event_base_loopexit(base, NULL);
  146. }
  147.  
  148. int
  149. main(int argc, char **argv)
  150. {
  151.    WSADATA WsaData;
  152.     WSAStartup( MAKEWORD(2,2), &WsaData );
  153.         struct event_base *base;
  154.         struct evconnlistener *listener;
  155.         struct sockaddr_in sin;
  156.  
  157.         int port = 5555;
  158.  
  159.         if (argc > 1) {
  160.                 port = atoi(argv[1]);
  161.         }
  162.         if (port<=0 || port>65535) {
  163.                 puts("Invalid port");
  164.                 return 1;
  165.         }
  166.  
  167.         base = event_base_new();
  168.         if (!base) {
  169.                 puts("Couldn't open event base");
  170.                 return 1;
  171.         }
  172.  
  173.         /* Clear the sockaddr before using it, in case there are extra
  174.          * platform-specific fields that can mess us up. */
  175.         memset(&sin, 0, sizeof(sin));/* This is an INET address */
  176.         sin.sin_family = AF_INET;/* Listen on 0.0.0.0 */
  177.         sin.sin_addr.s_addr = htonl(0);/* Listen on the given port. */
  178.         sin.sin_port = htons(port);
  179.  
  180.         listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
  181.             LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
  182.             (struct sockaddr*)&sin, sizeof(sin));
  183.         if (!listener) {
  184.                 perror("Couldn't create listener");
  185.                 return 1;
  186.         }
  187.         evconnlistener_set_error_cb(listener, accept_error_cb);
  188.  
  189.         MY_THREAD mainThread;
  190.         mainThread.SetAlarm( 30 );// fire every 30 millisecs
  191.  
  192.         mainThread.StartThread();
  193.  
  194.         event_base_dispatch(base);
  195.         return 0;
  196. }
Advertisement
Add Comment
Please, Sign In to add comment