PageRenderTime 33ms CodeModel.GetById 13ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/raw_echo_server/client/AWSClientSocket.cpp

http://github.com/jtblatt/duderino
C++ | 447 lines | 340 code | 102 blank | 5 comment | 72 complexity | 06df6a41fe4cf8bf05085dadea9b3316 MD5 | raw file
  1/* Copyright (c) 2009 Yahoo! Inc.  All rights reserved.
  2 * The copyrights embodied in the content of this file are licensed by Yahoo! Inc.
  3 * under the BSD (revised) open source license.
  4 */
  5
  6#ifndef AWS_CLIENT_SOCKET_H
  7#include <AWSClientSocket.h>
  8#endif
  9
 10#ifndef ESF_ASSERT_H
 11#include <ESFAssert.h>
 12#endif
 13
 14#ifndef ESF_NULL_LOGGER_H
 15#include <ESFNullLogger.h>
 16#endif
 17
 18#ifndef ESF_SYSTEM_ALLOCATOR_H
 19#include <ESFSystemAllocator.h>
 20#endif
 21
 22#ifndef ESF_BUFFER_POOL_H
 23#include <ESFBufferPool.h>
 24#endif
 25
 26#ifndef ESF_THREAD_H
 27#include <ESFThread.h>
 28#endif
 29
 30// TODO buffer pool size not hardcoded
 31bool AWSClientSocket::_ReuseConnections = true;
 32ESFBufferPool AWSClientSocket::_BufferPool(1024, 900, ESFSystemAllocator::GetInstance());
 33
 34AWSClientSocket::AWSClientSocket(AWSClientSocketFactory *factory,
 35                                 AWSPerformanceCounter *counter,
 36                                 int requestsPerConnection,
 37                                 const ESFSocketAddress &peer,
 38                                 ESFCleanupHandler *cleanupHandler,
 39                                 ESFLogger *logger) :
 40    _requestsPerConnection(requestsPerConnection),
 41    _inReadMode(false),
 42    _successCounter(counter),
 43    _logger(logger ? logger : ESFNullLogger::GetInstance()),
 44    _cleanupHandler(cleanupHandler),
 45    _buffer(0),
 46    _socket(peer, false),
 47    _factory(factory)
 48{
 49    setupBuffer();
 50    AWSPerformanceCounter::GetTime(&_start);
 51}
 52
 53AWSClientSocket::~AWSClientSocket()
 54{
 55}
 56
 57bool AWSClientSocket::wantAccept()
 58{
 59    return false;
 60}
 61
 62bool AWSClientSocket::wantConnect()
 63{
 64    return false == _socket.isConnected();
 65}
 66
 67bool AWSClientSocket::wantRead()
 68{
 69    if (0 == _buffer && false == setupBuffer())
 70    {
 71        return false;
 72    }
 73
 74    return _socket.isConnected() && _inReadMode && 0 < _buffer->getWritable();
 75}
 76
 77bool AWSClientSocket::wantWrite()
 78{
 79    if (0 == _buffer && false == setupBuffer())
 80    {
 81        return false;
 82    }
 83
 84    return _socket.isConnected() && false == _inReadMode && 0 < _buffer->getReadable();
 85}
 86
 87bool AWSClientSocket::isIdle()  // todo pass in current time to reduce number of syscalls
 88{
 89    return false;   // todo - implement
 90}
 91
 92bool AWSClientSocket::handleAcceptEvent(ESFFlag *isRunning, ESFLogger *logger)
 93{
 94    if (_logger->isLoggable(ESFLogger::Warning))
 95    {
 96        _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
 97                     "[socket:%d] Cannot handle accept events",
 98                     _socket.getSocketDescriptor());
 99    }
