ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

633 lines
12 KiB

  1. //
  2. // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #define BOOSTER_SOURCE
  9. #include "socket_details.h"
  10. #include <booster/aio/socket.h>
  11. #ifndef BOOSTER_WIN32
  12. #include <sys/ioctl.h>
  13. #endif
  14. #ifdef __sun
  15. // for FIONREAD
  16. #include <sys/filio.h>
  17. #endif
  18. //#define BOOSTER_AIO_FORCE_POLL
  19. namespace booster {
  20. namespace aio {
  21. struct stream_socket::data{};
  22. stream_socket::stream_socket()
  23. {
  24. }
  25. stream_socket::stream_socket(io_service &s) : basic_socket(s)
  26. {
  27. }
  28. stream_socket::~stream_socket()
  29. {
  30. }
  31. void stream_socket::open(family_type d)
  32. {
  33. basic_socket::open(d,sock_stream);
  34. }
  35. void stream_socket::open(family_type d,system::error_code &e)
  36. {
  37. basic_socket::open(d,sock_stream,e);
  38. }
  39. void stream_socket::shutdown(how_type how,system::error_code &e)
  40. {
  41. #ifndef SHUT_RDWR
  42. #define SHUT_RDWR SD_BOTH
  43. #endif
  44. #ifndef SHUT_WR
  45. #define SHUT_WR SD_SEND
  46. #endif
  47. #ifndef SHUT_RD
  48. #define SHUT_RD SD_RECEIVE
  49. #endif
  50. int method = 0;
  51. switch(how) {
  52. case shut_rd: method = SHUT_RD; break;
  53. case shut_wr: method = SHUT_WR; break;
  54. case shut_rdwr: method = SHUT_RDWR; break;
  55. }
  56. int res = ::shutdown(native(),method);
  57. if(res < 0)
  58. e=geterror();
  59. }
  60. void stream_socket::shutdown(how_type how)
  61. {
  62. system::error_code e;
  63. shutdown(how,e);
  64. if(e)
  65. throw system::system_error(e);
  66. }
  67. size_t stream_socket::read_some(mutable_buffer const &buffer,system::error_code &e)
  68. {
  69. int n=readv(buffer);
  70. if(n < 0) {
  71. e=geterror();
  72. return 0;
  73. }
  74. if(n == 0) {
  75. e=system::error_code(aio_error::eof,aio_error_cat);
  76. return 0;
  77. }
  78. return n;
  79. }
  80. size_t stream_socket::write_some(const_buffer const &buffer,system::error_code &e)
  81. {
  82. int n=writev(buffer);
  83. if(n < 0) {
  84. e=geterror();
  85. return 0;
  86. }
  87. if(n == 0) {
  88. e=system::error_code(aio_error::eof,aio_error_cat);
  89. return 0;
  90. }
  91. return n;
  92. }
  93. size_t stream_socket::read_some(mutable_buffer const &buffer)
  94. {
  95. system::error_code e;
  96. size_t r=read_some(buffer,e);
  97. if(e)
  98. throw system::system_error(e);
  99. return r;
  100. }
  101. size_t stream_socket::write_some(const_buffer const &buffer)
  102. {
  103. system::error_code e;
  104. size_t r=write_some(buffer,e);
  105. if(e)
  106. throw system::system_error(e);
  107. return r;
  108. }
  109. int stream_socket::readv(mutable_buffer const &b)
  110. {
  111. static const unsigned max_vec_size = 16;
  112. mutable_buffer::buffer_data_type data = b.get();
  113. unsigned size=0;
  114. #ifndef BOOSTER_WIN32
  115. struct iovec vec[max_vec_size];
  116. for(;size < max_vec_size && size < data.second;size++) {
  117. vec[size].iov_base = data.first[size].ptr;
  118. vec[size].iov_len = data.first[size].size;
  119. }
  120. for(;;) {
  121. int ret = ::readv(native(),vec,size);
  122. if(ret >= 0)
  123. return ret;
  124. if(ret < 0 && errno==EINTR)
  125. continue;
  126. return ret;
  127. }
  128. #else // Win32
  129. WSABUF vec[max_vec_size];
  130. for(;size < max_vec_size && size < data.second;size++) {
  131. vec[size].buf = data.first[size].ptr;
  132. vec[size].len = data.first[size].size;
  133. }
  134. DWORD recved=0;
  135. DWORD flags=0;
  136. int res = ::WSARecv(native(),vec,size,&recved,&flags,0,0);
  137. if(res == 0)
  138. return recved;
  139. return -1;
  140. #endif
  141. }
  142. int stream_socket::writev(const_buffer const &b)
  143. {
  144. static const unsigned max_vec_size = 16;
  145. const_buffer::buffer_data_type data = b.get();
  146. unsigned size=0;
  147. #ifndef BOOSTER_WIN32
  148. struct iovec vec[max_vec_size];
  149. for(;size < max_vec_size && size < data.second;size++) {
  150. vec[size].iov_base = const_cast<char *>(data.first[size].ptr);
  151. vec[size].iov_len = data.first[size].size;
  152. }
  153. for(;;) {
  154. int ret = ::writev(native(),vec,size);
  155. if(ret >= 0)
  156. return ret;
  157. if(ret < 0 && errno==EINTR)
  158. continue;
  159. return ret;
  160. }
  161. #else // Win32
  162. WSABUF vec[max_vec_size];
  163. for(;size < max_vec_size && size < data.second;size++) {
  164. vec[size].buf = const_cast<char *>(data.first[size].ptr);
  165. vec[size].len = data.first[size].size;
  166. }
  167. DWORD send=0;
  168. int res = ::WSASend(native(),vec,size,&send,0,0,0);
  169. if(res == 0)
  170. return send;
  171. return -1;
  172. #endif
  173. }
  174. void stream_socket::connect(endpoint const &ep,system::error_code &e)
  175. {
  176. endpoint::native_address_type address = ep.raw();
  177. #ifndef BOOSTER_WIN32
  178. for(;;) {
  179. int res = ::connect(native(),address.first,address.second);
  180. if(res < 0 && errno==EINTR)
  181. continue;
  182. if(res < 0) {
  183. e=geterror();
  184. return;
  185. }
  186. break;
  187. }
  188. #else
  189. if(::connect(native(),address.first,address.second) < 0)
  190. e=geterror();
  191. #endif
  192. }
  193. void stream_socket::connect(endpoint const &ep)
  194. {
  195. system::error_code e;
  196. connect(ep,e);
  197. if(e) throw system::system_error(e);
  198. }
  199. size_t stream_socket::read(mutable_buffer const &buffer,system::error_code &e)
  200. {
  201. mutable_buffer tmp = buffer;
  202. size_t count = 0;
  203. while(!tmp.empty()) {
  204. size_t n = read_some(tmp,e);
  205. count+=n;
  206. if(e) return count;
  207. tmp+=n;
  208. }
  209. return count;
  210. }
  211. size_t stream_socket::write(const_buffer const &buffer,system::error_code &e)
  212. {
  213. const_buffer tmp = buffer;
  214. size_t count = 0;
  215. while(!tmp.empty()) {
  216. size_t n = write_some(tmp,e);
  217. count+=n;
  218. if(e) return count;
  219. tmp+=n;
  220. }
  221. return count;
  222. }
  223. size_t stream_socket::read(mutable_buffer const &buf)
  224. {
  225. system::error_code e;
  226. size_t n=read(buf,e);
  227. if(e)
  228. throw system::system_error(e);
  229. return n;
  230. }
  231. size_t stream_socket::write(const_buffer const &buf)
  232. {
  233. system::error_code e;
  234. size_t n=write(buf,e);
  235. if(e)
  236. throw system::system_error(e);
  237. return n;
  238. }
  239. namespace {
  240. struct reader_some : public booster::callable<void(system::error_code const &e)> {
  241. io_handler h;
  242. mutable_buffer buf;
  243. stream_socket *sock;
  244. typedef intrusive_ptr<reader_some> pointer;
  245. reader_some(io_handler const &ih,mutable_buffer const &ibuf,stream_socket *isock) :
  246. h(ih),buf(ibuf),sock(isock)
  247. {
  248. }
  249. void operator()(system::error_code const &e)
  250. {
  251. if(e) {
  252. h(e,0);
  253. }
  254. else {
  255. system::error_code err;
  256. size_t n=sock->read_some(buf,err);
  257. if(n==0 && err && basic_io_device::would_block(err))
  258. sock->on_readable(pointer(this));
  259. else
  260. h(err,n);
  261. }
  262. }
  263. };
  264. struct writer_some : public booster::callable<void(system::error_code const &e)> {
  265. io_handler h;
  266. const_buffer buf;
  267. stream_socket *sock;
  268. typedef intrusive_ptr<writer_some> pointer;
  269. writer_some(io_handler const &ih,const_buffer const &ibuf,stream_socket *isock) :
  270. h(ih),buf(ibuf),sock(isock)
  271. {
  272. }
  273. void operator()(system::error_code const &e)
  274. {
  275. if(e) {
  276. h(e,0);
  277. }
  278. else {
  279. system::error_code err;
  280. size_t n=sock->write_some(buf,err);
  281. if(n==0 && err && basic_io_device::would_block(err))
  282. sock->on_writeable(pointer(this));
  283. else
  284. h(err,n);
  285. }
  286. }
  287. };
  288. struct async_connector : public callable<void(system::error_code const &e)> {
  289. event_handler h;
  290. stream_socket *sock;
  291. async_connector(event_handler const &_h,stream_socket *_s) : h(_h),sock(_s) {}
  292. typedef std::auto_ptr<async_connector> pointer;
  293. void operator()(system::error_code const &e)
  294. {
  295. if(e) { h(e); return; }
  296. system::error_code err;
  297. int errval=0;
  298. socklen_t len = sizeof(errval);
  299. #ifdef BOOSTER_WIN32
  300. char *errptr = reinterpret_cast<char *>(&errval);
  301. #else
  302. int *errptr = &errval;
  303. #endif
  304. int res = ::getsockopt(sock->native(),SOL_SOCKET,SO_ERROR,errptr,&len);
  305. if(res < 0) {
  306. err=geterror();
  307. }
  308. else if(errval!=0) {
  309. err=system::error_code(errval,syscat);
  310. }
  311. h(e);
  312. }
  313. };
  314. struct reader_all : public callable<void(system::error_code const &e)>
  315. {
  316. typedef intrusive_ptr<reader_all> pointer;
  317. reader_all(stream_socket *s,mutable_buffer const &b,io_handler const &handler) :
  318. buf(b),
  319. count(0),
  320. self(s),
  321. h(handler)
  322. {
  323. }
  324. void run()
  325. {
  326. #ifdef BOOSTER_AIO_FORCE_POLL
  327. self->on_readable(intrusive_ptr<reader_all>(this));
  328. #else
  329. system::error_code e;
  330. size_t n = self->read_some(buf,e);
  331. count+=n;
  332. buf+=n;
  333. if(buf.empty() || (e && !basic_io_device::would_block(e))) {
  334. self->get_io_service().post(h,e,count);
  335. }
  336. else {
  337. self->on_readable(intrusive_ptr<reader_all>(this));
  338. }
  339. #endif
  340. }
  341. void operator()(system::error_code const &e)
  342. {
  343. if(e) {
  344. h(e,count);
  345. }
  346. else {
  347. system::error_code err;
  348. size_t n=self->read_some(buf,err);
  349. count+=n;
  350. buf+=n;
  351. if(buf.empty() || (err && !basic_io_device::would_block(err))) {
  352. h(err,count);
  353. }
  354. else {
  355. self->on_readable(intrusive_ptr<reader_all>(this));
  356. }
  357. }
  358. }
  359. private:
  360. mutable_buffer buf;
  361. size_t count;
  362. stream_socket *self;
  363. io_handler h;
  364. };
  365. struct writer_all : public callable<void(system::error_code const &e)>
  366. {
  367. typedef intrusive_ptr<writer_all> pointer;
  368. writer_all(stream_socket *s,const_buffer const &b,size_t n,io_handler const &handler) :
  369. buf(b + n),
  370. count(n),
  371. self(s),
  372. h(handler)
  373. {
  374. }
  375. void run()
  376. {
  377. #ifdef BOOSTER_AIO_FORCE_POLL
  378. self->on_writeable(intrusive_ptr<writer_all>(this));
  379. #else
  380. system::error_code e;
  381. size_t n = self->write_some(buf,e);
  382. count+=n;
  383. buf+=n;
  384. if(buf.empty() || (e && !basic_io_device::would_block(e))) {
  385. self->get_io_service().post(h,e,count);
  386. }
  387. else {
  388. self->on_writeable(intrusive_ptr<writer_all>(this));
  389. }
  390. #endif
  391. }
  392. void operator()(system::error_code const &e)
  393. {
  394. if(e) {
  395. h(e,count);
  396. }
  397. else {
  398. system::error_code err;
  399. size_t n=self->write_some(buf,err);
  400. count+=n;
  401. buf+=n;
  402. if(buf.empty() || (err && !basic_io_device::would_block(err))) {
  403. h(err,count);
  404. }
  405. else {
  406. self->on_writeable(intrusive_ptr<writer_all>(this));
  407. }
  408. }
  409. }
  410. private:
  411. const_buffer buf;
  412. size_t count;
  413. stream_socket *self;
  414. io_handler h;
  415. };
  416. } // anonymous
  417. void stream_socket::async_write_some(const_buffer const &buffer,io_handler const &h)
  418. {
  419. if(!dont_block(h))
  420. return;
  421. #ifdef BOOSTER_AIO_FORCE_POLL
  422. writer_some::pointer writer(new writer_some(h,buffer,this));
  423. on_writeable(writer);
  424. #else
  425. system::error_code e;
  426. size_t n = write_some(buffer,e);
  427. if(e && would_block(e)) {
  428. writer_some::pointer writer(new writer_some(h,buffer,this));
  429. on_writeable(writer);
  430. }
  431. else {
  432. get_io_service().post(h,e,n);
  433. }
  434. #endif
  435. }
  436. void stream_socket::async_read_some(mutable_buffer const &buffer,io_handler const &h)
  437. {
  438. if(!dont_block(h))
  439. return;
  440. #ifdef BOOSTER_AIO_FORCE_POLL
  441. reader_some::pointer reader(new reader_some(h,buffer,this));
  442. on_readable(reader);
  443. #else
  444. system::error_code e;
  445. size_t n = read_some(buffer,e);
  446. if(e && would_block(e)) {
  447. reader_some::pointer reader(new reader_some(h,buffer,this));
  448. on_readable(reader);
  449. }
  450. else {
  451. get_io_service().post(h,e,n);
  452. }
  453. #endif
  454. }
  455. void stream_socket::async_connect(endpoint const &ep,event_handler const &h)
  456. {
  457. if(!dont_block(h))
  458. return;
  459. system::error_code e;
  460. connect(ep,e);
  461. if(e && would_block(e)) {
  462. async_connector::pointer connector(new async_connector(h,this));
  463. on_writeable(connector);
  464. }
  465. else {
  466. get_io_service().post(h,e);
  467. }
  468. }
  469. void stream_socket::async_read(mutable_buffer const &buffer,io_handler const &h)
  470. {
  471. if(!dont_block(h))
  472. return;
  473. reader_all::pointer r(new reader_all(this,buffer,h));
  474. r->run();
  475. }
  476. void stream_socket::async_write(const_buffer const &buffer,io_handler const &h)
  477. {
  478. if(!dont_block(h))
  479. return;
  480. #ifdef BOOSTER_AIO_FORCE_POLL
  481. writer_all::pointer r(new writer_all(this,buffer,0,h));
  482. r->run();
  483. #else
  484. system::error_code e;
  485. size_t n = write_some(buffer,e);
  486. if((!e && n!=buffer.bytes_count()) || (e && would_block(e))) {
  487. writer_all::pointer r(new writer_all(this,buffer,n,h));
  488. r->run();
  489. }
  490. else {
  491. get_io_service().post(h,e,n);
  492. }
  493. #endif
  494. }
  495. size_t stream_socket::bytes_readable(booster::system::error_code &e)
  496. {
  497. #ifdef BOOSTER_WIN32
  498. unsigned long size = 0;
  499. int r = ::ioctlsocket(native(),FIONREAD,&size);
  500. if(r != 0) {
  501. e=geterror();
  502. return 0;
  503. }
  504. return size;
  505. #else
  506. int size = 0;
  507. int r = ::ioctl(native(),FIONREAD,&size);
  508. if(r < 0) {
  509. e=geterror();
  510. return 0;
  511. }
  512. return size;
  513. #endif
  514. }
  515. size_t stream_socket::bytes_readable()
  516. {
  517. booster::system::error_code e;
  518. size_t r = bytes_readable(e);
  519. if(e)
  520. throw booster::system::system_error(e);
  521. return r;
  522. }
  523. void socket_pair(stream_socket &s1,stream_socket &s2,system::error_code &e)
  524. {
  525. try {
  526. socket_pair(s1,s2);
  527. }
  528. catch(system::system_error const &err) {
  529. e=err.code();
  530. }
  531. }
  532. void socket_pair(stream_socket &s1,stream_socket &s2)
  533. {
  534. #ifdef BOOSTER_AIO_NO_PF_UNIX
  535. acceptor a;
  536. a.open(pf_inet);
  537. a.set_option(acceptor::reuse_address,true);
  538. a.bind(endpoint("127.0.0.1",0));
  539. a.listen(1);
  540. s1.open(pf_inet);
  541. s1.connect(a.local_endpoint());
  542. a.accept(s2);
  543. a.close();
  544. #else
  545. int fds[2];
  546. if(::socketpair(AF_UNIX,SOCK_STREAM,0,fds) < 0)
  547. throw system::system_error(geterror());
  548. s1.assign(fds[0]);
  549. s2.assign(fds[1]);
  550. #endif
  551. }
  552. } // aio
  553. } // booster