socket_base.hpp 8.93 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
3 4 5 6

    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
7
    the terms of the GNU Lesser General Public License as published by
8 9 10 11 12 13
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    0MQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU Lesser General Public License for more details.
15

16
    You should have received a copy of the GNU Lesser General Public License
17 18 19 20 21 22
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __ZMQ_SOCKET_BASE_HPP_INCLUDED__
#define __ZMQ_SOCKET_BASE_HPP_INCLUDED__

23
#include <string>
24
#include <map>
25
#include <stdarg.h>
26

27
#include "own.hpp"
28
#include "array.hpp"
29
#include "blob.hpp"
Martin Sustrik's avatar
Martin Sustrik committed
30
#include "stdint.hpp"
31
#include "poller.hpp"
32
#include "atomic_counter.hpp"
33
#include "i_poll_events.hpp"
34
#include "mailbox.hpp"
35
#include "stdint.hpp"
36
#include "clock.hpp"
37
#include "pipe.hpp"
38

39 40 41 42 43
extern "C"
{
    void zmq_free_event (void *data, void *hint);
}

44 45 46
namespace zmq
{

47 48 49 50
    class ctx_t;
    class msg_t;
    class pipe_t;

51
    class socket_base_t :
52
        public own_t,
53
        public array_item_t <>,
54 55
        public i_poll_events,
        public i_pipe_events
56
    {
57 58
        friend class reaper_t;

59 60
    public:

61 62 63
        //  Returns false if object is not a socket.
        bool check_tag ();

64
        //  Create a socket of a specified type.
65
        static socket_base_t *create (int type_, zmq::ctx_t *parent_,
66
            uint32_t tid_, int sid_);
67

68 69
        //  Returns the mailbox associated with this socket.
        mailbox_t *get_mailbox ();
70 71 72 73

        //  Interrupt blocking call if the socket is stuck in one.
        //  This function can be called from a different thread!
        void stop ();
74

75
        //  Interface for communication with the API layer.
76 77
        int setsockopt (int option_, const void *optval_, size_t optvallen_);
        int getsockopt (int option_, void *optval_, size_t *optvallen_);
78 79
        int bind (const char *addr_);
        int connect (const char *addr_);
80
        int term_endpoint (const char *addr_);
81 82
        int send (zmq::msg_t *msg_, int flags_);
        int recv (zmq::msg_t *msg_, int flags_);
83
        int close ();
84

85 86 87 88 89
        //  These functions are used by the polling mechanism to determine
        //  which events are to be reported from this socket.
        bool has_in ();
        bool has_out ();

90 91 92 93 94 95 96 97 98
        //  Using this function reaper thread ask the socket to regiter with
        //  its poller.
        void start_reaping (poller_t *poller_);

        //  i_poll_events implementation. This interface is used when socket
        //  is handled by the poller in the reaper thread.
        void in_event ();
        void out_event ();
        void timer_event (int id_);
Martin Sustrik's avatar
Martin Sustrik committed
99

100 101 102
        //  i_pipe_events interface implementation.
        void read_activated (pipe_t *pipe_);
        void write_activated (pipe_t *pipe_);
103
        void hiccuped (pipe_t *pipe_);
104
        void pipe_terminated (pipe_t *pipe_);
skaller's avatar
skaller committed
105 106
        void lock();
        void unlock();
107

108 109
        int monitor (const char *endpoint_, int events_);

110 111 112
        void set_fd(fd_t fd_);
        fd_t fd();

113 114 115 116 117 118 119 120 121 122
        void event_connected (std::string &addr_, int fd_);
        void event_connect_delayed (std::string &addr_, int err_);
        void event_connect_retried (std::string &addr_, int interval_);
        void event_listening (std::string &addr_, int fd_);
        void event_bind_failed (std::string &addr_, int err_);
        void event_accepted (std::string &addr_, int fd_);
        void event_accept_failed (std::string &addr_, int err_);
        void event_closed (std::string &addr_, int fd_);        
        void event_close_failed (std::string &addr_, int fd_);  
        void event_disconnected (std::string &addr_, int fd_); 
123

124 125
    protected:

126
        socket_base_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
127 128
        virtual ~socket_base_t ();

129 130
        //  Concrete algorithms for the x- methods are to be defined by
        //  individual socket types.
131
        virtual void xattach_pipe (zmq::pipe_t *pipe_,
132
            bool subscribe_to_all_ = false) = 0;
133

134
        //  The default implementation assumes there are no specific socket
135
        //  options for the particular socket type. If not so, override this
136
        //  method.
137
        virtual int xsetsockopt (int option_, const void *optval_,
138 139 140 141
            size_t optvallen_);

        //  The default implementation assumes that send is not supported.
        virtual bool xhas_out ();
142
        virtual int xsend (zmq::msg_t *msg_);
143 144 145

        //  The default implementation assumes that recv in not supported.
        virtual bool xhas_in ();
146
        virtual int xrecv (zmq::msg_t *msg_);
Martin Sustrik's avatar
Martin Sustrik committed
147

148 149 150 151 152
        //  Returns the credential for the peer from which we have received
        //  the last message. If no message has been received yet,
        //  the function returns empty credential.
        virtual blob_t get_credential () const;

153 154 155
        //  i_pipe_events will be forwarded to these functions.
        virtual void xread_activated (pipe_t *pipe_);
        virtual void xwrite_activated (pipe_t *pipe_);
156
        virtual void xhiccuped (pipe_t *pipe_);
157
        virtual void xpipe_terminated (pipe_t *pipe_) = 0;
158

159 160 161
        //  Delay actual destruction of the socket.
        void process_destroy ();

162
        // Socket event data dispath
163
        void monitor_event (zmq_event_t data_, const std::string& addr_);
164

165 166
        // Monitor socket cleanup
        void stop_monitor ();
167
        
168
        // Next assigned name on a zmq_connect() call used by ROUTER and STREAM socket types
169 170
        std::string connect_rid;

171
    private:
172
        //  Creates new endpoint ID and adds the endpoint to the map.
173
        void add_endpoint (const char *addr_, own_t *endpoint_, pipe_t *pipe);
174 175

        //  Map of open endpoints.
176 177
        typedef std::pair <own_t *, pipe_t*> endpoint_pipe_t;
        typedef std::multimap <std::string, endpoint_pipe_t> endpoints_t;
178
        endpoints_t endpoints;
179

180 181 182 183
        //  Map of open inproc endpoints.
        typedef std::multimap <std::string, pipe_t *> inprocs_t;
        inprocs_t inprocs;

184 185 186 187
        //  To be called after processing commands or invoking any command
        //  handlers explicitly. If required, it will deallocate the socket.
        void check_destroy ();

188 189 190 191
        //  Moves the flags from the message to local variables,
        //  to be later retrieved by getsockopt.
        void extract_flags (msg_t *msg_);

192 193 194
        //  Used to check whether the object is a socket.
        uint32_t tag;

195 196
        //  If true, associated context was already terminated.
        bool ctx_terminated;
197

198 199 200 201 202
        //  If true, object should have been already destroyed. However,
        //  destruction is delayed while we unwind the stack to the point
        //  where it doesn't intersect the object being destroyed.
        bool destroyed;

203 204 205 206
        //  Parse URI string.
        int parse_uri (const char *uri_, std::string &protocol_,
            std::string &address_);

207 208 209
        //  Check whether transport protocol, as specified in connect or
        //  bind, is available and compatible with the socket type.
        int check_protocol (const std::string &protocol_);
210

211
        //  Register the pipe with this socket.
212
        void attach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_ = false);
213

214 215
        //  Processes commands sent to this socket (if any). If timeout is -1,
        //  returns only after at least one command was processed.
216 217
        //  If throttle argument is true, commands are processed at most once
        //  in a predefined time period.
218
        int process_commands (int timeout_, bool throttle_);
219

220
        //  Handlers for incoming commands.
221
        void process_stop ();
222
        void process_bind (zmq::pipe_t *pipe_);
223
        void process_term (int linger_);
224

225 226
        //  Socket's mailbox object.
        mailbox_t mailbox;
227

228 229 230 231
        //  List of attached pipes.
        typedef array_t <pipe_t, 3> pipes_t;
        pipes_t pipes;

232 233 234 235
        //  Reaper's poller and handle of this socket within it.
        poller_t *poller;
        poller_t::handle_t handle;

236
        //  Timestamp of when commands were processed the last time.
Martin Sustrik's avatar
Martin Sustrik committed
237
        uint64_t last_tsc;
238

Martin Sustrik's avatar
Martin Sustrik committed
239 240 241
        //  Number of messages received since last command processing.
        int ticks;

242
        //  True if the last message received had MORE flag set.
243 244
        bool rcvmore;

245 246
        // File descriptor if applicable
        fd_t file_desc;
247

248 249 250
        //  Improves efficiency of time measurement.
        clock_t clock;

251 252 253 254 255 256
        // Monitor socket;
        void *monitor_socket;

        // Bitmask of events being monitored
        int monitor_events;

257 258 259
        // Last socket endpoint resolved URI
        std::string last_endpoint;

260
        socket_base_t (const socket_base_t&);
261
        const socket_base_t &operator = (const socket_base_t&);
skaller's avatar
skaller committed
262
        mutex_t sync;
263 264 265 266 267
    };

}

#endif
Pieter Hintjens's avatar
Pieter Hintjens committed
268