~ubuntu-branches/ubuntu/saucy/zeromq3/saucy

« back to all changes in this revision

Viewing changes to src/v1_decoder.cpp

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2012-10-16 19:49:30 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20121016194930-98r0bi746eoaa4iv
Tags: 3.2.1~rc2+dfsg-1
* New upstream RC release (Closes: #690704)
* Bump Standards-Version to 3.9.4 (no changes needed)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (c) 2009-2011 250bpm s.r.o.
 
3
    Copyright (c) 2007-2009 iMatix Corporation
 
4
    Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
 
5
 
 
6
    This file is part of 0MQ.
 
7
 
 
8
    0MQ is free software; you can redistribute it and/or modify it under
 
9
    the terms of the GNU Lesser General Public License as published by
 
10
    the Free Software Foundation; either version 3 of the License, or
 
11
    (at your option) any later version.
 
12
 
 
13
    0MQ is distributed in the hope that it will be useful,
 
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
    GNU Lesser General Public License for more details.
 
17
 
 
18
    You should have received a copy of the GNU Lesser General Public License
 
19
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
 
 
25
#include "platform.hpp"
 
26
#ifdef ZMQ_HAVE_WINDOWS
 
27
#include "windows.hpp"
 
28
#endif
 
29
 
 
30
#include "v1_protocol.hpp"
 
31
#include "v1_decoder.hpp"
 
32
#include "likely.hpp"
 
33
#include "wire.hpp"
 
34
#include "err.hpp"
 
35
 
 
36
zmq::v1_decoder_t::v1_decoder_t (size_t bufsize_,
 
37
      int64_t maxmsgsize_, i_msg_sink *msg_sink_) :
 
38
    decoder_base_t <v1_decoder_t> (bufsize_),
 
39
    msg_sink (msg_sink_),
 
40
    msg_flags (0),
 
41
    maxmsgsize (maxmsgsize_)
 
42
{
 
43
    int rc = in_progress.init ();
 
44
    errno_assert (rc == 0);
 
45
 
 
46
    //  At the beginning, read one byte and go to flags_ready state.
 
47
    next_step (tmpbuf, 1, &v1_decoder_t::flags_ready);
 
48
}
 
49
 
 
50
zmq::v1_decoder_t::~v1_decoder_t ()
 
51
{
 
52
    int rc = in_progress.close ();
 
53
    errno_assert (rc == 0);
 
54
}
 
55
 
 
56
void zmq::v1_decoder_t::set_msg_sink (i_msg_sink *msg_sink_)
 
57
{
 
58
    msg_sink = msg_sink_;
 
59
}
 
60
 
 
61
bool zmq::v1_decoder_t::stalled () const
 
62
{
 
63
    return next == &v1_decoder_t::message_ready;
 
64
}
 
65
 
 
66
bool zmq::v1_decoder_t::flags_ready ()
 
67
{
 
68
    msg_flags = 0;
 
69
    if (tmpbuf [0] & v1_protocol_t::more_flag)
 
70
        msg_flags |= msg_t::more;
 
71
 
 
72
    //  The payload length is either one or eight bytes,
 
73
    //  depending on whether the 'large' bit is set.
 
74
    if (tmpbuf [0] & v1_protocol_t::large_flag)
 
75
        next_step (tmpbuf, 8, &v1_decoder_t::eight_byte_size_ready);
 
76
    else
 
77
        next_step (tmpbuf, 1, &v1_decoder_t::one_byte_size_ready);
 
78
 
 
79
    return true;
 
80
}
 
81
 
 
82
bool zmq::v1_decoder_t::one_byte_size_ready ()
 
83
{
 
84
    int rc = 0;
 
85
 
 
86
    //  Message size must not exceed the maximum allowed size.
 
87
    if (maxmsgsize >= 0)
 
88
        if (unlikely (tmpbuf [0] > static_cast <uint64_t> (maxmsgsize)))
 
89
            goto error;
 
90
 
 
91
    //  in_progress is initialised at this point so in theory we should
 
92
    //  close it before calling zmq_msg_init_size, however, it's a 0-byte
 
93
    //  message and thus we can treat it as uninitialised...
 
94
    rc = in_progress.init_size (tmpbuf [0]);
 
95
    if (unlikely (rc)) {
 
96
        errno_assert (errno == ENOMEM);
 
97
        int rc = in_progress.init ();
 
98
        errno_assert (rc == 0);
 
99
        goto error;
 
100
    }
 
101
 
 
102
    in_progress.set_flags (msg_flags);
 
103
    next_step (in_progress.data (), in_progress.size (),
 
104
        &v1_decoder_t::message_ready);
 
105
 
 
106
    return true;
 
107
 
 
108
error:
 
109
    decoding_error ();
 
110
    return false;
 
111
}
 
112
 
 
113
bool zmq::v1_decoder_t::eight_byte_size_ready ()
 
114
{
 
115
    int rc = 0;
 
116
 
 
117
    //  The payload size is encoded as 64-bit unsigned integer.
 
118
    //  The most significant byte comes first.
 
119
    const uint64_t msg_size = get_uint64 (tmpbuf);
 
120
 
 
121
    //  Message size must not exceed the maximum allowed size.
 
122
    if (maxmsgsize >= 0)
 
123
        if (unlikely (msg_size > static_cast <uint64_t> (maxmsgsize)))
 
124
            goto error;
 
125
 
 
126
    //  Message size must fit into size_t data type.
 
127
    if (unlikely (msg_size != static_cast <size_t> (msg_size)))
 
128
        goto error;
 
129
 
 
130
    //  in_progress is initialised at this point so in theory we should
 
131
    //  close it before calling init_size, however, it's a 0-byte
 
132
    //  message and thus we can treat it as uninitialised.
 
133
    rc = in_progress.init_size (static_cast <size_t> (msg_size));
 
134
    if (unlikely (rc)) {
 
135
        errno_assert (errno == ENOMEM);
 
136
        int rc = in_progress.init ();
 
137
        errno_assert (rc == 0);
 
138
        goto error;
 
139
    }
 
140
 
 
141
    in_progress.set_flags (msg_flags);
 
142
    next_step (in_progress.data (), in_progress.size (),
 
143
        &v1_decoder_t::message_ready);
 
144
 
 
145
    return true;
 
146
 
 
147
error:
 
148
    decoding_error ();
 
149
    return false;
 
150
}
 
151
 
 
152
bool zmq::v1_decoder_t::message_ready ()
 
153
{
 
154
    //  Message is completely read. Push it further and start reading
 
155
    //  new message. (in_progress is a 0-byte message after this point.)
 
156
    if (unlikely (!msg_sink))
 
157
        return false;
 
158
    int rc = msg_sink->push_msg (&in_progress);
 
159
    if (unlikely (rc != 0)) {
 
160
        if (errno != EAGAIN)
 
161
            decoding_error ();
 
162
        return false;
 
163
    }
 
164
 
 
165
    next_step (tmpbuf, 1, &v1_decoder_t::flags_ready);
 
166
    return true;
 
167
}