28 #ifndef WEBSOCKETPP_TRANSPORT_IOSTREAM_CON_HPP
29 #define WEBSOCKETPP_TRANSPORT_IOSTREAM_CON_HPP
31 #include <websocketpp/transport/iostream/base.hpp>
33 #include <websocketpp/transport/base/connection.hpp>
35 #include <websocketpp/uri.hpp>
37 #include <websocketpp/logger/levels.hpp>
39 #include <websocketpp/common/connection_hdl.hpp>
40 #include <websocketpp/common/memory.hpp>
41 #include <websocketpp/common/platforms.hpp>
59 template <
typename config>
60 class connection :
public lib::enable_shared_from_this< connection<config> > {
63 typedef connection<config>
type;
65 typedef lib::shared_ptr<type> ptr;
78 typedef lib::shared_ptr<timer> timer_ptr;
80 explicit connection(
bool is_server,
const lib::shared_ptr<alog_type> & alog,
const lib::shared_ptr<elog_type> & elog)
81 : m_output_stream(NULL)
83 , m_is_server(is_server)
87 , m_remote_endpoint(
"iostream transport")
89 m_alog->write(log::alevel::devel,
"iostream con transport constructor");
94 return type::shared_from_this();
106 scoped_lock_type lock(m_read_mutex);
144 scoped_lock_type lock(t.m_read_mutex);
167 scoped_lock_type lock(m_read_mutex);
169 return this->read_some_impl(buf,len);
190 scoped_lock_type lock(m_read_mutex);
192 size_t total_read = 0;
193 size_t temp_read = 0;
196 temp_read =
this->read_some_impl(buf+total_read,len-total_read);
197 total_read += temp_read;
198 }
while (temp_read != 0 && total_read < len);
209 return this->read_some(buf,len);
221 scoped_lock_type lock(m_read_mutex);
224 complete_read(make_error_code(transport::error::eof));
237 scoped_lock_type lock(m_read_mutex);
240 complete_read(make_error_code(transport::error::pass_through));
290 m_remote_endpoint = value;
306 return m_remote_endpoint;
314 return m_connection_hdl;
381 m_vector_write_handler = h;
401 m_shutdown_handler = h;
410 void init(init_handler handler) {
411 m_alog->write(log::alevel::devel,
"iostream connection init");
412 handler(lib::error_code());
440 read_handler handler)
443 s <<
"iostream_con async_read_at_least: " << num_bytes;
444 m_alog->write(log::alevel::devel,s.str());
446 if (num_bytes > len) {
447 handler(make_error_code(error::invalid_num_bytes),size_t(0));
451 if (m_reading ==
true) {
452 handler(make_error_code(error::double_read),size_t(0));
456 if (num_bytes == 0 || len == 0) {
457 handler(lib::error_code(),size_t(0));
463 m_bytes_needed = num_bytes;
464 m_read_handler = handler;
487 void async_write(
char const * buf, size_t len, transport::write_handler
490 m_alog->write(log::alevel::devel,
"iostream_con async_write");
495 if (m_output_stream) {
496 m_output_stream->write(buf,len);
498 if (m_output_stream->bad()) {
499 ec = make_error_code(error::bad_stream);
501 }
else if (m_write_handler) {
502 ec = m_write_handler(m_connection_hdl, buf, len);
504 ec = make_error_code(error::output_stream_required);
530 m_alog->write(log::alevel::devel,
"iostream_con async_write buffer list");
535 if (m_output_stream) {
536 std::vector<buffer>::const_iterator it;
537 for (it = bufs.begin(); it != bufs.end(); it++) {
538 m_output_stream->write((*it).buf,(*it).len);
540 if (m_output_stream->bad()) {
541 ec = make_error_code(error::bad_stream);
545 }
else if (m_vector_write_handler) {
546 ec = m_vector_write_handler(m_connection_hdl, bufs);
547 }
else if (m_write_handler) {
548 std::vector<buffer>::const_iterator it;
549 for (it = bufs.begin(); it != bufs.end(); it++) {
550 ec = m_write_handler(m_connection_hdl, (*it).buf, (*it).len);
555 ec = make_error_code(error::output_stream_required);
566 m_connection_hdl = hdl;
582 return lib::error_code();
596 if (m_shutdown_handler) {
597 ec = m_shutdown_handler(m_connection_hdl);
603 void read(std::istream &in) {
604 m_alog->write(log::alevel::devel,
"iostream_con read");
608 m_elog->write(log::elevel::devel,
"write while not reading");
612 in.read(m_buf+m_cursor,
static_cast<std::streamsize>(m_len-m_cursor));
614 if (in.gcount() == 0) {
615 m_elog->write(log::elevel::devel,
"read zero bytes");
619 m_cursor +=
static_cast<size_t>(in.gcount());
624 complete_read(make_error_code(error::bad_stream));
627 if (m_cursor >= m_bytes_needed) {
629 complete_read(lib::error_code());
634 size_t read_some_impl(
char const * buf, size_t len) {
635 m_alog->write(log::alevel::devel,
"iostream_con read_some");
638 m_elog->write(log::elevel::devel,
"write while not reading");
642 size_t bytes_to_copy = (std::min)(len,m_len-m_cursor);
644 std::copy(buf,buf+bytes_to_copy,m_buf+m_cursor);
646 m_cursor += bytes_to_copy;
648 if (m_cursor >= m_bytes_needed) {
649 complete_read(lib::error_code());
652 return bytes_to_copy;
671 void complete_read(lib::error_code
const & ec) {
674 read_handler handler = m_read_handler;
675 m_read_handler = read_handler();
677 handler(ec,m_cursor);
683 size_t m_bytes_needed;
684 read_handler m_read_handler;
688 std::ostream * m_output_stream;
689 connection_hdl m_connection_hdl;
690 write_handler m_write_handler;
691 vector_write_handler m_vector_write_handler;
692 shutdown_handler m_shutdown_handler;
695 bool const m_is_server;
697 lib::shared_ptr<alog_type> m_alog;
698 lib::shared_ptr<elog_type> m_elog;
699 std::string m_remote_endpoint;
706 mutex_type m_read_mutex;