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