NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
connection.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the WebSocket++ Project nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef WEBSOCKETPP_TRANSPORT_ASIO_CON_HPP
29 #define WEBSOCKETPP_TRANSPORT_ASIO_CON_HPP
30 
32 
34 
37 
39 #include <websocketpp/error.hpp>
40 #include <websocketpp/uri.hpp>
41 
48 
49 #include <istream>
50 #include <sstream>
51 #include <string>
52 #include <vector>
53 
54 namespace websocketpp {
55 namespace transport {
56 namespace asio {
57 
58 typedef lib::function<void(connection_hdl)> tcp_init_handler;
59 
61 
66 template <typename config>
68 public:
72  typedef lib::shared_ptr<type> ptr;
73 
79  typedef typename config::alog_type alog_type;
81  typedef typename config::elog_type elog_type;
82 
84  typedef typename request_type::ptr request_ptr;
86  typedef typename response_type::ptr response_ptr;
87 
89  typedef lib::asio::io_service * io_service_ptr;
91  typedef lib::shared_ptr<lib::asio::io_service::strand> strand_ptr;
93  typedef lib::shared_ptr<lib::asio::steady_timer> timer_ptr;
94 
95  // connection is friends with its associated endpoint to allow the endpoint
96  // to call private/protected utility methods that we don't want to expose
97  // to the public api.
98  friend class endpoint<config>;
99 
100  // generate and manage our own io_service
101  explicit connection(bool is_server, alog_type & alog, elog_type & elog)
102  : m_is_server(is_server)
103  , m_alog(alog)
104  , m_elog(elog)
105  {
106  m_alog.write(log::alevel::devel,"asio con transport constructor");
107  }
108 
110  ptr get_shared() {
111  return lib::static_pointer_cast<type>(socket_con_type::get_shared());
112  }
113 
114  bool is_secure() const {
116  }
117 
119 
130  void set_uri(uri_ptr u) {
132  }
133 
135 
144  void set_tcp_pre_init_handler(tcp_init_handler h) {
145  m_tcp_pre_init_handler = h;
146  }
147 
149 
158  void set_tcp_init_handler(tcp_init_handler h) {
160  }
161 
163 
173  void set_tcp_post_init_handler(tcp_init_handler h) {
174  m_tcp_post_init_handler = h;
175  }
176 
178 
189  void set_proxy(std::string const & uri, lib::error_code & ec) {
190  // TODO: return errors for illegal URIs here?
191  // TODO: should https urls be illegal for the moment?
192  m_proxy = uri;
193  m_proxy_data = lib::make_shared<proxy_data>();
194  ec = lib::error_code();
195  }
196 
198  void set_proxy(std::string const & uri) {
199  lib::error_code ec;
200  set_proxy(uri,ec);
201  if (ec) { throw exception(ec); }
202  }
203 
205 
217  void set_proxy_basic_auth(std::string const & username, std::string const &
218  password, lib::error_code & ec)
219  {
220  if (!m_proxy_data) {
222  return;
223  }
224 
225  // TODO: username can't contain ':'
226  std::string val = "Basic "+base64_encode(username + ":" + password);
227  m_proxy_data->req.replace_header("Proxy-Authorization",val);
228  ec = lib::error_code();
229  }
230 
232  void set_proxy_basic_auth(std::string const & username, std::string const &
233  password)
234  {
235  lib::error_code ec;
236  set_proxy_basic_auth(username,password,ec);
237  if (ec) { throw exception(ec); }
238  }
239 
241 
250  void set_proxy_timeout(long duration, lib::error_code & ec) {
251  if (!m_proxy_data) {
253  return;
254  }
255 
256  m_proxy_data->timeout_proxy = duration;
257  ec = lib::error_code();
258  }
259 
261  void set_proxy_timeout(long duration) {
262  lib::error_code ec;
263  set_proxy_timeout(duration,ec);
264  if (ec) { throw exception(ec); }
265  }
266 
267  std::string const & get_proxy() const {
268  return m_proxy;
269  }
270 
272 
281  std::string get_remote_endpoint() const {
282  lib::error_code ec;
283 
284  std::string ret = socket_con_type::get_remote_endpoint(ec);
285 
286  if (ec) {
287  m_elog.write(log::elevel::info,ret);
288  return "Unknown";
289  } else {
290  return ret;
291  }
292  }
293 
296  return m_connection_hdl;
297  }
298 
300 
313  timer_ptr set_timer(long duration, timer_handler callback) {
314  timer_ptr new_timer = lib::make_shared<lib::asio::steady_timer>(
315  lib::ref(*m_io_service),
316  lib::asio::milliseconds(duration)
317  );
318 
320  new_timer->async_wait(m_strand->wrap(lib::bind(
322  new_timer,
323  callback,
324  lib::placeholders::_1
325  )));
326  } else {
327  new_timer->async_wait(lib::bind(
329  new_timer,
330  callback,
331  lib::placeholders::_1
332  ));
333  }
334 
335  return new_timer;
336  }
337 
339 
349  void handle_timer(timer_ptr, timer_handler callback,
350  lib::asio::error_code const & ec)
351  {
352  if (ec) {
355  } else {
356  log_err(log::elevel::info,"asio handle_timer",ec);
358  }
359  } else {
360  callback(lib::error_code());
361  }
362  }
363 
365  strand_ptr get_strand() {
366  return m_strand;
367  }
368 
370 
388  lib::asio::error_code get_transport_ec() const {
389  return m_tec;
390  }
391 
393 
409 protected:
410  void init(init_handler callback) {
411  if (m_alog.static_test(log::alevel::devel)) {
412  m_alog.write(log::alevel::devel,"asio connection init");
413  }
414 
415  // TODO: pre-init timeout. Right now no implemented socket policies
416  // actually have an asyncronous pre-init
417 
419  lib::bind(
421  get_shared(),
422  callback,
423  lib::placeholders::_1
424  )
425  );
426  }
427 
429 
436  lib::error_code proxy_init(std::string const & authority) {
437  if (!m_proxy_data) {
440  }
441  m_proxy_data->req.set_version("HTTP/1.1");
442  m_proxy_data->req.set_method("CONNECT");
443 
444  m_proxy_data->req.set_uri(authority);
445  m_proxy_data->req.replace_header("Host",authority);
446 
447  return lib::error_code();
448  }
449 
451 
460  lib::error_code init_asio (io_service_ptr io_service) {
461  m_io_service = io_service;
462 
464  m_strand = lib::make_shared<lib::asio::io_service::strand>(
465  lib::ref(*io_service));
466  }
467 
468  lib::error_code ec = socket_con_type::init_asio(io_service, m_strand,
469  m_is_server);
470 
471  return ec;
472  }
473 
474  void handle_pre_init(init_handler callback, lib::error_code const & ec) {
475  if (m_alog.static_test(log::alevel::devel)) {
476  m_alog.write(log::alevel::devel,"asio connection handle pre_init");
477  }
478 
479  if (m_tcp_pre_init_handler) {
480  m_tcp_pre_init_handler(m_connection_hdl);
481  }
482 
483  if (ec) {
484  callback(ec);
485  }
486 
487  // If we have a proxy set issue a proxy connect, otherwise skip to
488  // post_init
489  if (!m_proxy.empty()) {
490  proxy_write(callback);
491  } else {
492  post_init(callback);
493  }
494  }
495 
496  void post_init(init_handler callback) {
497  if (m_alog.static_test(log::alevel::devel)) {
498  m_alog.write(log::alevel::devel,"asio connection post_init");
499  }
500 
501  timer_ptr post_timer;
502 
504  post_timer = set_timer(
506  lib::bind(
508  get_shared(),
509  post_timer,
510  callback,
511  lib::placeholders::_1
512  )
513  );
514  }
515 
517  lib::bind(
519  get_shared(),
520  post_timer,
521  callback,
522  lib::placeholders::_1
523  )
524  );
525  }
526 
528 
536  void handle_post_init_timeout(timer_ptr, init_handler callback,
537  lib::error_code const & ec)
538  {
539  lib::error_code ret_ec;
540 
541  if (ec) {
543  m_alog.write(log::alevel::devel,
544  "asio post init timer cancelled");
545  return;
546  }
547 
548  log_err(log::elevel::devel,"asio handle_post_init_timeout",ec);
549  ret_ec = ec;
550  } else {
551  if (socket_con_type::get_ec()) {
552  ret_ec = socket_con_type::get_ec();
553  } else {
555  }
556  }
557 
558  m_alog.write(log::alevel::devel, "Asio transport post-init timed out");
560  callback(ret_ec);
561  }
562 
564 
572  void handle_post_init(timer_ptr post_timer, init_handler callback,
573  lib::error_code const & ec)
574  {
576  (post_timer && lib::asio::is_neg(post_timer->expires_from_now())))
577  {
578  m_alog.write(log::alevel::devel,"post_init cancelled");
579  return;
580  }
581 
582  if (post_timer) {
583  post_timer->cancel();
584  }
585 
586  if (m_alog.static_test(log::alevel::devel)) {
587  m_alog.write(log::alevel::devel,"asio connection handle_post_init");
588  }
589 
590  if (m_tcp_post_init_handler) {
591  m_tcp_post_init_handler(m_connection_hdl);
592  }
593 
594  callback(ec);
595  }
596 
597  void proxy_write(init_handler callback) {
598  if (m_alog.static_test(log::alevel::devel)) {
599  m_alog.write(log::alevel::devel,"asio connection proxy_write");
600  }
601 
602  if (!m_proxy_data) {
604  "assertion failed: !m_proxy_data in asio::connection::proxy_write");
605  callback(make_error_code(error::general));
606  return;
607  }
608 
609  m_proxy_data->write_buf = m_proxy_data->req.raw();
610 
611  m_bufs.push_back(lib::asio::buffer(m_proxy_data->write_buf.data(),
612  m_proxy_data->write_buf.size()));
613 
614  m_alog.write(log::alevel::devel,m_proxy_data->write_buf);
615 
616  // Set a timer so we don't wait forever for the proxy to respond
617  m_proxy_data->timer = this->set_timer(
618  m_proxy_data->timeout_proxy,
619  lib::bind(
621  get_shared(),
622  callback,
623  lib::placeholders::_1
624  )
625  );
626 
627  // Send proxy request
629  lib::asio::async_write(
631  m_bufs,
632  m_strand->wrap(lib::bind(
634  callback,
635  lib::placeholders::_1
636  ))
637  );
638  } else {
639  lib::asio::async_write(
641  m_bufs,
642  lib::bind(
644  callback,
645  lib::placeholders::_1
646  )
647  );
648  }
649  }
650 
651  void handle_proxy_timeout(init_handler callback, lib::error_code const & ec)
652  {
654  m_alog.write(log::alevel::devel,
655  "asio handle_proxy_write timer cancelled");
656  return;
657  } else if (ec) {
658  log_err(log::elevel::devel,"asio handle_proxy_write",ec);
659  callback(ec);
660  } else {
661  m_alog.write(log::alevel::devel,
662  "asio handle_proxy_write timer expired");
665  }
666  }
667 
669  lib::asio::error_code const & ec)
670  {
671  if (m_alog.static_test(log::alevel::devel)) {
672  m_alog.write(log::alevel::devel,
673  "asio connection handle_proxy_write");
674  }
675 
676  m_bufs.clear();
677 
678  // Timer expired or the operation was aborted for some reason.
679  // Whatever aborted it will be issuing the callback so we are safe to
680  // return
682  lib::asio::is_neg(m_proxy_data->timer->expires_from_now()))
683  {
684  m_elog.write(log::elevel::devel,"write operation aborted");
685  return;
686  }
687 
688  if (ec) {
689  log_err(log::elevel::info,"asio handle_proxy_write",ec);
690  m_proxy_data->timer->cancel();
692  return;
693  }
694 
695  proxy_read(callback);
696  }
697 
698  void proxy_read(init_handler callback) {
699  if (m_alog.static_test(log::alevel::devel)) {
700  m_alog.write(log::alevel::devel,"asio connection proxy_read");
701  }
702 
703  if (!m_proxy_data) {
705  "assertion failed: !m_proxy_data in asio::connection::proxy_read");
706  m_proxy_data->timer->cancel();
707  callback(make_error_code(error::general));
708  return;
709  }
710 
712  lib::asio::async_read_until(
714  m_proxy_data->read_buf,
715  "\r\n\r\n",
716  m_strand->wrap(lib::bind(
718  callback,
719  lib::placeholders::_1, lib::placeholders::_2
720  ))
721  );
722  } else {
723  lib::asio::async_read_until(
725  m_proxy_data->read_buf,
726  "\r\n\r\n",
727  lib::bind(
729  callback,
730  lib::placeholders::_1, lib::placeholders::_2
731  )
732  );
733  }
734  }
735 
737 
743  lib::asio::error_code const & ec, size_t)
744  {
745  if (m_alog.static_test(log::alevel::devel)) {
746  m_alog.write(log::alevel::devel,
747  "asio connection handle_proxy_read");
748  }
749 
750  // Timer expired or the operation was aborted for some reason.
751  // Whatever aborted it will be issuing the callback so we are safe to
752  // return
754  lib::asio::is_neg(m_proxy_data->timer->expires_from_now()))
755  {
756  m_elog.write(log::elevel::devel,"read operation aborted");
757  return;
758  }
759 
760  // At this point there is no need to wait for the timer anymore
761  m_proxy_data->timer->cancel();
762 
763  if (ec) {
764  m_elog.write(log::elevel::info,
765  "asio handle_proxy_read error: "+ec.message());
767  } else {
768  if (!m_proxy_data) {
770  "assertion failed: !m_proxy_data in asio::connection::handle_proxy_read");
771  callback(make_error_code(error::general));
772  return;
773  }
774 
775  std::istream input(&m_proxy_data->read_buf);
776 
777  m_proxy_data->res.consume(input);
778 
779  if (!m_proxy_data->res.headers_ready()) {
780  // we read until the headers were done in theory but apparently
781  // they aren't. Internal endpoint error.
782  callback(make_error_code(error::general));
783  return;
784  }
785 
786  m_alog.write(log::alevel::devel,m_proxy_data->res.raw());
787 
788  if (m_proxy_data->res.get_status_code() != http::status_code::ok) {
789  // got an error response back
790  // TODO: expose this error in a programmatically accessible way?
791  // if so, see below for an option on how to do this.
792  std::stringstream s;
793  s << "Proxy connection error: "
794  << m_proxy_data->res.get_status_code()
795  << " ("
796  << m_proxy_data->res.get_status_msg()
797  << ")";
798  m_elog.write(log::elevel::info,s.str());
800  return;
801  }
802 
803  // we have successfully established a connection to the proxy, now
804  // we can continue and the proxy will transparently forward the
805  // WebSocket connection.
806 
807  // TODO: decide if we want an on_proxy callback that would allow
808  // access to the proxy response.
809 
810  // free the proxy buffers and req/res objects as they aren't needed
811  // anymore
812  m_proxy_data.reset();
813 
814  // Continue with post proxy initialization
815  post_init(callback);
816  }
817  }
818 
820  void async_read_at_least(size_t num_bytes, char *buf, size_t len,
821  read_handler handler)
822  {
823  if (m_alog.static_test(log::alevel::devel)) {
824  std::stringstream s;
825  s << "asio async_read_at_least: " << num_bytes;
826  m_alog.write(log::alevel::devel,s.str());
827  }
828 
829  // TODO: safety vs speed ?
830  // maybe move into an if devel block
831  /*if (num_bytes > len) {
832  m_elog.write(log::elevel::devel,
833  "asio async_read_at_least error::invalid_num_bytes");
834  handler(make_error_code(transport::error::invalid_num_bytes),
835  size_t(0));
836  return;
837  }*/
838 
840  lib::asio::async_read(
842  lib::asio::buffer(buf,len),
843  lib::asio::transfer_at_least(num_bytes),
844  m_strand->wrap(make_custom_alloc_handler(
845  m_read_handler_allocator,
846  lib::bind(
848  handler,
849  lib::placeholders::_1, lib::placeholders::_2
850  )
851  ))
852  );
853  } else {
854  lib::asio::async_read(
856  lib::asio::buffer(buf,len),
857  lib::asio::transfer_at_least(num_bytes),
859  m_read_handler_allocator,
860  lib::bind(
862  handler,
863  lib::placeholders::_1, lib::placeholders::_2
864  )
865  )
866  );
867  }
868 
869  }
870 
871  void handle_async_read(read_handler handler, lib::asio::error_code const & ec,
872  size_t bytes_transferred)
873  {
874  m_alog.write(log::alevel::devel, "asio con handle_async_read");
875 
876  // translate asio error codes into more lib::error_codes
877  lib::error_code tec;
878  if (ec == lib::asio::error::eof) {
880  } else if (ec) {
881  // We don't know much more about the error at this point. As our
882  // socket/security policy if it knows more:
884  m_tec = ec;
885 
886  if (tec == transport::error::tls_error ||
888  {
889  // These are aggregate/catch all errors. Log some human readable
890  // information to the info channel to give library users some
891  // more details about why the upstream method may have failed.
892  log_err(log::elevel::info,"asio async_read_at_least",ec);
893  }
894  }
895  if (handler) {
896  handler(tec,bytes_transferred);
897  } else {
898  // This can happen in cases where the connection is terminated while
899  // the transport is waiting on a read.
900  m_alog.write(log::alevel::devel,
901  "handle_async_read called with null read handler");
902  }
903  }
904 
906  void async_write(const char* buf, size_t len, write_handler handler) {
907  m_bufs.push_back(lib::asio::buffer(buf,len));
908 
910  lib::asio::async_write(
912  m_bufs,
913  m_strand->wrap(make_custom_alloc_handler(
914  m_write_handler_allocator,
915  lib::bind(
917  handler,
918  lib::placeholders::_1, lib::placeholders::_2
919  )
920  ))
921  );
922  } else {
923  lib::asio::async_write(
925  m_bufs,
927  m_write_handler_allocator,
928  lib::bind(
930  handler,
931  lib::placeholders::_1, lib::placeholders::_2
932  )
933  )
934  );
935  }
936  }
937 
939  void async_write(std::vector<buffer> const & bufs, write_handler handler) {
940  std::vector<buffer>::const_iterator it;
941 
942  for (it = bufs.begin(); it != bufs.end(); ++it) {
943  m_bufs.push_back(lib::asio::buffer((*it).buf,(*it).len));
944  }
945 
947  lib::asio::async_write(
949  m_bufs,
950  m_strand->wrap(make_custom_alloc_handler(
951  m_write_handler_allocator,
952  lib::bind(
954  handler,
955  lib::placeholders::_1, lib::placeholders::_2
956  )
957  ))
958  );
959  } else {
960  lib::asio::async_write(
962  m_bufs,
964  m_write_handler_allocator,
965  lib::bind(
967  handler,
968  lib::placeholders::_1, lib::placeholders::_2
969  )
970  )
971  );
972  }
973  }
974 
976 
980  void handle_async_write(write_handler handler, lib::asio::error_code const & ec, size_t) {
981  m_bufs.clear();
982  lib::error_code tec;
983  if (ec) {
984  log_err(log::elevel::info,"asio async_write",ec);
986  }
987  if (handler) {
988  handler(tec);
989  } else {
990  // This can happen in cases where the connection is terminated while
991  // the transport is waiting on a read.
992  m_alog.write(log::alevel::devel,
993  "handle_async_write called with null write handler");
994  }
995  }
996 
998 
1005  m_connection_hdl = hdl;
1007  }
1008 
1010 
1013  lib::error_code interrupt(interrupt_handler handler) {
1015  m_io_service->post(m_strand->wrap(handler));
1016  } else {
1017  m_io_service->post(handler);
1018  }
1019  return lib::error_code();
1020  }
1021 
1022  lib::error_code dispatch(dispatch_handler handler) {
1024  m_io_service->post(m_strand->wrap(handler));
1025  } else {
1026  m_io_service->post(handler);
1027  }
1028  return lib::error_code();
1029  }
1030 
1031  /*void handle_interrupt(interrupt_handler handler) {
1032  handler();
1033  }*/
1034 
1037  if (m_alog.static_test(log::alevel::devel)) {
1038  m_alog.write(log::alevel::devel,"asio connection async_shutdown");
1039  }
1040 
1041  timer_ptr shutdown_timer;
1042  shutdown_timer = set_timer(
1044  lib::bind(
1046  get_shared(),
1047  shutdown_timer,
1048  callback,
1049  lib::placeholders::_1
1050  )
1051  );
1052 
1054  lib::bind(
1056  get_shared(),
1057  shutdown_timer,
1058  callback,
1059  lib::placeholders::_1
1060  )
1061  );
1062  }
1063 
1065 
1070  void handle_async_shutdown_timeout(timer_ptr, init_handler callback,
1071  lib::error_code const & ec)
1072  {
1073  lib::error_code ret_ec;
1074 
1075  if (ec) {
1077  m_alog.write(log::alevel::devel,
1078  "asio socket shutdown timer cancelled");
1079  return;
1080  }
1081 
1082  log_err(log::elevel::devel,"asio handle_async_shutdown_timeout",ec);
1083  ret_ec = ec;
1084  } else {
1086  }
1087 
1088  m_alog.write(log::alevel::devel,
1089  "Asio transport socket shutdown timed out");
1091  callback(ret_ec);
1092  }
1093 
1094  void handle_async_shutdown(timer_ptr shutdown_timer, shutdown_handler
1095  callback, lib::asio::error_code const & ec)
1096  {
1098  lib::asio::is_neg(shutdown_timer->expires_from_now()))
1099  {
1100  m_alog.write(log::alevel::devel,"async_shutdown cancelled");
1101  return;
1102  }
1103 
1104  shutdown_timer->cancel();
1105 
1106  lib::error_code tec;
1107  if (ec) {
1108  if (ec == lib::asio::error::not_connected) {
1109  // The socket was already closed when we tried to close it. This
1110  // happens periodically (usually if a read or write fails
1111  // earlier and if it is a real error will be caught at another
1112  // level of the stack.
1113  } else {
1114  // We don't know anything more about this error, give our
1115  // socket/security policy a crack at it.
1117  m_tec = ec;
1118 
1119  if (tec == transport::error::tls_short_read) {
1120  // TLS short read at this point is somewhat expected if both
1121  // sides try and end the connection at the same time or if
1122  // SSLv2 is being used. In general there is nothing that can
1123  // be done here other than a low level development log.
1124  } else {
1125  // all other errors are effectively pass through errors of
1126  // some sort so print some detail on the info channel for
1127  // library users to look up if needed.
1128  log_err(log::elevel::info,"asio async_shutdown",ec);
1129  }
1130  }
1131  } else {
1132  if (m_alog.static_test(log::alevel::devel)) {
1133  m_alog.write(log::alevel::devel,
1134  "asio con handle_async_shutdown");
1135  }
1136  }
1137  callback(tec);
1138  }
1139 
1142  lib::asio::error_code cec = socket_con_type::cancel_socket();
1143  if (cec) {
1145  // cancel not supported on this OS, ignore and log at dev level
1146  m_alog.write(log::alevel::devel, "socket cancel not supported");
1147  } else {
1148  log_err(log::elevel::warn, "socket cancel failed", cec);
1149  }
1150  }
1151  }
1152 
1153 private:
1155  template <typename error_type>
1156  void log_err(log::level l, const char * msg, const error_type & ec) {
1157  std::stringstream s;
1158  s << msg << " error: " << ec << " (" << ec.message() << ")";
1159  m_elog.write(l,s.str());
1160  }
1161 
1162  // static settings
1163  const bool m_is_server;
1164  alog_type& m_alog;
1165  elog_type& m_elog;
1166 
1167  struct proxy_data {
1168  proxy_data() : timeout_proxy(config::timeout_proxy) {}
1169 
1170  request_type req;
1171  response_type res;
1172  std::string write_buf;
1173  lib::asio::streambuf read_buf;
1174  long timeout_proxy;
1175  timer_ptr timer;
1176  };
1177 
1178  std::string m_proxy;
1179  lib::shared_ptr<proxy_data> m_proxy_data;
1180 
1181  // transport resources
1182  io_service_ptr m_io_service;
1183  strand_ptr m_strand;
1184  connection_hdl m_connection_hdl;
1185 
1186  std::vector<lib::asio::const_buffer> m_bufs;
1187 
1189  lib::asio::error_code m_tec;
1190 
1191  // Handlers
1192  tcp_init_handler m_tcp_pre_init_handler;
1193  tcp_init_handler m_tcp_post_init_handler;
1194 
1195  handler_allocator m_read_handler_allocator;
1196  handler_allocator m_write_handler_allocator;
1197 };
1198 
1199 
1200 } // namespace asio
1201 } // namespace transport
1202 } // namespace websocketpp
1203 
1204 #endif // WEBSOCKETPP_TRANSPORT_ASIO_CON_HPP
static const bool enable_multithreading
Definition: timers.cpp:98
void handle_async_shutdown(timer_ptr shutdown_timer, shutdown_handler callback, lib::asio::error_code const &ec)
Asio based endpoint transport component.
Definition: base.hpp:143
static const long timeout_socket_shutdown
Definition: timers.cpp:105
void write(level, std::string const &)
Write a string message to the given channel.
Definition: stub.hpp:82
lib::asio::error_code get_transport_ec() const
Get the internal transport error code for a closed/failed connection.
Definition: connection.hpp:388
config::elog_type elog_type
Type of this transport&#39;s error logging policy.
Definition: connection.hpp:81
void async_shutdown(socket::shutdown_handler callback)
Definition: tls.hpp:328
lib::error_code make_error_code(error::value e)
Definition: error.hpp:235
TLS enabled Asio connection socket component.
Definition: tls.hpp:63
socket_type & get_socket()
Retrieve a pointer to the wrapped socket.
Definition: tls.hpp:119
void cancel_socket_checked()
Cancel the underlying socket and log any errors.
lib::shared_ptr< type > ptr
Type of a shared pointer to this connection socket component.
Definition: tls.hpp:68
void async_write(const char *buf, size_t len, write_handler handler)
Initiate a potentially asyncronous write of the given buffer.
Definition: connection.hpp:906
lib::asio::error_code cancel_socket()
Cancel all async operations on this socket.
Definition: tls.hpp:322
void proxy_write(init_handler callback)
Definition: connection.hpp:597
void set_proxy_basic_auth(std::string const &username, std::string const &password, lib::error_code &ec)
Set the basic auth credentials to use (exception free)
Definition: connection.hpp:217
void pre_init(init_handler callback)
Pre-initialize security policy.
Definition: tls.hpp:231
lib::shared_ptr< type > ptr
Definition: response.hpp:60
bool is_neg(T duration)
Definition: asio.hpp:114
connection(bool is_server, alog_type &alog, elog_type &elog)
Definition: connection.hpp:101
bool is_secure() const
Check whether or not this connection is secure.
Definition: tls.hpp:95
lib::asio::io_service * io_service_ptr
Type of a pointer to the Asio io_service being used.
Definition: connection.hpp:89
boost::posix_time::time_duration milliseconds(long duration)
Definition: asio.hpp:117
void set_tcp_pre_init_handler(tcp_init_handler h)
Sets the tcp pre init handler.
Definition: connection.hpp:144
strand_ptr get_strand()
Get a pointer to this connection&#39;s strand.
Definition: connection.hpp:365
void set_handle(connection_hdl hdl)
Sets the connection handle.
Definition: tls.hpp:295
lib::function< void(lib::error_code const &)> write_handler
The type and signature of the callback passed to the write method.
Definition: connection.hpp:123
static level const devel
Low level debugging information (warning: very chatty)
Definition: levels.hpp:63
lib::weak_ptr< void > connection_hdl
A handle to uniquely identify a connection.
void handle_async_read(read_handler handler, lib::asio::error_code const &ec, size_t bytes_transferred)
Definition: connection.hpp:871
socket_con_type::ptr socket_con_ptr
Type of a shared pointer to the socket connection component.
Definition: connection.hpp:77
void proxy_read(init_handler callback)
Definition: connection.hpp:698
void handle_post_init_timeout(timer_ptr, init_handler callback, lib::error_code const &ec)
Post init timeout callback.
Definition: connection.hpp:536
void async_write(std::vector< buffer > const &bufs, write_handler handler)
Initiate a potentially asyncronous write of the given buffers.
Definition: connection.hpp:939
lib::function< void()> interrupt_handler
The type and signature of the callback passed to the interrupt method.
Definition: connection.hpp:132
lib::shared_ptr< type > ptr
Type of a shared pointer to this connection transport component.
Definition: connection.hpp:72
lib::error_code translate_ec(ErrorCodeType ec)
Translate any security policy specific information about an error code.
Definition: tls.hpp:356
lib::function< void(lib::error_code const &, size_t)> read_handler
The type and signature of the callback passed to the read method.
Definition: connection.hpp:120
std::string base64_encode(unsigned char const *input, size_t len)
Encode a char buffer into a base64 string.
Definition: base64.hpp:66
underlying transport pass through
Definition: connection.hpp:153
void init(init_handler callback)
Initialize transport for reading.
Definition: connection.hpp:410
socket_type::next_layer_type & get_next_layer()
Retrieve a pointer to the layer below the ssl stream.
Definition: tls.hpp:111
_WEBSOCKETPP_CONSTEXPR_TOKEN_ bool static_test(level) const
Test whether a channel is statically enabled.
Definition: stub.hpp:100
connection_hdl get_handle() const
Get the connection handle.
Definition: connection.hpp:295
void post_init(init_handler callback)
Definition: connection.hpp:496
Stores, parses, and manipulates HTTP responses.
Definition: response.hpp:57
void handle_pre_init(init_handler callback, lib::error_code const &ec)
Definition: connection.hpp:474
void handle_async_shutdown_timeout(timer_ptr, init_handler callback, lib::error_code const &ec)
Async shutdown timeout handler.
void handle_async_write(write_handler handler, lib::asio::error_code const &ec, size_t)
Async write callback.
Definition: connection.hpp:980
void set_tcp_post_init_handler(tcp_init_handler h)
Sets the tcp post init handler.
Definition: connection.hpp:173
static level const devel
Development messages (warning: very chatty)
Definition: levels.hpp:141
std::string get_remote_endpoint() const
Get the remote endpoint address.
Definition: connection.hpp:281
void handle_timer(timer_ptr, timer_handler callback, lib::asio::error_code const &ec)
Timer callback.
Definition: connection.hpp:349
std::string get_remote_endpoint(lib::error_code &ec) const
Get the remote endpoint address.
Definition: tls.hpp:158
timer_ptr set_timer(long duration, timer_handler callback)
Call back a function after a period of time.
Definition: connection.hpp:313
lib::shared_ptr< type > ptr
Definition: request.hpp:53
void set_proxy(std::string const &uri, lib::error_code &ec)
Set the proxy to connect through (exception free)
Definition: connection.hpp:189
config::alog_type alog_type
Type of this transport&#39;s access logging policy.
Definition: connection.hpp:79
lib::shared_ptr< lib::asio::io_service::strand > strand_ptr
Type of a pointer to the Asio io_service::strand being used.
Definition: connection.hpp:91
void set_uri(uri_ptr u)
Set hostname hook.
Definition: tls.hpp:218
lib::function< void()> dispatch_handler
The type and signature of the callback passed to the dispatch method.
Definition: connection.hpp:135
void handle_proxy_read(init_handler callback, lib::asio::error_code const &ec, size_t)
Proxy read callback.
Definition: connection.hpp:742
The connection was in the wrong state for this operation.
Definition: error.hpp:74
lib::error_code interrupt(interrupt_handler handler)
Trigger the on_interrupt handler.
lib::error_code dispatch(dispatch_handler handler)
static level const info
Information about minor configuration problems or additional information about other warnings...
Definition: levels.hpp:69
void set_proxy_timeout(long duration, lib::error_code &ec)
Set the proxy timeout duration (exception free)
Definition: connection.hpp:250
ptr get_shared()
Get a shared pointer to this component.
Definition: tls.hpp:87
lib::function< void(lib::error_code const &)> timer_handler
The type and signature of the callback passed to the read method.
Definition: connection.hpp:126
there was an error in the underlying transport library
Definition: base.hpp:171
lib::function< void(lib::error_code const &)> shutdown_handler
The type and signature of the callback passed to the shutdown method.
Definition: connection.hpp:129
Namespace for the WebSocket++ project.
Definition: base64.hpp:41
void set_proxy_timeout(long duration)
Set the proxy timeout duration (exception)
Definition: connection.hpp:261
lib::function< void(lib::error_code const &)> init_handler
The type and signature of the callback passed to the init hook.
Definition: connection.hpp:117
lib::error_code init_asio(io_service_ptr service, strand_ptr strand, bool is_server)
Perform one time initializations.
Definition: tls.hpp:185
static const long timeout_proxy
Definition: timers.cpp:101
Asio based connection transport component.
Definition: connection.hpp:67
static const long timeout_socket_post_init
Definition: timers.cpp:102
custom_alloc_handler< Handler > make_custom_alloc_handler(handler_allocator &a, Handler h)
Definition: base.hpp:128
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
Definition: uri.hpp:351
lib::shared_ptr< lib::asio::steady_timer > timer_ptr
Type of a pointer to the Asio timer class.
Definition: connection.hpp:93
The connection to the requested proxy server failed.
Definition: base.hpp:174
ptr get_shared()
Get a shared pointer to this component.
Definition: connection.hpp:110
void handle_proxy_write(init_handler callback, lib::asio::error_code const &ec)
Definition: connection.hpp:668
connection< config > type
Type of this connection transport component.
Definition: connection.hpp:70
void post_init(init_handler callback)
Post-initialize security policy.
Definition: tls.hpp:263
lib::function< void(connection_hdl)> tcp_init_handler
Definition: connection.hpp:58
void handle_post_init(timer_ptr post_timer, init_handler callback, lib::error_code const &ec)
Post init timeout callback.
Definition: connection.hpp:572
void async_shutdown(shutdown_handler callback)
close and clean up the underlying socket
Stores, parses, and manipulates HTTP requests.
Definition: request.hpp:50
lib::error_code proxy_init(std::string const &authority)
initialize the proxy buffers and http parsers
Definition: connection.hpp:436
std::string const & get_proxy() const
Definition: connection.hpp:267
lib::error_code init_asio(io_service_ptr io_service)
Finish constructing the transport.
Definition: connection.hpp:460
uint32_t level
Type of a channel package.
Definition: levels.hpp:37
lib::error_code make_error_code(error::value e)
Definition: connection.hpp:224
config::socket_type::socket_con_type socket_con_type
Type of the socket connection component.
Definition: connection.hpp:75
void set_proxy(std::string const &uri)
Set the proxy to connect through (exception)
Definition: connection.hpp:198
void async_read_at_least(size_t num_bytes, char *buf, size_t len, read_handler handler)
read at least num_bytes bytes into buf and then call handler.
Definition: connection.hpp:820
void set_tcp_init_handler(tcp_init_handler h)
Sets the tcp pre init handler (deprecated)
Definition: connection.hpp:158
Stub logger that ignores all input.
Definition: stub.hpp:41
static level const library
Information about unusual system states or other minor internal library problems, less chatty than de...
Definition: levels.hpp:66
void set_handle(connection_hdl hdl)
Set Connection Handle.
Catch-all error for transport policy errors that don&#39;t fit in other categories.
Definition: base.hpp:165
static level const warn
Information about important problems not severe enough to terminate connections.
Definition: levels.hpp:72
void set_uri(uri_ptr u)
Set uri hook.
Definition: connection.hpp:130
void handle_proxy_timeout(init_handler callback, lib::error_code const &ec)
Definition: connection.hpp:651
void set_proxy_basic_auth(std::string const &username, std::string const &password)
Set the basic auth credentials to use (exception)
Definition: connection.hpp:232