Commit 8cd64b76 authored by Bitiquinho's avatar Bitiquinho

Adapt to new draft header. Rebase dgram socket on pair socket

parent 23b3403f
...@@ -38,24 +38,18 @@ ...@@ -38,24 +38,18 @@
zmq::dgram_t::dgram_t (class ctx_t *parent_, uint32_t tid_, int sid_) : zmq::dgram_t::dgram_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
socket_base_t (parent_, tid_, sid_), socket_base_t (parent_, tid_, sid_),
pipe (NULL),
last_in (NULL),
prefetched (false), prefetched (false),
identity_sent (false), more_out (false)
current_out (NULL),
more_out (false),
next_rid (generate_random ())
{ {
options.type = ZMQ_DGRAM; options.type = ZMQ_DGRAM;
options.raw_socket = true; options.raw_socket = true;
prefetched_id.init ();
prefetched_msg.init ();
} }
zmq::dgram_t::~dgram_t () zmq::dgram_t::~dgram_t ()
{ {
zmq_assert (outpipes.empty ()); zmq_assert (!pipe);
prefetched_id.close ();
prefetched_msg.close ();
} }
void zmq::dgram_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) void zmq::dgram_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
...@@ -64,110 +58,85 @@ void zmq::dgram_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) ...@@ -64,110 +58,85 @@ void zmq::dgram_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
zmq_assert (pipe_); zmq_assert (pipe_);
identify_peer (pipe_); // ZMQ_DGRAM socket can only be connected to a single peer.
fq.attach (pipe_); // The socket rejects any further connection requests.
if (pipe == NULL)
pipe = pipe_;
else
pipe_->terminate (false);
} }
void zmq::dgram_t::xpipe_terminated (pipe_t *pipe_) void zmq::dgram_t::xpipe_terminated (pipe_t *pipe_)
{ {
outpipes_t::iterator it = outpipes.find (pipe_->get_identity ()); if (pipe_ == pipe) {
zmq_assert (it != outpipes.end ()); if (last_in == pipe) {
outpipes.erase (it); saved_credential = last_in->get_credential ();
fq.pipe_terminated (pipe_); last_in = NULL;
if (pipe_ == current_out) }
current_out = NULL; pipe = NULL;
}
} }
void zmq::dgram_t::xread_activated (pipe_t *pipe_) void zmq::dgram_t::xread_activated (pipe_t *)
{ {
fq.activated (pipe_); // There's just one pipe. No lists of active and inactive pipes.
// There's nothing to do here.
} }
void zmq::dgram_t::xwrite_activated (pipe_t *pipe_) void zmq::dgram_t::xwrite_activated (pipe_t *)
{ {
outpipes_t::iterator it; // There's just one pipe. No lists of active and inactive pipes.
for (it = outpipes.begin (); it != outpipes.end (); ++it) // There's nothing to do here.
if (it->second.pipe == pipe_)
break;
zmq_assert (it != outpipes.end ());
zmq_assert (!it->second.active);
it->second.active = true;
} }
int zmq::dgram_t::xsend (msg_t *msg_) int zmq::dgram_t::xsend (msg_t *msg_)
{ {
// If there's no out pipe, just drop it.
if (!pipe) {
int rc = msg_->close ();
errno_assert (rc == 0);
return -1;
}
// If this is the first part of the message it's the ID of the // If this is the first part of the message it's the ID of the
// peer to send the message to. // peer to send the message to.
if (!more_out) { if (!more_out) {
zmq_assert (!current_out); // If we have malformed message (prefix with no subsequent message) then ignore it.
// If we have malformed message (prefix with no subsequent message)
// then just silently ignore it.
// TODO: The connections should be killed instead.
if (msg_->flags () & msg_t::more) { if (msg_->flags () & msg_t::more) {
errno = EINVAL;
// Find the pipe associated with the identity stored in the prefix.
// If there's no such pipe return an error
blob_t identity ((unsigned char*) msg_->data (), msg_->size ());
outpipes_t::iterator it = outpipes.find (identity);
if (it != outpipes.end ()) {
current_out = it->second.pipe;
if (!current_out->check_write ()) {
it->second.active = false;
current_out = NULL;
errno = EAGAIN;
return -1;
}
}
else {
errno = EHOSTUNREACH;
return -1; return -1;
} }
}
// Expect one more message frame. // Expect one more message frame.
more_out = true; more_out = true;
int rc = msg_->close ();
errno_assert (rc == 0);
rc = msg_->init ();
errno_assert (rc == 0);
return 0;
} }
else {
// Ignore the MORE flag // Ignore the MORE flag
msg_->reset_flags (msg_t::more); msg_->reset_flags (msg_t::more);
// This is the last part of the message. // This is the last part of the message.
more_out = false; more_out = false;
}
// Push the message into the pipe. If there's no out pipe, just drop it.
if (current_out) {
// Close the remote connection if user has asked to do so // Close the remote connection if user has asked to do so
// by sending zero length message. // by sending zero length message.
// Pending messages in the pipe will be dropped (on receiving term- ack) // Pending messages in the pipe will be dropped (on receiving term- ack)
if (msg_->size () == 0) { if (msg_->size () == 0) {
current_out->terminate (false); pipe->terminate (false);
int rc = msg_->close (); int rc = msg_->close ();
errno_assert (rc == 0); errno_assert (rc == 0);
rc = msg_->init (); rc = msg_->init ();
errno_assert (rc == 0); errno_assert (rc == 0);
current_out = NULL; pipe = NULL;
return 0; return 0;
} }
bool ok = current_out->write (msg_); // Push the message into the pipe.
if (likely (ok)) if (!pipe->write (msg_)) {
current_out->flush (); errno = EAGAIN;
current_out = NULL; return -1;
}
else {
int rc = msg_->close ();
errno_assert (rc == 0);
} }
if (!(msg_->flags () & msg_t::more))
pipe->flush ();
// Detach the message from the data buffer. // Detach the message from the data buffer.
int rc = msg_->init (); int rc = msg_->init ();
errno_assert (rc == 0); errno_assert (rc == 0);
...@@ -175,78 +144,30 @@ int zmq::dgram_t::xsend (msg_t *msg_) ...@@ -175,78 +144,30 @@ int zmq::dgram_t::xsend (msg_t *msg_)
return 0; return 0;
} }
int zmq::dgram_t::xsetsockopt (int option_, const void *optval_, int zmq::dgram_t::xrecv (msg_t *msg_)
size_t optvallen_)
{ {
bool is_int = (optvallen_ == sizeof (int)); // Deallocate old content of the message.
int value = 0; int rc = msg_->close ();
if (is_int) memcpy(&value, optval_, sizeof (int)); errno_assert (rc == 0);
switch (option_) {
case ZMQ_CONNECT_RID:
if (optval_ && optvallen_) {
connect_rid.assign ((char*) optval_, optvallen_);
return 0;
}
break;
case ZMQ_STREAM_NOTIFY: if (!pipe || !pipe->read (msg_)) {
if (is_int && (value == 0 || value == 1)) { // Initialise the output parameter to be a 0-byte message.
options.raw_notify = (value != 0); rc = msg_->init ();
return 0; errno_assert (rc == 0);
}
break;
default: errno = EAGAIN;
break;
}
errno = EINVAL;
return -1; return -1;
} }
last_in = pipe;
int zmq::dgram_t::xrecv (msg_t *msg_)
{
if (prefetched) { if (prefetched) {
if (!identity_sent) { msg_->reset_flags (msg_t::more);
int rc = msg_->move (prefetched_id);
errno_assert (rc == 0);
identity_sent = true;
}
else {
int rc = msg_->move (prefetched_msg);
errno_assert (rc == 0);
prefetched = false; prefetched = false;
} }
return 0; else {
}
pipe_t *pipe = NULL;
int rc = fq.recvpipe (&prefetched_msg, &pipe);
if (rc != 0)
return -1;
zmq_assert (pipe != NULL);
zmq_assert ((prefetched_msg.flags () & msg_t::more) == 0);
// We have received a frame with TCP data.
// Rather than sending this frame, we keep it in prefetched
// buffer and send a frame with peer's ID.
blob_t identity = pipe->get_identity ();
rc = msg_->close();
errno_assert (rc == 0);
rc = msg_->init_size (identity.size ());
errno_assert (rc == 0);
// forward metadata (if any)
metadata_t *metadata = prefetched_msg.metadata();
if (metadata)
msg_->set_metadata(metadata);
memcpy (msg_->data (), identity.data (), identity.size ());
msg_->set_flags (msg_t::more); msg_->set_flags (msg_t::more);
prefetched = true; prefetched = true;
identity_sent = true; }
return 0; return 0;
} }
...@@ -257,65 +178,24 @@ bool zmq::dgram_t::xhas_in () ...@@ -257,65 +178,24 @@ bool zmq::dgram_t::xhas_in ()
if (prefetched) if (prefetched)
return true; return true;
// Try to read the next message. if (!pipe)
// The message, if read, is kept in the pre-fetch buffer.
pipe_t *pipe = NULL;
int rc = fq.recvpipe (&prefetched_msg, &pipe);
if (rc != 0)
return false; return false;
zmq_assert (pipe != NULL); return pipe->check_read ();
zmq_assert ((prefetched_msg.flags () & msg_t::more) == 0);
blob_t identity = pipe->get_identity ();
rc = prefetched_id.init_size (identity.size ());
errno_assert (rc == 0);
// forward metadata (if any)
metadata_t *metadata = prefetched_msg.metadata();
if (metadata)
prefetched_id.set_metadata(metadata);
memcpy (prefetched_id.data (), identity.data (), identity.size ());
prefetched_id.set_flags (msg_t::more);
prefetched = true;
identity_sent = false;
return true;
} }
bool zmq::dgram_t::xhas_out () bool zmq::dgram_t::xhas_out ()
{ {
// In theory, STREAM socket is always ready for writing. Whether actual //if (more_out)
// attempt to write succeeds depends on which pipe the message is going // return false;
// to be routed to.
return true; if (!pipe)
return false;
return pipe->check_write ();
} }
void zmq::dgram_t::identify_peer (pipe_t *pipe_) zmq::blob_t zmq::dgram_t::get_credential () const
{ {
// Always assign identity for raw-socket return last_in? last_in->get_credential (): saved_credential;
unsigned char buffer [5];
buffer [0] = 0;
blob_t identity;
if (connect_rid.length ()) {
identity = blob_t ((unsigned char*) connect_rid.c_str(),
connect_rid.length ());
connect_rid.clear ();
outpipes_t::iterator it = outpipes.find (identity);
zmq_assert (it == outpipes.end ());
}
else {
put_uint32 (buffer + 1, next_rid++);
identity = blob_t (buffer, sizeof buffer);
memcpy (options.identity, identity.data (), identity.size ());
options.identity_size = (unsigned char) identity.size ();
}
pipe_->set_identity (identity);
// Add the record into output pipes lookup table
outpipe_t outpipe = {pipe_, true};
const bool ok = outpipes.insert (
outpipes_t::value_type (identity, outpipe)).second;
zmq_assert (ok);
} }
...@@ -30,15 +30,17 @@ ...@@ -30,15 +30,17 @@
#ifndef __ZMQ_DGRAM_HPP_INCLUDED__ #ifndef __ZMQ_DGRAM_HPP_INCLUDED__
#define __ZMQ_DGRAM_HPP_INCLUDED__ #define __ZMQ_DGRAM_HPP_INCLUDED__
#include <map> #include "blob.hpp"
#include "socket_base.hpp"
#include "router.hpp" #include "session_base.hpp"
namespace zmq namespace zmq
{ {
class ctx_t; class ctx_t;
class msg_t;
class pipe_t; class pipe_t;
class io_thread_t;
class dgram_t : class dgram_t :
public socket_base_t public socket_base_t
...@@ -54,50 +56,25 @@ namespace zmq ...@@ -54,50 +56,25 @@ namespace zmq
int xrecv (zmq::msg_t *msg_); int xrecv (zmq::msg_t *msg_);
bool xhas_in (); bool xhas_in ();
bool xhas_out (); bool xhas_out ();
blob_t get_credential () const;
void xread_activated (zmq::pipe_t *pipe_); void xread_activated (zmq::pipe_t *pipe_);
void xwrite_activated (zmq::pipe_t *pipe_); void xwrite_activated (zmq::pipe_t *pipe_);
void xpipe_terminated (zmq::pipe_t *pipe_); void xpipe_terminated (zmq::pipe_t *pipe_);
int xsetsockopt (int option_, const void *optval_, size_t optvallen_);
private:
// Generate peer's id and update lookup map
void identify_peer (pipe_t *pipe_);
// Fair queueing object for inbound pipes.
fq_t fq;
// True iff there is a message held in the pre-fetch buffer.
bool prefetched;
// If true, the receiver got the message part with
// the peer's identity.
bool identity_sent;
// Holds the prefetched identity.
msg_t prefetched_id;
// Holds the prefetched message. private:
msg_t prefetched_msg;
struct outpipe_t
{
zmq::pipe_t *pipe; zmq::pipe_t *pipe;
bool active;
};
// Outbound pipes indexed by the peer IDs. zmq::pipe_t *last_in;
typedef std::map <blob_t, outpipe_t> outpipes_t;
outpipes_t outpipes;
// The pipe we are currently writing to. blob_t saved_credential;
zmq::pipe_t *current_out;
// True iff there is a message held in the pre-fetch buffer.
bool prefetched;
// If true, more outgoing message parts are expected. // If true, more outgoing message parts are expected.
bool more_out; bool more_out;
// Routing IDs are generated. It's a simple increment and wrap-over
// algorithm. This value is the next ID to use (if not used already).
uint32_t next_rid;
dgram_t (const dgram_t&); dgram_t (const dgram_t&);
const dgram_t &operator = (const dgram_t&); const dgram_t &operator = (const dgram_t&);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment