/raw_echo_server/client/AWSClientSocket.cpp
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