PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/include/libnode/detail/net/socket.h

https://github.com/danielchow/libnode
C Header | 1019 lines | 848 code | 156 blank | 15 comment | 154 complexity | 85a167911cfed6b239c5df244b6e69bc MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause
  1. // Copyright (c) 2012-2014 Plenluno All rights reserved.
  2. #ifndef LIBNODE_DETAIL_NET_SOCKET_H_
  3. #define LIBNODE_DETAIL_NET_SOCKET_H_
  4. #include <libnode/config.h>
  5. #include <libnode/dns.h>
  6. #include <libnode/net.h>
  7. #include <libnode/process.h>
  8. #include <libnode/string_decoder.h>
  9. #include <libnode/timer.h>
  10. #include <libnode/uv/error.h>
  11. #include <libnode/detail/uv/stream_common.h>
  12. #include <libnode/detail/events/event_emitter.h>
  13. #include <libj/json.h>
  14. #include <libj/this.h>
  15. #include <assert.h>
  16. namespace libj {
  17. namespace node {
  18. namespace detail {
  19. namespace http {
  20. class Parser;
  21. class OutgoingMessage;
  22. } // namespace http
  23. } // namespace detail
  24. } // namespace node
  25. } // namespace libj
  26. namespace libj {
  27. namespace node {
  28. namespace detail {
  29. namespace net {
  30. class Socket : public events::EventEmitter<node::net::Socket> {
  31. public:
  32. LIBJ_MUTABLE_DEFS(Socket, LIBNODE_NET_SOCKET);
  33. static Ptr create(libj::JsObject::CPtr options = libj::JsObject::null()) {
  34. LIBJ_STATIC_SYMBOL_DEF(OPTION_HANDLE, "handle");
  35. if (options) {
  36. Boolean allowHalfOpen =
  37. to<Boolean>(options->get(OPTION_ALLOW_HALF_OPEN));
  38. uv_file fd;
  39. if (to<uv_file>(options->get(OPTION_FD), &fd)) {
  40. return create(fd, allowHalfOpen);
  41. } else {
  42. uv::Stream* handle =
  43. to<uv::Stream*>(options->get(OPTION_HANDLE));
  44. return create(handle, allowHalfOpen);
  45. }
  46. } else {
  47. return create(static_cast<uv::Stream*>(NULL), false);
  48. }
  49. }
  50. static Ptr create(uv::Stream* handle, Boolean allowHalfOpen) {
  51. Socket* sock = new Socket();
  52. sock->handle_ = handle;
  53. if (allowHalfOpen) sock->setFlag(ALLOW_HALF_OPEN);
  54. return create(sock);
  55. }
  56. virtual Boolean readable() const {
  57. return hasFlag(READABLE);
  58. }
  59. virtual Boolean writable() const {
  60. return hasFlag(WRITABLE);
  61. }
  62. virtual Boolean setEncoding(Buffer::Encoding enc) {
  63. switch (enc) {
  64. case Buffer::UTF8:
  65. case Buffer::UTF16BE:
  66. case Buffer::UTF16LE:
  67. case Buffer::UTF32BE:
  68. case Buffer::UTF32LE:
  69. case Buffer::HEX:
  70. case Buffer::NONE:
  71. decoder_ = StringDecoder::create(enc);
  72. return true;
  73. default:
  74. decoder_ = StringDecoder::null();
  75. return false;
  76. }
  77. }
  78. virtual Boolean pause() {
  79. setFlag(PAUSED);
  80. return handle_ && !hasFlag(CONNECTING) && !handle_->readStop();
  81. }
  82. virtual Boolean resume() {
  83. unsetFlag(PAUSED);
  84. return handle_ && !hasFlag(CONNECTING) && !handle_->readStart();
  85. }
  86. virtual Boolean write(
  87. const Value& data,
  88. Buffer::Encoding enc = Buffer::NONE) {
  89. return write(data, enc, JsFunction::null());
  90. }
  91. virtual Boolean end(
  92. const Value& data = UNDEFINED,
  93. Buffer::Encoding enc = Buffer::NONE) {
  94. if (hasFlag(CONNECTING) && !hasFlag(SHUTDOWN_QUEUED)) {
  95. if (!data.isUndefined()) write(data, enc);
  96. unsetFlag(WRITABLE);
  97. setFlag(SHUTDOWN_QUEUED);
  98. }
  99. if (!hasFlag(WRITABLE)) {
  100. return false;
  101. } else {
  102. unsetFlag(WRITABLE);
  103. }
  104. if (!data.isUndefined()) write(data, enc);
  105. if (!hasFlag(READABLE)) {
  106. return destroySoon();
  107. } else {
  108. setFlag(SHUTDOWN);
  109. uv::Shutdown* req = handle_->shutdown();
  110. if (req) {
  111. AfterShutdown::Ptr afterShutdown(new AfterShutdown(this));
  112. req->onComplete = afterShutdown;
  113. return true;
  114. } else {
  115. destroy(node::uv::Error::last());
  116. return false;
  117. }
  118. }
  119. }
  120. virtual Boolean destroy() {
  121. return destroy(Error::null());
  122. }
  123. virtual Boolean destroySoon() {
  124. if (hasFlag(DESTROYED)) return false;
  125. unsetFlag(WRITABLE);
  126. setFlag(DESTROY_SOON);
  127. if (pendingWriteReqs_) {
  128. return true;
  129. } else {
  130. return destroy();
  131. }
  132. }
  133. virtual libj::JsObject::Ptr address() {
  134. if (handle_ && handle_->type() == UV_TCP) {
  135. uv::Tcp* tcp = static_cast<uv::Tcp*>(handle_);
  136. return tcp->getSockName();
  137. } else {
  138. return libj::JsObject::null();
  139. }
  140. }
  141. virtual String::CPtr remoteAddress() {
  142. LIBJ_STATIC_SYMBOL_DEF(symAddress, "address");
  143. if (handle_ && handle_->type() == UV_TCP) {
  144. uv::Tcp* tcp = static_cast<uv::Tcp*>(handle_);
  145. return tcp->getPeerName()->getCPtr<String>(symAddress);
  146. } else {
  147. return String::null();
  148. }
  149. }
  150. virtual Int remotePort() {
  151. LIBJ_STATIC_SYMBOL_DEF(symPort, "port");
  152. if (handle_ && handle_->type() == UV_TCP) {
  153. uv::Tcp* tcp = static_cast<uv::Tcp*>(handle_);
  154. Int port = to<Int>(tcp->getPeerName()->get(symPort), -1);
  155. return port;
  156. } else {
  157. return -1;
  158. }
  159. }
  160. virtual Size bytesRead() const {
  161. return bytesRead_;
  162. }
  163. virtual Size bytesWritten() const {
  164. Size bytes = bytesDispatched_;
  165. Size len = connectBufQueue_->length();
  166. for (Size i = 0; i < len; i++) {
  167. bytes += connectBufQueue_->getCPtr<Buffer>(i)->length();
  168. }
  169. return bytes;
  170. }
  171. virtual Boolean connect(
  172. Int port,
  173. String::CPtr host = String::null(),
  174. JsFunction::Ptr cb = JsFunction::null()) {
  175. if (port < 0) {
  176. return false;
  177. } else {
  178. connect(port, host, String::null(), String::null(), cb);
  179. return true;
  180. }
  181. }
  182. virtual Boolean connect(
  183. String::CPtr path,
  184. JsFunction::Ptr cb = JsFunction::null()) {
  185. if (path) {
  186. connect(0, String::null(), String::null(), path, cb);
  187. return true;
  188. } else {
  189. return false;
  190. }
  191. }
  192. virtual void setTimeout(
  193. UInt timeout,
  194. JsFunction::Ptr callback = JsFunction::null()) {
  195. if (timeout) {
  196. startTimer(timeout);
  197. if (callback) {
  198. once(EVENT_TIMEOUT, callback);
  199. }
  200. } else {
  201. finishTimer();
  202. if (callback) {
  203. removeListener(EVENT_TIMEOUT, callback);
  204. }
  205. }
  206. }
  207. virtual Boolean setNoDelay(Boolean noDelay) {
  208. if (handle_ && handle_->type() == UV_TCP) {
  209. uv::Tcp* tcp = static_cast<uv::Tcp*>(handle_);
  210. return !tcp->setNoDelay(noDelay);
  211. } else {
  212. return false;
  213. }
  214. }
  215. virtual Boolean setKeepAlive(
  216. Boolean enable = false,
  217. UInt initialDelay = 0) {
  218. if (handle_ && handle_->type() == UV_TCP) {
  219. uv::Tcp* tcp = static_cast<uv::Tcp*>(handle_);
  220. return !tcp->setKeepAlive(enable, initialDelay / 1000);
  221. } else {
  222. return false;
  223. }
  224. }
  225. public:
  226. Buffer::Encoding encoding() const {
  227. return decoder_ ? decoder_->encoding() : Buffer::NONE;
  228. }
  229. Boolean write(
  230. const Value& data,
  231. JsFunction::Ptr cb) {
  232. return write(data, Buffer::NONE, cb);
  233. }
  234. Boolean write(
  235. const Value& data,
  236. Buffer::Encoding enc,
  237. JsFunction::Ptr cb) {
  238. Buffer::CPtr buf;
  239. if (data.is<String>()) {
  240. String::CPtr str = toCPtr<String>(data);
  241. if (enc == Buffer::NONE) enc = Buffer::UTF8;
  242. buf = Buffer::create(str, enc);
  243. } else if (data.is<StringBuilder>()) {
  244. StringBuilder::CPtr sb = toCPtr<StringBuilder>(data);
  245. if (enc == Buffer::NONE) enc = Buffer::UTF8;
  246. buf = Buffer::create(sb, enc);
  247. } else {
  248. buf = toCPtr<Buffer>(data);
  249. }
  250. if (!buf) return false;
  251. if (hasFlag(CONNECTING)) {
  252. connectQueueSize_ += buf->length();
  253. if (!connectBufQueue_) {
  254. assert(!connectCbQueue_);
  255. connectBufQueue_ = JsArray::create();
  256. connectCbQueue_ = JsArray::create();
  257. }
  258. connectBufQueue_->push(buf);
  259. connectCbQueue_->push(cb);
  260. return false;
  261. }
  262. return writeBuffer(buf, cb);
  263. }
  264. Boolean destroy(Error::CPtr err) {
  265. return destroy(err, JsFunction::null());
  266. }
  267. Boolean connect(
  268. libj::JsObject::CPtr options,
  269. JsFunction::Ptr cb = JsFunction::null()) {
  270. if (!options) return false;
  271. Int port = -1;
  272. const Value& vPort = options->get(node::net::OPTION_PORT);
  273. if (!vPort.isUndefined()) {
  274. String::CPtr sPort = String::valueOf(vPort);
  275. if (sPort) {
  276. Long lPort = to<Long>(json::parse(sPort), -1);
  277. port = static_cast<Int>(lPort);
  278. }
  279. }
  280. String::CPtr path =
  281. options->getCPtr<String>(node::net::OPTION_PATH);
  282. String::CPtr host =
  283. options->getCPtr<String>(node::net::OPTION_HOST);
  284. String::CPtr localAddress =
  285. options->getCPtr<String>(node::net::OPTION_LOCAL_ADDRESS);
  286. if (path) {
  287. return connect(path, cb);
  288. } else if (port >= 0) {
  289. connect(port, host, localAddress, String::null(), cb);
  290. return true;
  291. } else {
  292. return false;
  293. }
  294. }
  295. JsFunction::Ptr setOnData(JsFunction::Ptr onData) {
  296. JsFunction::Ptr previous = onData_;
  297. onData_ = onData;
  298. return previous;
  299. }
  300. JsFunction::Ptr setOnEnd(JsFunction::Ptr onEnd) {
  301. JsFunction::Ptr previous = onEnd_;
  302. onEnd_ = onEnd;
  303. return previous;
  304. }
  305. JsFunction::Ptr setOnDrain(JsFunction::Ptr onDrain) {
  306. if (onDrain_) {
  307. removeListener(EVENT_DRAIN, onDrain_);
  308. }
  309. if (onDrain) {
  310. addListener(EVENT_DRAIN, onDrain);
  311. }
  312. JsFunction::Ptr previous = onDrain_;
  313. onDrain_ = onDrain;
  314. return previous;
  315. }
  316. JsFunction::Ptr setOnClose(JsFunction::Ptr onClose) {
  317. if (onClose_) {
  318. removeListener(EVENT_CLOSE, onClose_);
  319. }
  320. if (onClose) {
  321. addListener(EVENT_CLOSE, onClose);
  322. }
  323. JsFunction::Ptr previous = onClose_;
  324. onClose_ = onClose;
  325. return previous;
  326. }
  327. http::Parser* parser() const {
  328. return parser_;
  329. }
  330. void setParser(http::Parser* parser) {
  331. parser_ = parser;
  332. }
  333. http::OutgoingMessage* httpMessage() const {
  334. return httpMessage_;
  335. }
  336. void setHttpMessage(http::OutgoingMessage* msg) {
  337. httpMessage_ = msg;
  338. }
  339. void active() {
  340. if (hasTimer()) {
  341. finishTimer();
  342. startTimer(timeout_);
  343. }
  344. }
  345. void ref() {
  346. if (handle_) handle_->ref();
  347. }
  348. void unref() {
  349. if (handle_) handle_->unref();
  350. }
  351. private:
  352. static Ptr create(int fd, Boolean allowHalfOpen = false) {
  353. uv::Pipe* pipe = new uv::Pipe();
  354. pipe->open(fd);
  355. Socket* sock = new Socket();
  356. sock->handle_ = pipe;
  357. sock->setFlag(READABLE);
  358. sock->setFlag(WRITABLE);
  359. if (allowHalfOpen) sock->setFlag(ALLOW_HALF_OPEN);
  360. return create(sock);
  361. }
  362. static Ptr create(Socket* self) {
  363. LIBJ_STATIC_SYMBOL_DEF(EVENT_DESTROY, "destroy");
  364. initSocketHandle(self);
  365. Ptr socket(self);
  366. JsFunction::Ptr onDestroy(new OnDestroy(socket));
  367. socket->on(EVENT_DESTROY, onDestroy);
  368. return socket;
  369. }
  370. static void initSocketHandle(Socket* self) {
  371. self->flags_ = 0;
  372. self->pendingWriteReqs_ = 0;
  373. self->connectQueueSize_ = 0;
  374. self->bytesRead_ = 0;
  375. self->bytesDispatched_ = 0;
  376. uv::Stream* handle = self->handle_;
  377. if (handle) {
  378. OnRead::Ptr onRead(new OnRead(self, handle));
  379. handle->setOnRead(onRead);
  380. handle->setOwner(self);
  381. }
  382. }
  383. static void connect(
  384. Socket* self,
  385. uv::Pipe* handle,
  386. String::CPtr path) {
  387. assert(self->hasFlag(CONNECTING));
  388. uv::Connect* req = handle->connect(path);
  389. if (req) {
  390. AfterConnect::Ptr afterConnect(new AfterConnect(self));
  391. req->onComplete = afterConnect;
  392. } else {
  393. self->destroy(node::uv::Error::last());
  394. }
  395. }
  396. static void connect(
  397. Socket* self,
  398. uv::Tcp* handle,
  399. String::CPtr address,
  400. Int port,
  401. Int addressType,
  402. String::CPtr localAddress = String::null()) {
  403. assert(self->hasFlag(CONNECTING));
  404. if (localAddress) {
  405. Int r;
  406. if (addressType == 6) {
  407. r = handle->bind6(localAddress);
  408. } else {
  409. r = handle->bind(localAddress);
  410. }
  411. if (r) {
  412. self->destroy(node::uv::Error::last());
  413. return;
  414. }
  415. }
  416. uv::Connect* req;
  417. if (addressType == 6) {
  418. req = handle->connect6(address, port);
  419. } else { // addressType == 4
  420. req = handle->connect(address, port);
  421. }
  422. if (req) {
  423. AfterConnect::Ptr afterConnect(new AfterConnect(self));
  424. req->onComplete = afterConnect;
  425. } else {
  426. self->destroy(node::uv::Error::last());
  427. }
  428. }
  429. void connect(
  430. Int port,
  431. String::CPtr host,
  432. String::CPtr localAddress,
  433. String::CPtr path,
  434. JsFunction::Ptr cb) {
  435. LIBJ_STATIC_SYMBOL_DEF(symLocalhost4, "127.0.0.1");
  436. Boolean pipe = !!path;
  437. if (hasFlag(DESTROYED) || !handle_) {
  438. handle_ = pipe
  439. ? reinterpret_cast<uv::Stream*>(new uv::Pipe())
  440. : reinterpret_cast<uv::Stream*>(new uv::Tcp());
  441. initSocketHandle(this);
  442. }
  443. if (cb) on(EVENT_CONNECT, cb);
  444. active();
  445. setFlag(CONNECTING);
  446. setFlag(WRITABLE);
  447. if (pipe) {
  448. uv::Pipe* pipe = reinterpret_cast<uv::Pipe*>(handle_);
  449. connect(this, pipe, path);
  450. } else {
  451. uv::Tcp* tcp = reinterpret_cast<uv::Tcp*>(handle_);
  452. if (!host) {
  453. connect(this, tcp, symLocalhost4, port, 4);
  454. } else {
  455. AfterLookup::Ptr afterLookup(
  456. new AfterLookup(
  457. LIBJ_THIS_PTR(Socket), tcp, port, localAddress));
  458. dns::lookup(host, afterLookup);
  459. }
  460. }
  461. }
  462. void connectQueueCleanUp() {
  463. unsetFlag(CONNECTING);
  464. connectQueueSize_ = 0;
  465. connectBufQueue_ = JsArray::null();
  466. connectCbQueue_ = JsArray::null();
  467. }
  468. void fireErrorCallbacks(Error::CPtr err, JsFunction::Ptr cb) {
  469. if (cb) invoke(cb, err);
  470. if (err && !hasFlag(ERROR_EMITTED)) {
  471. EmitError::Ptr emitErr(new EmitError(this, err));
  472. process::nextTick(emitErr);
  473. setFlag(ERROR_EMITTED);
  474. }
  475. }
  476. Boolean destroy(Error::CPtr err, JsFunction::Ptr cb) {
  477. if (hasFlag(DESTROYED)) {
  478. #ifdef LIBNODE_REMOVE_LISTENER
  479. // OnDestroy has already called removeAllListeners
  480. // check the return value 'false' instead of calling:
  481. #else
  482. fireErrorCallbacks(err, cb);
  483. #endif
  484. return false;
  485. }
  486. connectQueueCleanUp();
  487. unsetFlag(READABLE);
  488. unsetFlag(WRITABLE);
  489. finishTimer();
  490. if (handle_) {
  491. handle_->close();
  492. handle_->setOnRead(JsFunction::null());
  493. handle_ = NULL;
  494. }
  495. fireErrorCallbacks(err, cb);
  496. EmitClose::Ptr emitClose(new EmitClose(this, err));
  497. process::nextTick(emitClose);
  498. setFlag(DESTROYED);
  499. // this.server has already registered a 'close' listener
  500. // which will do the following:
  501. // if (this.server) {
  502. // this.server._connections--;
  503. // if (this.server._emitCloseIfDrained) {
  504. // this.server._emitCloseIfDrained();
  505. // }
  506. // }
  507. return true;
  508. }
  509. Boolean writeBuffer(Buffer::CPtr buf, JsFunction::Ptr cb) {
  510. active();
  511. if (!handle_) {
  512. destroy(Error::create(Error::ILLEGAL_STATE), cb);
  513. return false;
  514. }
  515. uv::Write* req = handle_->writeBuffer(buf);
  516. if (!req) {
  517. destroy(node::uv::Error::last(), cb);
  518. return false;
  519. }
  520. AfterWrite::Ptr afterWrite(new AfterWrite(this, req));
  521. req->onComplete = afterWrite;
  522. req->cb = cb;
  523. pendingWriteReqs_++;
  524. bytesDispatched_ += req->bytes;
  525. return true;
  526. }
  527. Boolean hasTimer() {
  528. return !timer_.isUndefined();
  529. }
  530. void startTimer(Int timeout) {
  531. if (hasTimer()) finishTimer();
  532. JsFunction::Ptr emitTimeout(new EmitTimeout(this));
  533. timer_ = node::setTimeout(emitTimeout, timeout);
  534. timeout_ = timeout;
  535. }
  536. void finishTimer() {
  537. clearTimeout(timer_);
  538. timer_ = UNDEFINED;
  539. }
  540. private:
  541. class OnRead : LIBJ_JS_FUNCTION(OnRead)
  542. public:
  543. OnRead(
  544. Socket* sock,
  545. uv::Stream* handle)
  546. : self_(sock)
  547. , handle_(handle) {}
  548. virtual Value operator()(JsArray::Ptr args) {
  549. assert(self_->handle_ == handle_);
  550. self_->active();
  551. Buffer::CPtr buffer = args->getCPtr<Buffer>(0);
  552. if (buffer) {
  553. if (self_->decoder_) {
  554. String::CPtr str = self_->decoder_->write(buffer);
  555. if (str && str->length()) {
  556. self_->emit(EVENT_DATA, str);
  557. }
  558. } else {
  559. self_->emit(EVENT_DATA, buffer);
  560. }
  561. self_->bytesRead_ += buffer->length();
  562. if (self_->onData_) (*self_->onData_)(args);
  563. } else {
  564. node::uv::Error::CPtr err = node::uv::Error::last();
  565. if (err->code() == node::uv::Error::_EOF) {
  566. self_->unsetFlag(READABLE);
  567. assert(!self_->hasFlag(GOT_EOF));
  568. self_->setFlag(GOT_EOF);
  569. if (!self_->hasFlag(WRITABLE)) self_->destroy();
  570. if (!self_->hasFlag(ALLOW_HALF_OPEN)) self_->end();
  571. // if (self_->decoder_) {
  572. // String::CPtr ret = self_->decoder_->end();
  573. // if (ret) self_->emit(EVENT_DATA, ret);
  574. // }
  575. self_->emit(EVENT_END);
  576. if (self_->onEnd_) (*self_->onEnd_)();
  577. } else if (err->code() == node::uv::Error::_ECONNRESET) {
  578. self_->destroy();
  579. } else {
  580. self_->destroy(err);
  581. }
  582. }
  583. return Status::OK;
  584. }
  585. private:
  586. Socket* self_;
  587. uv::Stream* handle_;
  588. };
  589. class AfterShutdown : LIBJ_JS_FUNCTION(AfterShutdown)
  590. public:
  591. AfterShutdown(Socket* self) : self_(self) {}
  592. virtual Value operator()(JsArray::Ptr args) {
  593. assert(self_->hasFlag(SHUTDOWN));
  594. assert(!self_->hasFlag(WRITABLE));
  595. if (self_->hasFlag(DESTROYED)) {
  596. return Status::OK;
  597. } else if (self_->hasFlag(GOT_EOF) || !self_->hasFlag(READABLE)) {
  598. self_->destroy();
  599. }
  600. return Status::OK;
  601. }
  602. private:
  603. Socket* self_;
  604. };
  605. class AfterWrite : LIBJ_JS_FUNCTION(AfterWrite)
  606. public:
  607. AfterWrite(
  608. Socket* sock,
  609. uv::Write* req)
  610. : self_(sock)
  611. , req_(req) {}
  612. virtual Value operator()(JsArray::Ptr args) {
  613. if (self_->hasFlag(DESTROYED)) {
  614. return Error::ILLEGAL_STATE;
  615. }
  616. assert(args->get(0).is<int>());
  617. int status = to<int>(args->get(0));
  618. if (status) {
  619. node::uv::Error::CPtr err = node::uv::Error::last();
  620. self_->destroy(err, req_->cb);
  621. return err->code();
  622. }
  623. self_->active();
  624. self_->pendingWriteReqs_--;
  625. if (self_->pendingWriteReqs_ == 0) {
  626. self_->emit(EVENT_DRAIN);
  627. }
  628. if (req_->cb) (*req_->cb)();
  629. if (self_->pendingWriteReqs_ == 0 &&
  630. self_->hasFlag(DESTROY_SOON)) {
  631. self_->destroy();
  632. }
  633. return Status::OK;
  634. }
  635. private:
  636. Socket* self_;
  637. uv::Write* req_;
  638. };
  639. class AfterConnect : LIBJ_JS_FUNCTION(AfterConnect)
  640. public:
  641. AfterConnect(Socket* sock) : self_(sock) {}
  642. virtual Value operator()(JsArray::Ptr args) {
  643. if (self_->hasFlag(DESTROYED)) return Status::OK;
  644. assert(self_->hasFlag(CONNECTING));
  645. self_->unsetFlag(CONNECTING);
  646. assert(args->get(0).is<int>());
  647. assert(args->get(3).is<Boolean>());
  648. assert(args->get(4).is<Boolean>());
  649. int status = to<int>(args->get(0));
  650. Boolean readable = to<Boolean>(args->get(3));
  651. Boolean writable = to<Boolean>(args->get(4));
  652. if (!status) {
  653. if (readable) {
  654. self_->setFlag(READABLE);
  655. } else {
  656. self_->unsetFlag(READABLE);
  657. }
  658. if (writable) {
  659. self_->setFlag(WRITABLE);
  660. } else {
  661. self_->unsetFlag(WRITABLE);
  662. }
  663. self_->active();
  664. if (readable && !self_->hasFlag(PAUSED)) {
  665. self_->handle_->readStart();
  666. }
  667. if (self_->connectQueueSize_) {
  668. JsArray::Ptr connectBufQueue = self_->connectBufQueue_;
  669. JsArray::Ptr connectCbQueue = self_->connectCbQueue_;
  670. Size len = connectBufQueue->length();
  671. assert(connectCbQueue->length() == len);
  672. for (Size i = 0; i < len; i++) {
  673. JsFunction::Ptr cb =
  674. connectCbQueue->getPtr<JsFunction>(i);
  675. self_->write(connectBufQueue->get(i), cb);
  676. }
  677. self_->connectQueueCleanUp();
  678. }
  679. self_->emit(EVENT_CONNECT);
  680. if (self_->hasFlag(SHUTDOWN_QUEUED)) {
  681. self_->unsetFlag(SHUTDOWN_QUEUED);
  682. self_->end();
  683. }
  684. } else {
  685. self_->connectQueueCleanUp();
  686. self_->destroy(node::uv::Error::last());
  687. }
  688. return Status::OK;
  689. }
  690. private:
  691. Socket* self_;
  692. };
  693. class AfterLookup : LIBJ_JS_FUNCTION(AfterLookup)
  694. public:
  695. AfterLookup(
  696. Socket::Ptr self,
  697. uv::Tcp* tcp,
  698. Int port,
  699. String::CPtr localAddress)
  700. : self_(self)
  701. , tcp_(tcp)
  702. , port_(port)
  703. , localAddress_(localAddress) {}
  704. virtual Value operator()(JsArray::Ptr args) {
  705. LIBJ_STATIC_SYMBOL_DEF(symLocalhost4, "127.0.0.1");
  706. LIBJ_STATIC_SYMBOL_DEF(symLocalhost6, "0:0:0:0:0:0:0:1");
  707. if (!self_->hasFlag(CONNECTING)) return Status::OK;
  708. Error::CPtr err = args->getCPtr<Error>(0);
  709. String::CPtr ip = args->getCPtr<String>(1);
  710. Int addressType = to<Int>(args->get(2));
  711. if (err) {
  712. JsFunction::Ptr destroy(
  713. new EmitErrorAndDestroy(&(*self_), err));
  714. process::nextTick(destroy);
  715. } else {
  716. self_->active();
  717. if (!addressType) {
  718. addressType = 4;
  719. }
  720. if (!ip) {
  721. ip = addressType == 4 ? symLocalhost4 : symLocalhost6;
  722. }
  723. connect(
  724. &(*self_), tcp_, ip, port_, addressType, localAddress_);
  725. }
  726. return Status::OK;
  727. }
  728. private:
  729. Socket::Ptr self_;
  730. uv::Tcp* tcp_;
  731. Int port_;
  732. String::CPtr localAddress_;
  733. };
  734. class EmitError : LIBJ_JS_FUNCTION(EmitError)
  735. public:
  736. EmitError(
  737. Socket* sock,
  738. Error::CPtr err)
  739. : self_(sock)
  740. , error_(err) {}
  741. virtual Value operator()(JsArray::Ptr args) {
  742. self_->emit(EVENT_ERROR, error_);
  743. return Status::OK;
  744. }
  745. private:
  746. Socket* self_;
  747. Error::CPtr error_;
  748. };
  749. class EmitErrorAndDestroy : LIBJ_JS_FUNCTION(EmitErrorAndDestroy)
  750. public:
  751. EmitErrorAndDestroy(
  752. Socket* sock,
  753. Error::CPtr err)
  754. : self_(sock)
  755. , error_(err) {}
  756. virtual Value operator()(JsArray::Ptr args) {
  757. self_->emit(EVENT_ERROR, error_);
  758. self_->destroy();
  759. return Status::OK;
  760. }
  761. private:
  762. Socket* self_;
  763. Error::CPtr error_;
  764. };
  765. class EmitClose : LIBJ_JS_FUNCTION(EmitClose)
  766. public:
  767. EmitClose(
  768. Socket* sock,
  769. Error::CPtr err)
  770. : self_(sock)
  771. , error_(err) {}
  772. virtual Value operator()(JsArray::Ptr args) {
  773. LIBJ_STATIC_SYMBOL_DEF(EVENT_DESTROY, "destroy");
  774. self_->emit(EVENT_CLOSE, !!error_);
  775. self_->emit(EVENT_DESTROY);
  776. return Status::OK;
  777. }
  778. private:
  779. Socket* self_;
  780. Error::CPtr error_;
  781. };
  782. class EmitTimeout : LIBJ_JS_FUNCTION(EmitTimeout)
  783. public:
  784. EmitTimeout(Socket* self) : self_(self) {}
  785. virtual Value operator()(JsArray::Ptr args) {
  786. self_->emit(EVENT_TIMEOUT);
  787. return Status::OK;
  788. }
  789. private:
  790. Socket* self_;
  791. };
  792. class OnDestroy : LIBJ_JS_FUNCTION(OnDestroy)
  793. public:
  794. OnDestroy(Socket::Ptr sock) : self_(sock) {}
  795. virtual Value operator()(JsArray::Ptr args) {
  796. assert(!self_->handle_);
  797. assert(self_->hasFlag(DESTROYED));
  798. #ifdef LIBNODE_REMOVE_LISTENER
  799. self_->removeAllListeners();
  800. #endif
  801. return Status::OK;
  802. }
  803. private:
  804. Socket::Ptr self_;
  805. };
  806. public:
  807. enum Flag {
  808. READABLE = 1 << 0,
  809. WRITABLE = 1 << 1,
  810. CONNECTING = 1 << 2,
  811. PAUSED = 1 << 3,
  812. GOT_EOF = 1 << 4,
  813. DESTROYED = 1 << 5,
  814. DESTROY_SOON = 1 << 6,
  815. SHUTDOWN = 1 << 7,
  816. SHUTDOWN_QUEUED = 1 << 8,
  817. ERROR_EMITTED = 1 << 9,
  818. ALLOW_HALF_OPEN = 1 << 10,
  819. };
  820. private:
  821. uv::Stream* handle_;
  822. Value timer_;
  823. Int timeout_;
  824. Size pendingWriteReqs_;
  825. Size connectQueueSize_;
  826. JsArray::Ptr connectBufQueue_;
  827. JsArray::Ptr connectCbQueue_;
  828. Size bytesRead_;
  829. Size bytesDispatched_;
  830. StringDecoder::Ptr decoder_;
  831. JsFunction::Ptr onData_;
  832. JsFunction::Ptr onEnd_;
  833. JsFunction::Ptr onDrain_;
  834. JsFunction::Ptr onClose_;
  835. http::Parser* parser_;
  836. http::OutgoingMessage* httpMessage_;
  837. Socket()
  838. : handle_(NULL)
  839. , timer_(UNDEFINED)
  840. , timeout_(0)
  841. , pendingWriteReqs_(0)
  842. , connectQueueSize_(0)
  843. , connectBufQueue_(JsArray::null())
  844. , connectCbQueue_(JsArray::null())
  845. , bytesRead_(0)
  846. , bytesDispatched_(0)
  847. , decoder_(StringDecoder::null())
  848. , onData_(JsFunction::null())
  849. , onEnd_(JsFunction::null())
  850. , onDrain_(JsFunction::null())
  851. , onClose_(JsFunction::null())
  852. , parser_(NULL)
  853. , httpMessage_(NULL) {}
  854. public:
  855. virtual ~Socket() {
  856. if (handle_) handle_->close();
  857. }
  858. };
  859. } // namespace net
  860. } // namespace detail
  861. } // namespace node
  862. } // namespace libj
  863. #endif // LIBNODE_DETAIL_NET_SOCKET_H_