100
101    return true;    // todo - keep in multiplexer
102}
103
104bool AWSClientSocket::handleConnectEvent(ESFFlag *isRunning, ESFLogger *logger)
105{
106    if (0 == _buffer && false == setupBuffer())
107    {
108        return false;
109    }
110
111    ESF_ASSERT(_socket.isConnected());
112
113    if (_logger->isLoggable(ESFLogger::Debug))
114    {
115        _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
116                     "[socket:%d] Connected",
117                     _socket.getSocketDescriptor());
118    }
119
120    ESF_ASSERT(wantWrite());
121
122    return handleWritableEvent(isRunning, logger);
123}
124
125bool AWSClientSocket::handleReadableEvent(ESFFlag *isRunning, ESFLogger *logger)
126{
127    if (0 == _buffer && false == setupBuffer())
128    {
129        return false;
130    }
131
132    ESF_ASSERT(_buffer);
133    ESF_ASSERT(_inReadMode);
134    ESF_ASSERT(_buffer->isWritable());
135
136    ESFSSize result = 0;
137    ESFError error = ESF_SUCCESS;
138
139    while (isRunning->get() && _buffer->isWritable())
140    {
141        result = _socket.receive(_buffer);
142
143        if (0 > result)
144        {
145            error = ESFGetLastError();
146
147            if (ESF_AGAIN == error)
148            {
149                if (_logger->isLoggable(ESFLogger::Debug))
150                {
151                    _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
152                                 "[socket:%d] not ready for read",
153                                 _socket.getSocketDescriptor());
154                }
155
156                return true;    // keep in multiplexer
157            }
158
159            if (ESF_INTR == error)
160            {
161                if (_logger->isLoggable(ESFLogger::Debug))
162                {
163                    _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
164                                 "[socket:%d] interrupted",
165                                 _socket.getSocketDescriptor());
166                }
167
168                continue;
169            }
170
171            return handleErrorEvent(error, isRunning, logger);
172        }
173
174        if (0 == result)
175        {
176            return handleEndOfFileEvent(isRunning, logger);
177        }
178
179        if (_logger->isLoggable(ESFLogger::Debug))
180        {
181            _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
182                         "[socket:%d] Read %d bytes",
183                         _socket.getSocketDescriptor(), result);
184        }
185    }
186
187    if (! isRunning->get())
188    {
189        return false;   // remove from multiplexer
190    }
191
192    _successCounter->addObservation(&_start);
193
194    _start.tv_usec = 0;
195    _start.tv_sec = 0;
196
197    if (_logger->isLoggable(ESFLogger::Debug))
198    {
199        _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
200                     "[socket:%d] Received complete response",
201                     _socket.getSocketDescriptor());
202    }
203
204    _inReadMode = false;
205
206    ESF_ASSERT(wantWrite());
207
208    if (false == _ReuseConnections)
209    {
210        return false;   // remove from multiplexer
211    }
212
213    AWSPerformanceCounter::GetTime(&_start);
214
215    return true;    // keep in multiplexer - also yields to other sockets
216}
217
218bool AWSClientSocket::handleWritableEvent(ESFFlag *isRunning, ESFLogger *logger)
219{
220    if (0 == _buffer && false == setupBuffer())
221    {
222        return false;
223    }
224
225    ESF_ASSERT(_buffer);
226    ESF_ASSERT(false == _inReadMode);
227    ESF_ASSERT(_buffer->isReadable());
228
229    ESFSSize result = 0;
230    ESFError error = ESF_SUCCESS;
231
232    while (isRunning->get() && _buffer->isReadable())
233    {
234        result = _socket.send(_buffer);
235
236        if (0 > result)
237        {
238            error = ESFGetLastError();
239
240            if (ESF_AGAIN == error)
241            {
242                if (_logger->isLoggable(ESFLogger::Debug))
243                {
244                    _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
245                                 "[socket:%d] Not ready for write",
246                                 _socket.getSocketDescriptor());
247                }
248
249                return true;    // keep in multiplexer
250            }
251
252            if (ESF_INTR == error)
253            {
254                if (_logger->isLoggable(ESFLogger::Debug))
255                {
256                    _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
257                                 "[socket:%d] Interrupted",
258                                 _socket.getSocketDescriptor());
259                }
260
261                continue;
262            }
263
264            return handleErrorEvent(error, isRunning, logger);
265        }
266
267        if (_logger->isLoggable(ESFLogger::Debug))
268        {
269            _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
270                         "[socket:%d] Wrote %d bytes",
271                         _socket.getSocketDescriptor(), result);
272        }
273    }
274
275    if (! isRunning->get())
276    {
277        return false;   // remove from multiplexer
278    }
279
280    if (_logger->isLoggable(ESFLogger::Debug))
281    {
282        _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
283                     "[socket:%d] Sent complete request",
284                     _socket.getSocketDescriptor());
285    }
286
287    _inReadMode = true;
288
289    ESF_ASSERT(false == wantRead());
290
291    _buffer->compact();
292
293    ESF_ASSERT(true == wantRead());
294
295    return handleReadableEvent(isRunning, logger);
296}
297
298bool AWSClientSocket::handleErrorEvent(ESFError errorCode, ESFFlag *isRunning, ESFLogger *logger)
299{
300    if (_logger->isLoggable(ESFLogger::Warning))
301    {
302        char buffer[100];
303        char dottedAddress[16];
304
305        _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
306        ESFDescribeError(errorCode, buffer, sizeof(buffer));
307
308        _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
309                     "[socket:%d] Error from server %s: %s",
310                     _socket.getSocketDescriptor(), dottedAddress, buffer);
311    }
312
313    return false;    // remove from multiplexer
314}
315
316bool AWSClientSocket::handleEndOfFileEvent(ESFFlag *isRunning, ESFLogger *logger)
317{
318    if (_logger->isLoggable(ESFLogger::Debug))
319    {
320        char dottedAddress[16];
321
322        _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
323
324        _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
325                     "[socket:%d] Server %s closed socket",
326                     _socket.getSocketDescriptor(), dottedAddress);
327    }
328
329    return false;    // remove from multiplexer
330}
331
332bool AWSClientSocket::handleIdleEvent(ESFFlag *isRunning, ESFLogger *logger)
333{
334    if (_logger->isLoggable(ESFLogger::Debug))
335    {
336        char dottedAddress[16];
337
338        _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
339
340        _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
341                     "[socket:%d] Server %s is idle",
342                     _socket.getSocketDescriptor(), dottedAddress);
343    }
344
345    return false;    // remove from multiplexer
346}
347
348bool AWSClientSocket::handleRemoveEvent(ESFFlag *isRunning, ESFLogger *logger)
349{
350    if (_logger->isLoggable(ESFLogger::Debug))
351    {
352        char dottedAddress[16];
353
354        _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
355
356        _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
357                     "[socket:%d] Closing socket for server %s",
358                     _socket.getSocketDescriptor(), dottedAddress);
359    }
360
361    _BufferPool.releaseBuffer(_buffer);
362    _buffer = 0;
363    _socket.close();
364
365    if (false == isRunning->get())
366    {
367        return true;    // call cleanup handler on us after this returns
368    }
369
370    ESFError error = _factory->addNewConnection(_socket.getPeerAddress());
371
372    if (ESF_SUCCESS != error)
373    {
374        if (logger->isLoggable(ESFLogger::Critical))
375        {
376            char buffer[100];
377
378            ESFDescribeError(error, buffer, sizeof(buffer));
379
380            logger->log(ESFLogger::Critical, __FILE__, __LINE__,
381                        "[socket] Cannot add new connection: %s", buffer);
382        }
383    }
384
385    return true;    // call cleanup handler on us after this returns
386}
387
388SOCKET AWSClientSocket::getSocketDescriptor() const
389{
390    return _socket.getSocketDescriptor();
391}
392
393ESFCleanupHandler *AWSClientSocket::getCleanupHandler()
394{
395    return _cleanupHandler;
396}
397
398const char *AWSClientSocket::getName() const
399{
400    return "AWSClientSocket";
401}
402
403bool AWSClientSocket::run(ESFFlag *isRunning)
404{
405    return false;   // todo - log warning
406}
407
408bool AWSClientSocket::setupBuffer()
409{
410    if (_buffer)
411    {
412        return true;
413    }
414
415    _buffer = _BufferPool.acquireBuffer();
416
417    if (! _buffer)
418    {
419        if (_logger->isLoggable(ESFLogger::Error))
420        {
421            _logger->log(ESFLogger::Error, __FILE__, __LINE__,
422                         "[socket:%d] Cannot acquire new buffer",
423                         _socket.getSocketDescriptor());
424        }
425
426        return false;
427    }
428
429    ESF_ASSERT(_buffer->isWritable());
430
431    _buffer->clear();
432
433    unsigned int capacity = _buffer->getCapacity();
434
435    memset(_buffer->getBuffer(), ESFThread::GetThreadId() % 256, capacity);
436
437    _buffer->setWritePosition(capacity);
438
439    _inReadMode = false;
440
441    ESF_ASSERT(capacity = _buffer->getReadable());
442    ESF_ASSERT(0 == _buffer->getWritable());
443
444    return true;
445}
446
447