Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
libzmq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
libzmq
Commits
5d2a8b18
Commit
5d2a8b18
authored
May 17, 2013
by
Martin Hurton
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #557 from hintjens/master
Added as_server to options
parents
342e576e
f06abca0
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
167 additions
and
126 deletions
+167
-126
ipc_connecter.cpp
src/ipc_connecter.cpp
+1
-1
ipc_listener.cpp
src/ipc_listener.cpp
+1
-1
options.cpp
src/options.cpp
+5
-5
options.hpp
src/options.hpp
+2
-1
plain_mechanism.cpp
src/plain_mechanism.cpp
+56
-67
plain_mechanism.hpp
src/plain_mechanism.hpp
+1
-1
stream_engine.cpp
src/stream_engine.cpp
+4
-6
stream_engine.hpp
src/stream_engine.hpp
+2
-2
tcp_connecter.cpp
src/tcp_connecter.cpp
+1
-1
tcp_listener.cpp
src/tcp_listener.cpp
+1
-1
test_security.cpp
tests/test_security.cpp
+67
-18
testutil.hpp
tests/testutil.hpp
+26
-22
No files found.
src/ipc_connecter.cpp
View file @
5d2a8b18
...
...
@@ -113,7 +113,7 @@ void zmq::ipc_connecter_t::out_event ()
}
// Create the engine object for this connection.
stream_engine_t
*
engine
=
new
(
std
::
nothrow
)
stream_engine_t
(
fd
,
options
,
false
,
endpoint
);
stream_engine_t
(
fd
,
options
,
endpoint
);
alloc_assert
(
engine
);
// Attach the engine to the corresponding session object.
...
...
src/ipc_listener.cpp
View file @
5d2a8b18
...
...
@@ -81,7 +81,7 @@ void zmq::ipc_listener_t::in_event ()
// Create the engine object for this connection.
stream_engine_t
*
engine
=
new
(
std
::
nothrow
)
stream_engine_t
(
fd
,
options
,
true
,
endpoint
);
stream_engine_t
(
fd
,
options
,
endpoint
);
alloc_assert
(
engine
);
// Choose I/O thread to run connecter in. Given that we are already
...
...
src/options.cpp
View file @
5d2a8b18
...
...
@@ -52,7 +52,7 @@ zmq::options_t::options_t () :
tcp_keepalive_idle
(
-
1
),
tcp_keepalive_intvl
(
-
1
),
mechanism
(
ZMQ_NULL
),
plain
_server
(
0
),
as
_server
(
0
),
socket_id
(
0
)
{
}
...
...
@@ -251,7 +251,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
case
ZMQ_PLAIN_SERVER
:
if
(
is_int
&&
(
value
==
0
||
value
==
1
))
{
plain
_server
=
value
;
as
_server
=
value
;
mechanism
=
value
?
ZMQ_PLAIN
:
ZMQ_NULL
;
return
0
;
}
...
...
@@ -265,7 +265,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
else
if
(
optvallen_
>=
0
&&
optvallen_
<
256
&&
optval_
!=
NULL
)
{
plain_username
.
assign
((
const
char
*
)
optval_
,
optvallen_
);
plain_server
=
false
;
as_server
=
0
;
mechanism
=
ZMQ_PLAIN
;
return
0
;
}
...
...
@@ -279,7 +279,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
else
if
(
optvallen_
>=
0
&&
optvallen_
<
256
&&
optval_
!=
NULL
)
{
plain_password
.
assign
((
const
char
*
)
optval_
,
optvallen_
);
plain_server
=
false
;
as_server
=
0
;
mechanism
=
ZMQ_PLAIN
;
return
0
;
}
...
...
@@ -485,7 +485,7 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
case
ZMQ_PLAIN_SERVER
:
if
(
is_int
)
{
*
value
=
plain_server
;
*
value
=
as_server
&&
mechanism
==
ZMQ_PLAIN
;
return
0
;
}
break
;
...
...
src/options.hpp
View file @
5d2a8b18
...
...
@@ -125,11 +125,12 @@ namespace zmq
// Security mechanism for all connections on this socket
int
mechanism
;
// If peer is acting as server for PLAIN or CURVE mechanisms
int
as_server
;
// Security credentials for PLAIN mechanism
std
::
string
plain_username
;
std
::
string
plain_password
;
int
plain_server
;
// ID of the socket.
int
socket_id
;
...
...
src/plain_mechanism.cpp
View file @
5d2a8b18
...
...
@@ -30,10 +30,9 @@
#include "plain_mechanism.hpp"
#include "wire.hpp"
zmq
::
plain_mechanism_t
::
plain_mechanism_t
(
const
options_t
&
options_
,
bool
as_server_
)
:
zmq
::
plain_mechanism_t
::
plain_mechanism_t
(
const
options_t
&
options_
)
:
mechanism_t
(
options_
),
state
(
as_server_
?
waiting_for_hello
:
sending_hello
)
state
(
options
.
as_server
?
waiting_for_hello
:
sending_hello
)
{
}
...
...
@@ -46,31 +45,30 @@ int zmq::plain_mechanism_t::next_handshake_message (msg_t *msg_)
int
rc
=
0
;
switch
(
state
)
{
case
sending_hello
:
rc
=
hello_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_welcome
;
break
;
case
sending_welcome
:
rc
=
welcome_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_initiate
;
break
;
case
sending_initiate
:
rc
=
initiate_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_ready
;
break
;
case
sending_ready
:
rc
=
ready_command
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
case
sending_hello
:
rc
=
hello_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_welcome
;
break
;
case
sending_welcome
:
rc
=
welcome_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_initiate
;
break
;
case
sending_initiate
:
rc
=
initiate_command
(
msg_
);
if
(
rc
==
0
)
state
=
waiting_for_ready
;
break
;
case
sending_ready
:
rc
=
ready_command
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
}
return
rc
;
}
...
...
@@ -79,46 +77,46 @@ int zmq::plain_mechanism_t::process_handshake_message (msg_t *msg_)
int
rc
=
0
;
switch
(
state
)
{
case
waiting_for_hello
:
rc
=
process_hello_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_welcome
;
break
;
case
waiting_for_welcome
:
rc
=
process_welcome_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_initiate
;
break
;
case
waiting_for_initiate
:
rc
=
process_initiate_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_ready
;
break
;
case
waiting_for_ready
:
rc
=
process_ready_command
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
case
waiting_for_hello
:
rc
=
process_hello_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_welcome
;
break
;
case
waiting_for_welcome
:
rc
=
process_welcome_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_initiate
;
break
;
case
waiting_for_initiate
:
rc
=
process_initiate_command
(
msg_
);
if
(
rc
==
0
)
state
=
sending_ready
;
break
;
case
waiting_for_ready
:
rc
=
process_ready_command
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
}
if
(
rc
==
0
)
{
rc
=
msg_
->
close
();
errno_assert
(
rc
==
0
);
rc
=
msg_
->
init
();
errno_assert
(
rc
==
0
);
}
return
0
;
}
bool
zmq
::
plain_mechanism_t
::
is_handshake_complete
()
const
{
return
state
==
ready
;
}
int
zmq
::
plain_mechanism_t
::
hello_command
(
msg_t
*
msg_
)
const
{
const
std
::
string
username
=
options
.
plain_username
;
...
...
@@ -147,6 +145,7 @@ int zmq::plain_mechanism_t::hello_command (msg_t *msg_) const
return
0
;
}
int
zmq
::
plain_mechanism_t
::
process_hello_command
(
msg_t
*
msg_
)
{
const
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
...
...
@@ -164,7 +163,6 @@ int zmq::plain_mechanism_t::process_hello_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
size_t
username_length
=
static_cast
<
size_t
>
(
*
ptr
++
);
bytes_left
-=
1
;
...
...
@@ -172,7 +170,6 @@ int zmq::plain_mechanism_t::process_hello_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
const
std
::
string
username
=
std
::
string
((
char
*
)
ptr
,
username_length
);
ptr
+=
username_length
;
bytes_left
-=
username_length
;
...
...
@@ -181,7 +178,6 @@ int zmq::plain_mechanism_t::process_hello_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
size_t
password_length
=
static_cast
<
size_t
>
(
*
ptr
++
);
bytes_left
-=
1
;
...
...
@@ -189,7 +185,6 @@ int zmq::plain_mechanism_t::process_hello_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
const
std
::
string
password
=
std
::
string
((
char
*
)
ptr
,
password_length
);
ptr
+=
password_length
;
bytes_left
-=
password_length
;
...
...
@@ -198,9 +193,8 @@ int zmq::plain_mechanism_t::process_hello_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
// TODO: Add user authentication
return
0
;
}
...
...
@@ -221,7 +215,6 @@ int zmq::plain_mechanism_t::process_welcome_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
return
0
;
}
...
...
@@ -266,7 +259,6 @@ int zmq::plain_mechanism_t::process_initiate_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
return
parse_property_list
(
ptr
+
8
,
bytes_left
-
8
);
}
...
...
@@ -311,7 +303,6 @@ int zmq::plain_mechanism_t::process_ready_command (msg_t *msg_)
errno
=
EPROTO
;
return
-
1
;
}
return
parse_property_list
(
ptr
+
8
,
bytes_left
-
8
);
}
...
...
@@ -322,21 +313,21 @@ int zmq::plain_mechanism_t::parse_property_list (const unsigned char *ptr,
const
size_t
name_length
=
static_cast
<
size_t
>
(
*
ptr
);
ptr
+=
1
;
bytes_left
-=
1
;
if
(
bytes_left
<
name_length
)
break
;
const
std
::
string
name
=
std
::
string
((
const
char
*
)
ptr
,
name_length
);
const
std
::
string
name
=
std
::
string
((
const
char
*
)
ptr
,
name_length
);
ptr
+=
name_length
;
bytes_left
-=
name_length
;
if
(
bytes_left
<
4
)
break
;
const
size_t
value_length
=
static_cast
<
size_t
>
(
get_uint32
(
ptr
));
ptr
+=
4
;
bytes_left
-=
4
;
if
(
bytes_left
<
value_length
)
break
;
const
unsigned
char
*
const
value
=
ptr
;
ptr
+=
value_length
;
bytes_left
-=
value_length
;
...
...
@@ -348,11 +339,9 @@ int zmq::plain_mechanism_t::parse_property_list (const unsigned char *ptr,
if
(
name
==
"Identity"
&&
options
.
recv_identity
)
set_peer_identity
(
value
,
value_length
);
}
if
(
bytes_left
>
0
)
{
errno
=
EPROTO
;
return
-
1
;
}
return
0
;
}
src/plain_mechanism.hpp
View file @
5d2a8b18
...
...
@@ -32,7 +32,7 @@ namespace zmq
{
public
:
plain_mechanism_t
(
const
options_t
&
options_
,
bool
as_server_
);
plain_mechanism_t
(
const
options_t
&
options_
);
virtual
~
plain_mechanism_t
();
// mechanism implementation
...
...
src/stream_engine.cpp
View file @
5d2a8b18
...
...
@@ -50,10 +50,9 @@
#include "likely.hpp"
#include "wire.hpp"
zmq
::
stream_engine_t
::
stream_engine_t
(
fd_t
fd_
,
const
options_t
&
options_
,
bool
as_server_
,
const
std
::
string
&
endpoint_
)
:
zmq
::
stream_engine_t
::
stream_engine_t
(
fd_t
fd_
,
const
options_t
&
options_
,
const
std
::
string
&
endpoint_
)
:
s
(
fd_
),
as_server
(
as_server_
),
inpos
(
NULL
),
insize
(
0
),
decoder
(
NULL
),
...
...
@@ -80,7 +79,7 @@ zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
{
int
rc
=
tx_msg
.
init
();
errno_assert
(
rc
==
0
);
// Put the socket into non-blocking mode.
unblock_socket
(
s
);
// Set the socket buffer limits for the underlying socket.
...
...
@@ -532,8 +531,7 @@ bool zmq::stream_engine_t::handshake ()
}
else
if
(
memcmp
(
greeting_recv
+
12
,
"PLAIN
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
"
,
20
)
==
0
)
{
mechanism
=
new
(
std
::
nothrow
)
plain_mechanism_t
(
options
,
options
.
plain_server
);
mechanism
=
new
(
std
::
nothrow
)
plain_mechanism_t
(
options
);
alloc_assert
(
mechanism
);
}
else
{
...
...
src/stream_engine.hpp
View file @
5d2a8b18
...
...
@@ -52,8 +52,8 @@ namespace zmq
{
public
:
stream_engine_t
(
fd_t
fd_
,
const
options_t
&
options_
,
bool
as_server_
,
const
std
::
string
&
endpoint
);
stream_engine_t
(
fd_t
fd_
,
const
options_t
&
options_
,
const
std
::
string
&
endpoint
);
~
stream_engine_t
();
// i_engine interface implementation.
...
...
src/tcp_connecter.cpp
View file @
5d2a8b18
...
...
@@ -126,7 +126,7 @@ void zmq::tcp_connecter_t::out_event ()
// Create the engine object for this connection.
stream_engine_t
*
engine
=
new
(
std
::
nothrow
)
stream_engine_t
(
fd
,
options
,
false
,
endpoint
);
stream_engine_t
(
fd
,
options
,
endpoint
);
alloc_assert
(
engine
);
// Attach the engine to the corresponding session object.
...
...
src/tcp_listener.cpp
View file @
5d2a8b18
...
...
@@ -92,7 +92,7 @@ void zmq::tcp_listener_t::in_event ()
// Create the engine object for this connection.
stream_engine_t
*
engine
=
new
(
std
::
nothrow
)
stream_engine_t
(
fd
,
options
,
true
,
endpoint
);
stream_engine_t
(
fd
,
options
,
endpoint
);
alloc_assert
(
engine
);
// Choose I/O thread to run connecter in. Given that we are already
...
...
tests/test_security.cpp
View file @
5d2a8b18
...
...
@@ -17,11 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../include/zmq.h"
#include <string.h>
#include <stdbool.h>
#undef NDEBUG
#include <assert.h>
#include "testutil.hpp"
int
main
(
void
)
{
...
...
@@ -40,18 +36,43 @@ int main (void)
int
rc
;
size_t
optsize
;
int
mechanism
;
int
as_server
;
optsize
=
sizeof
(
int
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_MECHANISM
,
&
mechanism
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
mechanism
==
ZMQ_NULL
);
optsize
=
sizeof
(
int
);
rc
=
zmq_getsockopt
(
server
,
ZMQ_MECHANISM
,
&
mechanism
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
mechanism
==
ZMQ_NULL
);
assert
(
mechanism
==
ZMQ_NULL
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
as_server
==
0
);
rc
=
zmq_getsockopt
(
server
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
as_server
==
0
);
rc
=
zmq_bind
(
server
,
"tcp://*:9999"
);
assert
(
rc
==
0
);
rc
=
zmq_connect
(
client
,
"tcp://localhost:9999"
);
assert
(
rc
==
0
);
bounce
(
server
,
client
);
rc
=
zmq_close
(
client
);
assert
(
rc
==
0
);
rc
=
zmq_close
(
server
);
assert
(
rc
==
0
);
// Check PLAIN security
server
=
zmq_socket
(
ctx
,
ZMQ_DEALER
);
assert
(
server
);
client
=
zmq_socket
(
ctx
,
ZMQ_DEALER
);
assert
(
client
);
char
username
[
256
];
optsize
=
256
;
rc
=
zmq_getsockopt
(
client
,
ZMQ_PLAIN_USERNAME
,
username
,
&
optsize
);
...
...
@@ -80,36 +101,64 @@ int main (void)
assert
(
rc
==
0
);
assert
(
optsize
==
8
+
1
);
as_server
=
1
;
rc
=
zmq_setsockopt
(
server
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
sizeof
(
int
));
assert
(
rc
==
0
);
optsize
=
sizeof
(
int
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_MECHANISM
,
&
mechanism
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
mechanism
==
ZMQ_PLAIN
);
int
as_server
=
1
;
rc
=
zmq_setsockopt
(
server
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
sizeof
(
int
));
assert
(
rc
==
0
);
optsize
=
sizeof
(
int
);
rc
=
zmq_getsockopt
(
server
,
ZMQ_MECHANISM
,
&
mechanism
,
&
optsize
);
assert
(
rc
==
0
);
assert
(
mechanism
==
ZMQ_PLAIN
);
// Check we can switch back to NULL security
rc
=
zmq_setsockopt
(
client
,
ZMQ_PLAIN_USERNAME
,
NULL
,
0
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
&
optsize
);
assert
(
rc
==
0
);
rc
=
zmq_setsockopt
(
client
,
ZMQ_PLAIN_PASSWORD
,
NULL
,
0
);
assert
(
as_server
==
0
);
rc
=
zmq_getsockopt
(
server
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
&
optsize
);
assert
(
rc
==
0
);
optsize
=
sizeof
(
int
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_MECHANISM
,
&
mechanism
,
&
optsize
);
assert
(
as_server
==
1
);
rc
=
zmq_bind
(
server
,
"tcp://*:9998"
);
assert
(
rc
==
0
);
assert
(
mechanism
==
ZMQ_NULL
);
rc
=
zmq_connect
(
client
,
"tcp://localhost:9998"
);
assert
(
rc
==
0
);
bounce
(
server
,
client
);
rc
=
zmq_close
(
client
);
assert
(
rc
==
0
);
rc
=
zmq_close
(
server
);
assert
(
rc
==
0
);
// Check PLAIN security -- two servers trying to talk to each other
server
=
zmq_socket
(
ctx
,
ZMQ_DEALER
);
assert
(
server
);
client
=
zmq_socket
(
ctx
,
ZMQ_DEALER
);
assert
(
client
);
rc
=
zmq_setsockopt
(
server
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
sizeof
(
int
));
assert
(
rc
==
0
);
rc
=
zmq_setsockopt
(
client
,
ZMQ_PLAIN_SERVER
,
&
as_server
,
sizeof
(
int
));
assert
(
rc
==
0
);
rc
=
zmq_bind
(
server
,
"tcp://*:9997"
);
assert
(
rc
==
0
);
rc
=
zmq_connect
(
client
,
"tcp://localhost:9997"
);
assert
(
rc
==
0
);
//TODO: this test fails without any error
// bounce (server, client);
rc
=
zmq_close
(
client
);
assert
(
rc
==
0
);
rc
=
zmq_close
(
server
);
assert
(
rc
==
0
);
// Shutdown
rc
=
zmq_ctx_term
(
ctx
);
assert
(
rc
==
0
);
...
...
tests/testutil.hpp
View file @
5d2a8b18
...
...
@@ -17,59 +17,63 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __
ZMQ_TEST_
TESTUTIL_HPP_INCLUDED__
#define __
ZMQ_TEST_
TESTUTIL_HPP_INCLUDED__
#ifndef __TESTUTIL_HPP_INCLUDED__
#define __TESTUTIL_HPP_INCLUDED__
#include "../include/zmq.h"
#include <string.h>
#undef NDEBUG
#include <assert.h>
// Bounce a message from client to server and back
// For REQ/REP or DEALER/DEALER pairs only
static
void
bounce
(
void
*
s
b
,
void
*
sc
)
bounce
(
void
*
s
erver
,
void
*
client
)
{
const
char
*
content
=
"12345678ABCDEFGH12345678abcdefgh"
;
// Send
the message.
int
rc
=
zmq_send
(
sc
,
content
,
32
,
ZMQ_SNDMORE
);
// Send
message from client to server
int
rc
=
zmq_send
(
client
,
content
,
32
,
ZMQ_SNDMORE
);
assert
(
rc
==
32
);
rc
=
zmq_send
(
sc
,
content
,
32
,
0
);
rc
=
zmq_send
(
client
,
content
,
32
,
0
);
assert
(
rc
==
32
);
//
Bounce the message back.
char
buf
1
[
32
];
rc
=
zmq_recv
(
s
b
,
buf1
,
32
,
0
);
//
Receive message at server side
char
buf
fer
[
32
];
rc
=
zmq_recv
(
s
erver
,
buffer
,
32
,
0
);
assert
(
rc
==
32
);
int
rcvmore
;
size_t
sz
=
sizeof
(
rcvmore
);
rc
=
zmq_getsockopt
(
s
b
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
rc
=
zmq_getsockopt
(
s
erver
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
assert
(
rc
==
0
);
assert
(
rcvmore
);
rc
=
zmq_recv
(
s
b
,
buf1
,
32
,
0
);
rc
=
zmq_recv
(
s
erver
,
buffer
,
32
,
0
);
assert
(
rc
==
32
);
rc
=
zmq_getsockopt
(
s
b
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
rc
=
zmq_getsockopt
(
s
erver
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
assert
(
rc
==
0
);
assert
(
!
rcvmore
);
rc
=
zmq_send
(
sb
,
buf1
,
32
,
ZMQ_SNDMORE
);
// Send two parts back to client
rc
=
zmq_send
(
server
,
buffer
,
32
,
ZMQ_SNDMORE
);
assert
(
rc
==
32
);
rc
=
zmq_send
(
s
b
,
buf1
,
32
,
0
);
rc
=
zmq_send
(
s
erver
,
buffer
,
32
,
0
);
assert
(
rc
==
32
);
// Receive the bounced message.
char
buf2
[
32
];
rc
=
zmq_recv
(
sc
,
buf2
,
32
,
0
);
// Receive the two parts at the client side
rc
=
zmq_recv
(
client
,
buffer
,
32
,
0
);
assert
(
rc
==
32
);
rc
=
zmq_getsockopt
(
sc
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
assert
(
rc
==
0
);
assert
(
rcvmore
);
rc
=
zmq_recv
(
sc
,
buf2
,
32
,
0
);
rc
=
zmq_recv
(
client
,
buffer
,
32
,
0
);
assert
(
rc
==
32
);
rc
=
zmq_getsockopt
(
sc
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
rc
=
zmq_getsockopt
(
client
,
ZMQ_RCVMORE
,
&
rcvmore
,
&
sz
);
assert
(
rc
==
0
);
assert
(
!
rcvmore
);
// Check
whether the message is still the same.
assert
(
memcmp
(
buf
2
,
content
,
32
)
==
0
);
// Check
that message is still the same
assert
(
memcmp
(
buf
fer
,
content
,
32
)
==
0
);
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment