/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. #ifndef AWS_CLIENT_SOCKET_H
  6. #include <AWSClientSocket.h>
  7. #endif
  8. #ifndef ESF_ASSERT_H
  9. #include <ESFAssert.h>
  10. #endif
  11. #ifndef ESF_NULL_LOGGER_H
  12. #include <ESFNullLogger.h>
  13. #endif
  14. #ifndef ESF_SYSTEM_ALLOCATOR_H
  15. #include <ESFSystemAllocator.h>
  16. #endif
  17. #ifndef ESF_BUFFER_POOL_H
  18. #include <ESFBufferPool.h>
  19. #endif
  20. #ifndef ESF_THREAD_H
  21. #include <ESFThread.h>
  22. #endif
  23. // TODO buffer pool size not hardcoded
  24. bool AWSClientSocket::_ReuseConnections = true;
  25. ESFBufferPool AWSClientSocket::_BufferPool(1024, 900, ESFSystemAllocator::GetInstance());
  26. AWSClientSocket::AWSClientSocket(AWSClientSocketFactory *factory,
  27. AWSPerformanceCounter *counter,
  28. int requestsPerConnection,
  29. const ESFSocketAddress &peer,
  30. ESFCleanupHandler *cleanupHandler,
  31. ESFLogger *logger) :
  32. _requestsPerConnection(requestsPerConnection),
  33. _inReadMode(false),
  34. _successCounter(counter),
  35. _logger(logger ? logger : ESFNullLogger::GetInstance()),
  36. _cleanupHandler(cleanupHandler),
  37. _buffer(0),
  38. _socket(peer, false),
  39. _factory(factory)
  40. {
  41. setupBuffer();
  42. AWSPerformanceCounter::GetTime(&_start);
  43. }
  44. AWSClientSocket::~AWSClientSocket()
  45. {
  46. }
  47. bool AWSClientSocket::wantAccept()
  48. {
  49. return false;
  50. }
  51. bool AWSClientSocket::wantConnect()
  52. {
  53. return false == _socket.isConnected();
  54. }
  55. bool AWSClientSocket::wantRead()
  56. {
  57. if (0 == _buffer && false == setupBuffer())
  58. {
  59. return false;
  60. }
  61. return _socket.isConnected() && _inReadMode && 0 < _buffer->getWritable();
  62. }
  63. bool AWSClientSocket::wantWrite()
  64. {
  65. if (0 == _buffer && false == setupBuffer())
  66. {
  67. return false;
  68. }
  69. return _socket.isConnected() && false == _inReadMode && 0 < _buffer->getReadable();
  70. }
  71. bool AWSClientSocket::isIdle() // todo pass in current time to reduce number of syscalls
  72. {
  73. return false; // todo - implement
  74. }
  75. bool AWSClientSocket::handleAcceptEvent(ESFFlag *isRunning, ESFLogger *logger)
  76. {
  77. if (_logger->isLoggable(ESFLogger::Warning))
  78. {
  79. _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
  80. "[socket:%d] Cannot handle accept events",
  81. _socket.getSocketDescriptor());
  82. }
  83. return true; // todo - keep in multiplexer
  84. }
  85. bool AWSClientSocket::handleConnectEvent(ESFFlag *isRunning, ESFLogger *logger)
  86. {
  87. if (0 == _buffer && false == setupBuffer())
  88. {
  89. return false;
  90. }
  91. ESF_ASSERT(_socket.isConnected());
  92. if (_logger->isLoggable(ESFLogger::Debug))
  93. {
  94. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  95. "[socket:%d] Connected",
  96. _socket.getSocketDescriptor());
  97. }
  98. ESF_ASSERT(wantWrite());
  99. return handleWritableEvent(isRunning, logger);
  100. }
  101. bool AWSClientSocket::handleReadableEvent(ESFFlag *isRunning, ESFLogger *logger)
  102. {
  103. if (0 == _buffer && false == setupBuffer())
  104. {
  105. return false;
  106. }
  107. ESF_ASSERT(_buffer);
  108. ESF_ASSERT(_inReadMode);
  109. ESF_ASSERT(_buffer->isWritable());
  110. ESFSSize result = 0;
  111. ESFError error = ESF_SUCCESS;
  112. while (isRunning->get() && _buffer->isWritable())
  113. {
  114. result = _socket.receive(_buffer);
  115. if (0 > result)
  116. {
  117. error = ESFGetLastError();
  118. if (ESF_AGAIN == error)
  119. {
  120. if (_logger->isLoggable(ESFLogger::Debug))
  121. {
  122. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  123. "[socket:%d] not ready for read",
  124. _socket.getSocketDescriptor());
  125. }
  126. return true; // keep in multiplexer
  127. }
  128. if (ESF_INTR == error)
  129. {
  130. if (_logger->isLoggable(ESFLogger::Debug))
  131. {
  132. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  133. "[socket:%d] interrupted",
  134. _socket.getSocketDescriptor());
  135. }
  136. continue;
  137. }
  138. return handleErrorEvent(error, isRunning, logger);
  139. }
  140. if (0 == result)
  141. {
  142. return handleEndOfFileEvent(isRunning, logger);
  143. }
  144. if (_logger->isLoggable(ESFLogger::Debug))
  145. {
  146. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  147. "[socket:%d] Read %d bytes",
  148. _socket.getSocketDescriptor(), result);
  149. }
  150. }
  151. if (! isRunning->get())
  152. {
  153. return false; // remove from multiplexer
  154. }
  155. _successCounter->addObservation(&_start);
  156. _start.tv_usec = 0;
  157. _start.tv_sec = 0;
  158. if (_logger->isLoggable(ESFLogger::Debug))
  159. {
  160. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  161. "[socket:%d] Received complete response",
  162. _socket.getSocketDescriptor());
  163. }
  164. _inReadMode = false;
  165. ESF_ASSERT(wantWrite());
  166. if (false == _ReuseConnections)
  167. {
  168. return false; // remove from multiplexer
  169. }
  170. AWSPerformanceCounter::GetTime(&_start);
  171. return true; // keep in multiplexer - also yields to other sockets
  172. }
  173. bool AWSClientSocket::handleWritableEvent(ESFFlag *isRunning, ESFLogger *logger)
  174. {
  175. if (0 == _buffer && false == setupBuffer())
  176. {
  177. return false;
  178. }
  179. ESF_ASSERT(_buffer);
  180. ESF_ASSERT(false == _inReadMode);
  181. ESF_ASSERT(_buffer->isReadable());
  182. ESFSSize result = 0;
  183. ESFError error = ESF_SUCCESS;
  184. while (isRunning->get() && _buffer->isReadable())
  185. {
  186. result = _socket.send(_buffer);
  187. if (0 > result)
  188. {
  189. error = ESFGetLastError();
  190. if (ESF_AGAIN == error)
  191. {
  192. if (_logger->isLoggable(ESFLogger::Debug))
  193. {
  194. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  195. "[socket:%d] Not ready for write",
  196. _socket.getSocketDescriptor());
  197. }
  198. return true; // keep in multiplexer
  199. }
  200. if (ESF_INTR == error)
  201. {
  202. if (_logger->isLoggable(ESFLogger::Debug))
  203. {
  204. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  205. "[socket:%d] Interrupted",
  206. _socket.getSocketDescriptor());
  207. }
  208. continue;
  209. }
  210. return handleErrorEvent(error, isRunning, logger);
  211. }
  212. if (_logger->isLoggable(ESFLogger::Debug))
  213. {
  214. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  215. "[socket:%d] Wrote %d bytes",
  216. _socket.getSocketDescriptor(), result);
  217. }
  218. }
  219. if (! isRunning->get())
  220. {
  221. return false; // remove from multiplexer
  222. }
  223. if (_logger->isLoggable(ESFLogger::Debug))
  224. {
  225. _logger->log(ESFLogger::Debug, __FILE__, __LINE__,
  226. "[socket:%d] Sent complete request",
  227. _socket.getSocketDescriptor());
  228. }
  229. _inReadMode = true;
  230. ESF_ASSERT(false == wantRead());
  231. _buffer->compact();
  232. ESF_ASSERT(true == wantRead());
  233. return handleReadableEvent(isRunning, logger);
  234. }
  235. bool AWSClientSocket::handleErrorEvent(ESFError errorCode, ESFFlag *isRunning, ESFLogger *logger)
  236. {
  237. if (_logger->isLoggable(ESFLogger::Warning))
  238. {
  239. char buffer[100];
  240. char dottedAddress[16];
  241. _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
  242. ESFDescribeError(errorCode, buffer, sizeof(buffer));
  243. _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
  244. "[socket:%d] Error from server %s: %s",
  245. _socket.getSocketDescriptor(), dottedAddress, buffer);
  246. }
  247. return false; // remove from multiplexer
  248. }
  249. bool AWSClientSocket::handleEndOfFileEvent(ESFFlag *isRunning, ESFLogger *logger)
  250. {
  251. if (_logger->isLoggable(ESFLogger::Debug))
  252. {
  253. char dottedAddress[16];
  254. _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
  255. _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
  256. "[socket:%d] Server %s closed socket",
  257. _socket.getSocketDescriptor(), dottedAddress);
  258. }
  259. return false; // remove from multiplexer
  260. }
  261. bool AWSClientSocket::handleIdleEvent(ESFFlag *isRunning, ESFLogger *logger)
  262. {
  263. if (_logger->isLoggable(ESFLogger::Debug))
  264. {
  265. char dottedAddress[16];
  266. _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
  267. _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
  268. "[socket:%d] Server %s is idle",
  269. _socket.getSocketDescriptor(), dottedAddress);
  270. }
  271. return false; // remove from multiplexer
  272. }
  273. bool AWSClientSocket::handleRemoveEvent(ESFFlag *isRunning, ESFLogger *logger)
  274. {
  275. if (_logger->isLoggable(ESFLogger::Debug))
  276. {
  277. char dottedAddress[16];
  278. _socket.getPeerAddress().getIPAddress(dottedAddress, sizeof(dottedAddress));
  279. _logger->log(ESFLogger::Warning, __FILE__, __LINE__,
  280. "[socket:%d] Closing socket for server %s",
  281. _socket.getSocketDescriptor(), dottedAddress);
  282. }
  283. _BufferPool.releaseBuffer(_buffer);
  284. _buffer = 0;
  285. _socket.close();
  286. if (false == isRunning->get())
  287. {
  288. return true; // call cleanup handler on us after this returns
  289. }
  290. ESFError error = _factory->addNewConnection(_socket.getPeerAddress());
  291. if (ESF_SUCCESS != error)
  292. {
  293. if (logger->isLoggable(ESFLogger::Critical))
  294. {
  295. char buffer[100];
  296. ESFDescribeError(error, buffer, sizeof(buffer));
  297. logger->log(ESFLogger::Critical, __FILE__, __LINE__,
  298. "[socket] Cannot add new connection: %s", buffer);
  299. }
  300. }
  301. return true; // call cleanup handler on us after this returns
  302. }
  303. SOCKET AWSClientSocket::getSocketDescriptor() const
  304. {
  305. return _socket.getSocketDescriptor();
  306. }
  307. ESFCleanupHandler *AWSClientSocket::getCleanupHandler()
  308. {
  309. return _cleanupHandler;
  310. }
  311. const char *AWSClientSocket::getName() const
  312. {
  313. return "AWSClientSocket";
  314. }
  315. bool AWSClientSocket::run(ESFFlag *isRunning)
  316. {
  317. return false; // todo - log warning
  318. }
  319. bool AWSClientSocket::setupBuffer()
  320. {
  321. if (_buffer)
  322. {
  323. return true;
  324. }
  325. _buffer = _BufferPool.acquireBuffer();
  326. if (! _buffer)
  327. {
  328. if (_logger->isLoggable(ESFLogger::Error))
  329. {
  330. _logger->log(ESFLogger::Error, __FILE__, __LINE__,
  331. "[socket:%d] Cannot acquire new buffer",
  332. _socket.getSocketDescriptor());
  333. }
  334. return false;
  335. }
  336. ESF_ASSERT(_buffer->isWritable());
  337. _buffer->clear();
  338. unsigned int capacity = _buffer->getCapacity();
  339. memset(_buffer->getBuffer(), ESFThread::GetThreadId() % 256, capacity);
  340. _buffer->setWritePosition(capacity);
  341. _inReadMode = false;
  342. ESF_ASSERT(capacity = _buffer->getReadable());
  343. ESF_ASSERT(0 == _buffer->getWritable());
  344. return true;
  345. }