device.cpp 3.19 KB
Newer Older
1 2 3 4 5 6
/*
    Copyright (c) 2007-2010 iMatix Corporation

    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
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

Martin Sustrik's avatar
Martin Sustrik committed
20 21
#include <stddef.h>

22 23
#include "../include/zmq.h"

24
#include "device.hpp"
25
#include "socket_base.hpp"
26
#include "likely.hpp"
27 28
#include "err.hpp"

29
int zmq::device (class socket_base_t *insocket_,
30 31
        class socket_base_t *outsocket_)
{
Martin Sustrik's avatar
Martin Sustrik committed
32 33
    zmq_msg_t msg;
    int rc = zmq_msg_init (&msg);
34 35 36 37

    if (rc != 0) {
        return -1;
    }
38

Martin Sustrik's avatar
Martin Sustrik committed
39 40
    int64_t more;
    size_t moresz;
41 42 43 44 45 46 47 48 49 50 51 52

    zmq_pollitem_t items [2];
    items [0].socket = insocket_;
    items [0].fd = 0;
    items [0].events = ZMQ_POLLIN;
    items [0].revents = 0;
    items [1].socket = outsocket_;
    items [1].fd = 0;
    items [1].events = ZMQ_POLLIN;
    items [1].revents = 0;

    while (true) {
Martin Sustrik's avatar
Martin Sustrik committed
53 54

        //  Wait while there are either requests or replies to process.
55
        rc = zmq_poll (&items [0], 2, -1);
56
        if (unlikely (rc < 0)) {
57
            return -1;
58
        }
59 60

        //  The algorithm below asumes ratio of request and replies processed
Martin Sustrik's avatar
Martin Sustrik committed
61 62 63
        //  under full load to be 1:1. Although processing requests replies
        //  first is tempting it is suspectible to DoS attacks (overloading
        //  the system with unsolicited replies).
64

Martin Sustrik's avatar
Martin Sustrik committed
65
        //  Process a request.
66
        if (items [0].revents & ZMQ_POLLIN) {
Martin Sustrik's avatar
Martin Sustrik committed
67 68 69
            while (true) {

                rc = insocket_->recv (&msg, 0);
70
                if (unlikely (rc < 0)) {
71
                    return -1;
72
                }
Martin Sustrik's avatar
Martin Sustrik committed
73 74 75

                moresz = sizeof (more);
                rc = insocket_->getsockopt (ZMQ_RCVMORE, &more, &moresz);
76
                if (unlikely (rc < 0)) {
77
                    return -1;
78
                }
Martin Sustrik's avatar
Martin Sustrik committed
79 80

                rc = outsocket_->send (&msg, more ? ZMQ_SNDMORE : 0);
81
                if (unlikely (rc < 0)) {
82
                    return -1;
83
                }
84

Martin Sustrik's avatar
Martin Sustrik committed
85 86 87
                if (!more)
                    break;
            }
88 89
        }

Martin Sustrik's avatar
Martin Sustrik committed
90
        //  Process a reply.
91
        if (items [1].revents & ZMQ_POLLIN) {
Martin Sustrik's avatar
Martin Sustrik committed
92 93 94
            while (true) {

                rc = outsocket_->recv (&msg, 0);
95
                if (unlikely (rc < 0)) {
96
                    return -1;
97
                }
Martin Sustrik's avatar
Martin Sustrik committed
98 99 100

                moresz = sizeof (more);
                rc = outsocket_->getsockopt (ZMQ_RCVMORE, &more, &moresz);
101
                if (unlikely (rc < 0)) {
102
                    return -1;
103
                }
104

Martin Sustrik's avatar
Martin Sustrik committed
105
                rc = insocket_->send (&msg, more ? ZMQ_SNDMORE : 0);
106
                if (unlikely (rc < 0)) {
107
                    return -1;
108
                }
Martin Sustrik's avatar
Martin Sustrik committed
109 110 111 112

                if (!more)
                    break;
            }
113
        }
Martin Sustrik's avatar
Martin Sustrik committed
114

115
    }
Martin Sustrik's avatar
Martin Sustrik committed
116 117

    return 0;
118 119
}