static int
get_monitor_event (void *monitor)
{
    for(int i = 0; i < 2; i++) {
        //  First frame in message contains event number and value
        zmq_msg_t msg;
        zmq_msg_init (&msg);
        if (zmq_msg_recv (&msg, monitor, ZMQ_DONTWAIT) == -1) {
            msleep(150);
            continue;           //  Interruped, presumably
        }
        assert (zmq_msg_more (&msg));

        uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
        uint16_t event = *(uint16_t *) (data);

        //  Second frame in message contains event address
        zmq_msg_init (&msg);
        if (zmq_msg_recv (&msg, monitor, 0) == -1) {
            return -1;              //  Interruped, presumably
        }
        assert (!zmq_msg_more (&msg));

        return event;
    }
    return -1;
}
Beispiel #2
0
static bool read_msg(void* s, zmq_event_t& event, std::string& ep)
{
    int rc ;
    zmq_msg_t msg1;  // binary part
    zmq_msg_init (&msg1);
    zmq_msg_t msg2;  //  address part
    zmq_msg_init (&msg2);
    rc = zmq_msg_recv (&msg1, s, 0);
    if (rc == -1 && zmq_errno() == ETERM)
        return true ;

    assert (rc != -1);
    assert (zmq_msg_more(&msg1) != 0);
    rc = zmq_msg_recv (&msg2, s, 0);
    if (rc == -1 && zmq_errno() == ETERM)
        return true;

    assert (rc != -1);
    assert (zmq_msg_more(&msg2) == 0);
    // copy binary data to event struct
    const char* data = (char*)zmq_msg_data(&msg1);
    memcpy(&event.event, data, sizeof(event.event));
    memcpy(&event.value, data+sizeof(event.event), sizeof(event.value));
    // copy address part
    ep = std::string((char*)zmq_msg_data(&msg2), zmq_msg_size(&msg2));

    if (event.event == ZMQ_EVENT_MONITOR_STOPPED)
        return true;

    return false;
}
Beispiel #3
0
SETUP_TEARDOWN_TESTCONTEXT

//  Read one event off the monitor socket; return value and address
//  by reference, if not null, and event number by value. Returns -1
//  in case of error.

static int get_monitor_event (void *monitor_)
{
    for (int i = 0; i < 2; i++) {
        //  First frame in message contains event number and value
        zmq_msg_t msg;
        TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
        if (zmq_msg_recv (&msg, monitor_, ZMQ_DONTWAIT) == -1) {
            msleep (SETTLE_TIME);
            continue; //  Interrupted, presumably
        }
        TEST_ASSERT_TRUE (zmq_msg_more (&msg));

        uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
        uint16_t event = *(uint16_t *) (data);

        //  Second frame in message contains event address
        TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
        if (zmq_msg_recv (&msg, monitor_, 0) == -1) {
            return -1; //  Interrupted, presumably
        }
        TEST_ASSERT_FALSE (zmq_msg_more (&msg));

        return event;
    }
    return -1;
}
Beispiel #4
0
static int
get_monitor_event (void *monitor, int *value, char **address)
{
    //  First frame in message contains event number and value
    zmq_msg_t msg; 
    zmq_msg_init (&msg);
    if (zmq_msg_recv (&msg, monitor, 0) == -1)
        return -1;              //  Interruped, presumably
    assert (zmq_msg_more (&msg));
    
    uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
    uint16_t event = *(uint16_t *) (data);
    if (value)
        *value = *(uint32_t *) (data + 2);

    //  Second frame in message contains event address
    zmq_msg_init (&msg);
    if (zmq_msg_recv (&msg, monitor, 0) == -1)
        return -1;              //  Interruped, presumably
    assert (!zmq_msg_more (&msg));
    
    if (address) {
        uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
        size_t size = zmq_msg_size (&msg);
        *address = (char *) malloc (size + 1);
        memcpy (*address, data, size);
        *address [size] = 0;
    }
    return event;
}
Beispiel #5
0
int main (void)
{
    setup_test_environment();
    //  Create the infrastructure
    void *ctx = zmq_ctx_new ();
    assert (ctx);
    
    void *sb = zmq_socket (ctx, ZMQ_ROUTER);
    assert (sb);
    
    int rc = zmq_bind (sb, "inproc://a");
    assert (rc == 0);
    
    void *sc = zmq_socket (ctx, ZMQ_DEALER);
    assert (sc);
    
    rc = zmq_connect (sc, "inproc://a");
    assert (rc == 0);
   
    //  Send 2-part message.
    rc = zmq_send (sc, "A", 1, ZMQ_SNDMORE);
    assert (rc == 1);
    rc = zmq_send (sc, "B", 1, 0);
    assert (rc == 1);

    //  Identity comes first.
    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc >= 0);
    int more = zmq_msg_more (&msg);
    assert (more == 1);

    //  Then the first part of the message body.
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc == 1);
    more = zmq_msg_more (&msg);
    assert (more == 1);

    //  And finally, the second part of the message body.
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc == 1);
    more = zmq_msg_more (&msg);
    assert (more == 0);

    //  Deallocate the infrastructure.
    rc = zmq_close (sc);
    assert (rc == 0);
    
    rc = zmq_close (sb);
    assert (rc == 0);
    
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
    return 0 ;
}
Beispiel #6
0
int main (void) 
{
    //  Prepare our context and sockets
    void *context = zmq_ctx_new ();
    void *frontend = zmq_socket (context, ZMQ_ROUTER);
    void *backend  = zmq_socket (context, ZMQ_DEALER);
    zmq_bind (frontend, "tcp://*:5559");
    zmq_bind (backend,  "tcp://*:5560");

    //  Initialize poll set
    zmq_pollitem_t items [] = {
        { frontend, 0, ZMQ_POLLIN, 0 },
        { backend,  0, ZMQ_POLLIN, 0 }
    };
    //  Switch messages between sockets
    while (1) {
        zmq_msg_t message;
        zmq_poll (items, 2, -1);
        if (items [0].revents & ZMQ_POLLIN) {
            while (1) {
                //  Process all parts of the message
                zmq_msg_init (&message);
                zmq_msg_recv (&message, frontend, 0);
                zmq_msg_send (&message, backend,
                    zmq_msg_more (&message)? ZMQ_SNDMORE: 0);
                zmq_msg_close (&message);
                if (!zmq_msg_more (&message))
                    break;      //  Last message part
            }
        }
        if (items [1].revents & ZMQ_POLLIN) {
            while (1) {
                //  Process all parts of the message
                zmq_msg_init (&message);
                zmq_msg_recv (&message, backend, 0);
                zmq_msg_send (&message, frontend,
                    zmq_msg_more (&message)? ZMQ_SNDMORE: 0);
                zmq_msg_close (&message);
                if (!zmq_msg_more (&message))
                    break;      //  Last message part
            }
        }
    }
    //  We never get here but clean up anyhow
    zmq_close (frontend);
    zmq_close (backend);
    zmq_ctx_destroy (context);
    return 0;
}
Beispiel #7
0
static int luazmq_skt_recv_all (lua_State *L) {
  zsocket *skt = luazmq_getsocket(L);
  zmq_msg_t msg;
  int flags = luaL_optint(L,2,0);
  int i = 0;
  int result_index = lua_gettop(L) + 1;
  lua_newtable(L);
  while(1){
    int ret = zmq_msg_init(&msg);
    if(-1 == ret){
      ret = luazmq_fail(L, skt);
      lua_pushvalue(L,result_index);
      return ret + 1;
    }
      
    ret = zmq_msg_recv(&msg, skt->skt, flags);
    if(-1 == ret){
      ret = luazmq_fail(L, skt);
      zmq_msg_close(&msg);
      lua_pushvalue(L,result_index);
      return ret + 1;
    }

    lua_pushlstring(L, zmq_msg_data(&msg), zmq_msg_size(&msg));
    lua_rawseti(L, result_index, ++i);
    ret = zmq_msg_more(&msg);
    zmq_msg_close(&msg);
    if(!ret) break;
  }
  return 1;
}
static void 
client_loop_backend(client_state* state, void *backend)
{
    zmq_msg_t zmessage;
    while (1)
    {
        // Process all parts of the message
        zmq_msg_init (&zmessage);
        zmq_msg_recv (&zmessage, backend, 0);
        int more = zmq_msg_more (&zmessage);
        
        if(more)
        {
            zmq_msg_close (&zmessage);
            continue;
        }
        
        //char * data = (char *) zmq_msg_data(&zmessage);
        //printf("sending %s\n", data);
        
        process_backend_message(state, &zmessage);
        zmq_msg_close (&zmessage);
        break;
    }
}
Beispiel #9
0
static int luazmq_msg_recv(lua_State *L){
  zmessage *zmsg = luazmq_getmessage(L);
  zsocket  *zskt = luazmq_getsocket_at(L, 2);
  int flags = luaL_optint(L, 3, 0);
  int err = zmq_msg_recv(&zmsg->msg, zskt->skt, flags);
  if(-1 == err)return luazmq_fail(L, zskt);
  lua_settop(L, 1);
  lua_pushboolean(L, zmq_msg_more(&zmsg->msg));
  return 2;
}
Beispiel #10
0
static inline void switch_msg_from_to( void *from, void *to ) {
        zmq_msg_t msg;
        int more = 1;

        while( more ) {
                zmq_msg_init( &msg );
                int ret = zmq_msg_recv( &msg, from, 0 );
                assert( ret != -1 );
                more = zmq_msg_more( &msg );
                ret = zmq_msg_send( &msg, to, more ? ZMQ_SNDMORE : 0 );
                assert( ret != -1 );
        }
}
static void 
client_loop_frontend (client_state* state, void *frontend)
{
    zmq_msg_t zmessage;
    while (1) {
        // Process all parts of the message
        //printf("RECEIVED  \n");
        
        zmq_msg_init (&zmessage);
        zmq_msg_recv (&zmessage, frontend, 0);
        
        int more = zmq_msg_more (&zmessage);
        
        if(more)
        {
            zmq_msg_close (&zmessage);      
            continue;
        }
        
        zchat_message* message = zchat_message_deserialize_from_zmq_msg(&zmessage);
        if(message == NULL)
        {
            zchat_log("Message deserialisation error");
            zmq_msg_close (&zmessage);
            return;
        }
        
        if(message->type() == zchat_message_message_type_PONG)
        {
            //ECHO_2_STR("PONG", message->ShortDebugString().c_str());;
            process_pong_message(state, message);
        }
        
        if(message->type() == zchat_message_message_type_PING)
        {
            //ECHO_2_STR("PING", message->ShortDebugString().c_str());
            client_state_reset_heartbeat(state);
            client_state_set_heartbeat_time(state);
            add_pong_message(state);
        }
        
        client_state_reset_heartbeat(state);
        client_state_set_heartbeat_time(state);
        ECHO_2_STR("RECEIVED", message->ShortDebugString().c_str());
        
        zchat_message_destroy(message);
        zmq_msg_close (&zmessage);
        break; // Last message part
    }
}
Beispiel #12
0
void proccss_sub_msg(uv_poll_t *req, int status, int events)
{
	void * sub = req->data;
	assert(sub == g_sub_socket);
	if (!(events & UV_READABLE))
		return;


	while (true) {
		int zevents;
		size_t zlen = sizeof(zevents);
		zmq_getsockopt(sub, ZMQ_EVENTS, &zevents, &zlen);
		if (!(zevents & ZMQ_POLLIN))
			break;

		zmq_msg_t cmd;
		zmq_msg_init(&cmd);
		zmq_msg_recv(&cmd, sub, 0);
		if (!zmq_msg_more(&cmd)) {
			zmq_msg_close(&cmd);
			return;
		}
		zmq_msg_t data;
		zmq_msg_init(&data);
		zmq_msg_recv(&data, sub, 0);
		if (!zmq_msg_more(&data)) {
			handle_sub_msg(cmd, data);
		}
		else {
			while (zmq_msg_more(&data)) {
				zmq_msg_recv(&data, sub, 0);
			}
		}
		zmq_msg_close(&cmd);
		zmq_msg_close(&data);
	}
}
Beispiel #13
0
void test_routing_id ()
{
    //  Create the infrastructure
    void *sc = test_context_socket (ZMQ_DEALER);

    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://routing_id"));

    void *sb = test_context_socket (ZMQ_ROUTER);

    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://routing_id"));

    //  Send 2-part message.
    TEST_ASSERT_EQUAL_INT (
      1, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (sc, "A", 1, ZMQ_SNDMORE)));
    TEST_ASSERT_EQUAL_INT (
      1, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (sc, "B", 1, 0)));

    //  Routing id comes first.
    zmq_msg_t msg;
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0));
    TEST_ASSERT_EQUAL_INT (1, zmq_msg_more (&msg));

    //  Then the first part of the message body.
    TEST_ASSERT_EQUAL_INT (
      1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
    TEST_ASSERT_EQUAL_INT (1, zmq_msg_more (&msg));

    //  And finally, the second part of the message body.
    TEST_ASSERT_EQUAL_INT (
      1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
    TEST_ASSERT_EQUAL_INT (0, zmq_msg_more (&msg));

    //  Deallocate the infrastructure.
    test_context_socket_close (sc);
    test_context_socket_close (sb);
}
/**
 * @internal
 * Called whenever the socket becomes readable.
 * ZeroMq since sends multipart messages atomically (all or nothing)
 * both message parts are instantly available.
 *
 * @param socket  ZeroMq socket
 * @param context context passed to elektraIoAdapterZeroMqAttach()
 */
static void zeroMqRecvSocketReadable (void * socket, void * context)
{
	ElektraZeroMqRecvPluginData * data = context;

	char * changeType;
	char * changedKeyName;

	zmq_msg_t message;
	zmq_msg_init (&message);

	int result = zmq_msg_recv (&message, socket, ZMQ_DONTWAIT);
	if (result == -1)
	{
		ELEKTRA_LOG_WARNING ("receiving change type failed: %s; aborting", zmq_strerror (zmq_errno ()));
		zmq_msg_close (&message);
		return;
	}
	if (!zmq_msg_more (&message))
	{
		ELEKTRA_LOG_WARNING ("message has only one part; aborting");
		zmq_msg_close (&message);
		return;
	}
	int length = zmq_msg_size (&message);
	changeType = elektraStrNDup (zmq_msg_data (&message), length + 1);
	changeType[length] = '\0';
	ELEKTRA_LOG_DEBUG ("received change type %s", changeType);

	result = zmq_msg_recv (&message, socket, ZMQ_DONTWAIT);
	if (result == -1)
	{
		ELEKTRA_LOG_WARNING ("receiving key name failed: %s; aborting", zmq_strerror (zmq_errno ()));
		elektraFree (changeType);
		zmq_msg_close (&message);
		return;
	}
	length = zmq_msg_size (&message);
	changedKeyName = elektraStrNDup (zmq_msg_data (&message), length + 1);
	changedKeyName[length] = '\0';
	ELEKTRA_LOG_DEBUG ("received key name %s", changedKeyName);

	// notify about changes
	Key * changedKey = keyNew (changedKeyName, KEY_END);
	data->notificationCallback (changedKey, data->notificationContext);

	zmq_msg_close (&message);
	elektraFree (changeType);
	elektraFree (changedKeyName);
}
Beispiel #15
0
static int pcore_recv_identity (pb_core_t *core, pb_identity_t *identity)
{
	zmq_msg_t msg;
	int rc, more;

	zmq_msg_init (&msg);

	rc = zmq_recvmsg (core->sock, &msg, 0);
	if (rc < 0)
	{
		pb_log (core, PBYTE_WARN,
		        "Recieve identity failed: %s",
		        zmq_strerror(zmq_errno()));
		zmq_msg_close(&msg);
		return -1;
	}

	more = zmq_msg_more (&msg);
	if (more != 1)
	{
		pb_log (core, PBYTE_WARN,
		        "No more data after identity");
		zmq_msg_close(&msg);
		return -2;
	}

	if (zmq_msg_size (&msg) >= PBYTE_IDENTITY_LEN)
	{
		pb_log (core, PBYTE_WARN,
		        "Recieve message failed. "
		        "Large identity");
		zmq_msg_close(&msg);
		return -3;
	}

	// pb_print_buff (&core->logger, PBYTE_INFO,
	//                "incomming identity",
	//                zmq_msg_data(msg),
	//                zmq_msg_size(msg));

	memcpy (identity->identity, zmq_msg_data (&msg), zmq_msg_size (&msg));
	identity->identity_len = zmq_msg_size (&msg);

	zmq_msg_close(&msg);

	return 0;
}
Beispiel #16
0
static int luazmq_skt_recv_msg (lua_State *L) {
  zsocket *skt  = luazmq_getsocket(L);
  zmessage *msg = luazmq_getmessage_at(L,2);
  int flags     = luaL_optint(L,3,0);
  int ret = zmq_msg_recv(&msg->msg, skt->skt, flags);

  if(-1 == ret) return luazmq_fail(L, skt);

  lua_settop(L, 2); // remove flags
  if( zmq_msg_more(&msg->msg) ){
    skt->flags |= LUAZMQ_FLAG_MORE;
    lua_pushboolean(L, 1);
  }
  else{
    skt->flags &= ~LUAZMQ_FLAG_MORE;
    lua_pushboolean(L, 0);
  }
  return 2;
}
Beispiel #17
0
Return<int> Zmq::recv(std::string *data) {
  zmq_msg_t part;
  Return<int> ret(true, 0);

  if (socket == NULL){
    ret.success = false;
    data->append("Socket not initialized");
    return ret;
  }
  std::cout << "recv" << std::endl;

  ret.data = zmq_msg_init (&part);
  
  if (ret.data != 0){
    data->append(zmq_strerror(zmq_errno()));
    ret.success = false;
    return ret;
  }
  
  ret.data = zmq_msg_recv (&part, socket, 0);
  
  if (ret.data == -1){
    zmq_msg_close (&part); 
    data->append(zmq_strerror(zmq_errno()));
    ret.success = false;
    return ret;
  }

  ret.success = true;
  data->append(static_cast<char*>(zmq_msg_data (&part)), 
               zmq_msg_size(&part));
  

  ret.success = zmq_msg_more(&part);
  
  zmq_msg_close (&part); 


  return ret;
}
Beispiel #18
0
static int luazmq_skt_recv (lua_State *L) {
  zsocket *skt = luazmq_getsocket(L);
  zmq_msg_t msg;
  int flags = luaL_optint(L,2,0);
  int ret = zmq_msg_init(&msg);
  if(-1 == ret) return luazmq_fail(L, skt);
  ret = zmq_msg_recv(&msg, skt->skt, flags);
  if(-1 == ret){
    zmq_msg_close(&msg);
    return luazmq_fail(L, skt);
  }
  lua_pushlstring(L, zmq_msg_data(&msg), zmq_msg_size(&msg));
  if( zmq_msg_more(&msg) ){
    skt->flags |= LUAZMQ_FLAG_MORE;
    lua_pushboolean(L, 1);
  }
  else{
    skt->flags &= ~LUAZMQ_FLAG_MORE;
    lua_pushboolean(L, 0);
  }

  zmq_msg_close(&msg);
  return 2;
}
Beispiel #19
0
static int luazmq_skt_recvx (lua_State *L) {
  zsocket *skt = luazmq_getsocket(L);
  zmq_msg_t msg;
  int flags = luaL_optint(L,2,0);
  int i = 0;
  lua_settop(L, 1);

  while(1){
    int ret = zmq_msg_init(&msg);
    if(-1 == ret){
      ret = luazmq_fail(L, skt);
      {int j;for(j = ret; j >= 0; --j){
        lua_insert(L, 1);
      }}
      return ret + i;
    }

    ret = zmq_msg_recv(&msg, skt->skt, flags);
    if(-1 == ret){
      zmq_msg_close(&msg);
      ret = luazmq_fail(L, skt);
      {int j;for(j = ret; j >= 0; --j){
        lua_insert(L, 1);
      }}
      return ret + i;
    }

    i++;
    lua_checkstack(L, i);
    lua_pushlstring(L, zmq_msg_data(&msg), zmq_msg_size(&msg));
    ret = zmq_msg_more(&msg);
    zmq_msg_close(&msg);
    if(!ret) break;
  }
  return i;
}
Beispiel #20
0
JNIEXPORT jobject JNICALL
Java_org_zeromq_ZMQ_00024Event_recv (JNIEnv *env, jclass cls, jlong socket, jint flags)
{
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,2,2)
    zmq_msg_t event_msg;

    // read event message
    if (!read_msg(env, (void *) socket, &event_msg, flags))
        return NULL;

#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4,0,0)
    assert (zmq_msg_more(&event_msg) != 0);

    uint16_t event;
    int32_t value;
    // copy event data 
    char *data = (char *) zmq_msg_data(&event_msg);
    memcpy(&event, data, sizeof(event));
    memcpy(&value, data + sizeof(event), sizeof(value));

    if (zmq_msg_close(&event_msg) < 0) {
        raise_exception(env, zmq_errno());
        return NULL;
    }

    char addr[1025];
    char *paddr;
    zmq_msg_t addr_msg;

    // read address message
    if (!read_msg(env, (void *) socket, &addr_msg, flags))
        return NULL;
    assert (zmq_msg_more(&addr_msg) == 0);

    // copy the address string
    const size_t len = zmq_msg_size(&addr_msg);

    paddr = (char *)(len >= sizeof(addr) ? malloc(len + 1) : &addr);
    memcpy(paddr, zmq_msg_data(&addr_msg), len);
    *(paddr + len) = '\0';

    if (zmq_msg_close(&addr_msg) < 0) {
        raise_exception(env, zmq_errno());
        return NULL;
    }

    jstring address = env->NewStringUTF(paddr);
    if (len >= sizeof(addr))
        free(paddr);
    assert(address);

    return env->NewObject(cls, constructor, event, value, address);
#else
    assert (zmq_msg_more(&event_msg) == 0);

    zmq_event_t event;
    // copy event data to event struct
    memcpy (&event, zmq_msg_data (&event_msg), sizeof(event));

    if (zmq_msg_close(&event_msg) < 0) {
        raise_exception(env, zmq_errno());
        return NULL;
    }

    // the addr part is a pointer to a c string that libzmq might have already called free on
    // it is not to be trusted so better not use it at all
    switch (event.event) {
    case ZMQ_EVENT_CONNECTED:
        return env->NewObject(cls, constructor, event.event, event.data.connected.fd, NULL);
    case ZMQ_EVENT_CONNECT_DELAYED:
        return env->NewObject(cls, constructor, event.event, event.data.connect_delayed.err, NULL);
    case ZMQ_EVENT_CONNECT_RETRIED:
        return env->NewObject(cls, constructor, event.event, event.data.connect_retried.interval, NULL);
    case ZMQ_EVENT_LISTENING:
        return env->NewObject(cls, constructor, event.event, event.data.listening.fd, NULL);
    case ZMQ_EVENT_BIND_FAILED:
        return env->NewObject(cls, constructor, event.event, event.data.bind_failed.err, NULL);
    case ZMQ_EVENT_ACCEPTED:
        return env->NewObject(cls, constructor, event.event, event.data.accepted.fd, NULL);
    case ZMQ_EVENT_ACCEPT_FAILED:
        return env->NewObject(cls, constructor, event.event, event.data.accept_failed.err, NULL);
    case ZMQ_EVENT_CLOSED:
        return env->NewObject(cls, constructor, event.event, event.data.closed.fd, NULL);
    case ZMQ_EVENT_CLOSE_FAILED:
        return env->NewObject(cls, constructor, event.event, event.data.close_failed.err, NULL);
    case ZMQ_EVENT_DISCONNECTED:
        return env->NewObject(cls, constructor, event.event, event.data.disconnected.fd, NULL);
    default:
        return NULL;
    }
#endif // ZMQ_VERSION >= ZMQ_MAKE_VERSION(4,0,0)
#else
    return NULL;
#endif // ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,2,2)
}
Beispiel #21
0
static void test_stream_to_dealer ()
{
    int rc;
    char my_endpoint[MAX_SOCKET_STRING];

    //  We'll be using this socket in raw mode
    void *stream = test_context_socket (ZMQ_STREAM);

    int zero = 0;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero)));
    int enabled = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (stream, ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled)));
    bind_loopback_ipv4 (stream, my_endpoint, sizeof my_endpoint);

    //  We'll be using this socket as the other peer
    void *dealer = test_context_socket (ZMQ_DEALER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));

    //  Send a message on the dealer socket
    send_string_expect_success (dealer, "Hello", 0);

    //  Connecting sends a zero message
    //  First frame is routing id
    zmq_msg_t routing_id;
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&routing_id));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Verify the existence of Peer-Address metadata
    char const *peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Second frame is zero
    byte buffer[255];
    TEST_ASSERT_EQUAL_INT (
      0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 255, 0)));

    //  Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Real data follows
    //  First frame is routing id
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Second frame is greeting signature
    recv_array_expect_success (stream, greeting.signature, 0);

    //  Send our own protocol greeting
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&routing_id, stream, ZMQ_SNDMORE));
    TEST_ASSERT_EQUAL_INT (
      sizeof (greeting), TEST_ASSERT_SUCCESS_ERRNO (
                           zmq_send (stream, &greeting, sizeof (greeting), 0)));

    //  Now we expect the data from the DEALER socket
    //  We want the rest of greeting along with the Ready command
    int bytes_read = 0;
    while (bytes_read < 97) {
        //  First frame is the routing id of the connection (each time)
        TEST_ASSERT_GREATER_THAN_INT (
          0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)));
        TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));
        //  Second frame contains the next chunk of data
        TEST_ASSERT_SUCCESS_ERRNO (
          rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0));
        bytes_read += rc;
    }

    //  First two bytes are major and minor version numbers.
    TEST_ASSERT_EQUAL_INT (3, buffer[0]); //  ZMTP/3.0
    TEST_ASSERT_EQUAL_INT (0, buffer[1]);

    //  Mechanism is "NULL"
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2,
                                  "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 54, "\4\51\5READY", 8);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 62, "\13Socket-Type\0\0\0\6DEALER",
                                  22);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 84, "\10Identity\0\0\0\0", 13);

    //  Announce we are ready
    memcpy (buffer, "\4\51\5READY", 8);
    memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22);
    memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);

    //  Send Ready command
    TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (
                                       &routing_id, stream, ZMQ_SNDMORE)));
    TEST_ASSERT_EQUAL_INT (
      43, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, buffer, 43, 0)));

    //  Now we expect the data from the DEALER socket
    //  First frame is, again, the routing id of the connection
    TEST_ASSERT_GREATER_THAN_INT (
      0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Third frame contains Hello message from DEALER
    TEST_ASSERT_EQUAL_INT (7, TEST_ASSERT_SUCCESS_ERRNO (
                                zmq_recv (stream, buffer, sizeof buffer, 0)));

    //  Then we have a 5-byte message "Hello"
    TEST_ASSERT_EQUAL_INT (0, buffer[0]); //  Flags = 0
    TEST_ASSERT_EQUAL_INT (5, buffer[1]); //  Size = 5
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2, "Hello", 5);

    //  Send "World" back to DEALER
    TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (
                                       &routing_id, stream, ZMQ_SNDMORE)));
    byte world[] = {0, 5, 'W', 'o', 'r', 'l', 'd'};
    TEST_ASSERT_EQUAL_INT (
      sizeof (world),
      TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, world, sizeof (world), 0)));

    //  Expect response on DEALER socket
    recv_string_expect_success (dealer, "World", 0);

    //  Test large messages over STREAM socket
#define size 64000
    uint8_t msgout[size];
    memset (msgout, 0xAB, size);
    zmq_send (dealer, msgout, size, 0);

    uint8_t msgin[9 + size];
    memset (msgin, 0, 9 + size);
    bytes_read = 0;
    while (bytes_read < 9 + size) {
        //  Get routing id frame
        TEST_ASSERT_GREATER_THAN_INT (
          0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 256, 0)));
        //  Get next chunk
        TEST_ASSERT_GREATER_THAN_INT (
          0,
          TEST_ASSERT_SUCCESS_ERRNO (rc = zmq_recv (stream, msgin + bytes_read,
                                                    9 + size - bytes_read, 0)));
        bytes_read += rc;
    }
    for (int byte_nbr = 0; byte_nbr < size; byte_nbr++) {
        TEST_ASSERT_EQUAL_UINT8 (0xAB, msgin[9 + byte_nbr]);
    }
    test_context_socket_close (dealer);
    test_context_socket_close (stream);
}
bool TimesliceBuilderZeromq::run_cycle() {
  auto& c = connections_.at(conn_);

  std::size_t msg_size;

  // send request for timeslice data
  int rc;
  do {
    rc = zmq_send(c->socket, &ts_index_, sizeof(ts_index_), 0);
  } while (rc == -1 && errno == EAGAIN && *signal_status_ == 0);
  if (*signal_status_ != 0) {
    return true;
  }

  // receive desc answer (part 1), do not release
  rc = zmq_msg_init(&c->desc_msg);
  assert(rc == 0);
  do {
    rc = zmq_msg_recv(&c->desc_msg, c->socket, 0);
  } while (rc == -1 && errno == EAGAIN && *signal_status_ == 0);
  if (*signal_status_ != 0) {
    return true;
  }
  assert(rc != -1);
  msg_size = zmq_msg_size(&c->desc_msg);
  if (msg_size == 0) {
    zmq_msg_close(&c->desc_msg);
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  if (msg_size == 0 || *signal_status_ != 0) {
    return true;
  }

  // receive data answer (part 2), do not release
  assert(zmq_msg_more(&c->desc_msg));
  rc = zmq_msg_init(&c->data_msg);
  assert(rc == 0);
  do {
    rc = zmq_msg_recv(&c->data_msg, c->socket, 0);
  } while (rc == -1 && errno == EAGAIN && *signal_status_ == 0);
  if (*signal_status_ != 0) {
    return true;
  }
  assert(rc != -1);

  uint64_t size_required =
      zmq_msg_size(&c->desc_msg) + zmq_msg_size(&c->data_msg);

  while (c->data.size_available_contiguous() < size_required ||
         c->desc.size_available() < 1) {
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    handle_timeslice_completions();
  }

  // skip remaining bytes in data buffer to avoid fractured entry
  c->data.skip_buffer_wrap(size_required);

  // generate timeslice component descriptor
  assert(tpos_ == c->desc.write_index());
  c->desc.append(
      {ts_index_, c->data.write_index(), size_required,
       zmq_msg_size(&c->desc_msg) / sizeof(fles::MicrosliceDescriptor)});

  // copy into shared memory and release messages
  c->data.append(static_cast<uint8_t*>(zmq_msg_data(&c->desc_msg)),
                 zmq_msg_size(&c->desc_msg));
  c->data.append(static_cast<uint8_t*>(zmq_msg_data(&c->data_msg)),
                 zmq_msg_size(&c->data_msg));
  zmq_msg_close(&c->desc_msg);
  zmq_msg_close(&c->data_msg);

  ++conn_;
  if (conn_ == connections_.size()) {
    conn_ = 0;

    handle_timeslice_completions();

    timeslice_buffer_.send_work_item(
        {{ts_index_, tpos_, timeslice_size_,
          static_cast<uint32_t>(connections_.size())},
         timeslice_buffer_.get_data_size_exp(),
         timeslice_buffer_.get_desc_size_exp()});
    ++tpos_;
    // next timeslice: round robin
    ts_index_ += num_compute_nodes_;
  }

  return true;
}
int main (void)
{
    setup_test_environment();
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    void *server = zmq_socket (ctx, ZMQ_SERVER);
    void *client = zmq_socket (ctx, ZMQ_DEALER);

    int rc;

    rc = zmq_bind (server, "inproc://serverdropmore");
    assert (rc == 0);

    rc = zmq_connect (client, "inproc://serverdropmore");
    assert (rc == 0);

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    // we will send 2 3-frames messages and then single frame message, only last one should be received
    rc = send_msg (&msg, client, ZMQ_SNDMORE, 1);
    assert(rc == 1);

    rc = send_msg (&msg, client, ZMQ_SNDMORE, 2);
    assert(rc == 1);

    rc = send_msg (&msg, client, 0, 3);
    assert(rc == 1);

    rc = send_msg (&msg, client, ZMQ_SNDMORE, 4);
    assert(rc == 1);

    rc = send_msg (&msg, client, ZMQ_SNDMORE, 5);
    assert(rc == 1);

    rc = send_msg (&msg, client, 0, 6);
    assert(rc == 1);

    rc = send_msg (&msg, client, 0, 7);
    assert(rc == 1);

    rc = zmq_msg_recv (&msg, server, 0);
    assert (rc == 1);

    assert(zmq_msg_more(&msg) == 0);

    unsigned char* data = (unsigned char*)zmq_msg_data (&msg);
    assert (data[0] == 7);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    rc = zmq_close (server);
    assert (rc == 0);

    rc = zmq_close (client);
    assert (rc == 0);

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0 ;
}
Beispiel #24
0
 bool more() const {
     return zmq_msg_more(const_cast<zmq_msg_t*>(&msg_)) ? true : false;
 }
int main (void)
{
    setup_test_environment ();
    //  Create the infrastructure
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    void *sb = zmq_socket (ctx, ZMQ_ROUTER);
    assert (sb);

    int rc = zmq_bind (sb, "inproc://a");
    assert (rc == 0);

    void *sc = zmq_socket (ctx, ZMQ_DEALER);
    assert (sc);

    rc = zmq_connect (sc, "inproc://a");
    assert (rc == 0);

    //  Send 2-part message.
    rc = zmq_send (sc, "A", 1, ZMQ_SNDMORE);
    assert (rc == 1);
    rc = zmq_send (sc, "B", 1, 0);
    assert (rc == 1);

    //  Routing id comes first.
    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc >= 0);
    int more = zmq_msg_more (&msg);
    assert (more == 1);

    //  Then the first part of the message body.
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc == 1);
    more = zmq_msg_more (&msg);
    assert (more == 1);

    //  And finally, the second part of the message body.
    rc = zmq_msg_recv (&msg, sb, 0);
    assert (rc == 1);
    more = zmq_msg_more (&msg);
    assert (more == 0);

    // Test ZMQ_SHARED property (case 1, refcounted messages)
    zmq_msg_t msg_a;
    rc = zmq_msg_init_size (&msg_a, 1024); // large enough to be a type_lmsg
    assert (rc == 0);

    // Message is not shared
    rc = zmq_msg_get (&msg_a, ZMQ_SHARED);
    assert (rc == 0);

    zmq_msg_t msg_b;
    rc = zmq_msg_init (&msg_b);
    assert (rc == 0);

    rc = zmq_msg_copy (&msg_b, &msg_a);
    assert (rc == 0);

    // Message is now shared
    rc = zmq_msg_get (&msg_b, ZMQ_SHARED);
    assert (rc == 1);

    // cleanup
    rc = zmq_msg_close (&msg_a);
    assert (rc == 0);
    rc = zmq_msg_close (&msg_b);
    assert (rc == 0);

    // Test ZMQ_SHARED property (case 2, constant data messages)
    rc = zmq_msg_init_data (&msg_a, (void *) "TEST", 5, 0, 0);
    assert (rc == 0);

    // Message reports as shared
    rc = zmq_msg_get (&msg_a, ZMQ_SHARED);
    assert (rc == 1);

    // cleanup
    rc = zmq_msg_close (&msg_a);
    assert (rc == 0);

    //  Deallocate the infrastructure.
    rc = zmq_close (sc);
    assert (rc == 0);

    rc = zmq_close (sb);
    assert (rc == 0);

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
    return 0;
}
Beispiel #26
0
static void
test_stream_to_dealer (void)
{
    int rc;

    //  Set up our context and sockets
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  We'll be using this socket in raw mode
    void *stream = zmq_socket (ctx, ZMQ_STREAM);
    assert (stream);

    int zero = 0;
    rc = zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    int enabled = 1;
    rc = zmq_setsockopt (stream, ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled));
    assert (rc == 0);
    rc = zmq_bind (stream, "tcp://127.0.0.1:5556");
    assert (rc == 0);

    //  We'll be using this socket as the other peer
    void *dealer = zmq_socket (ctx, ZMQ_DEALER);
    assert (dealer);
    rc = zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    rc = zmq_connect (dealer, "tcp://localhost:5556");

    //  Send a message on the dealer socket
    rc = zmq_send (dealer, "Hello", 5, 0);
    assert (rc == 5);

    //  Connecting sends a zero message
    //  First frame is identity
    zmq_msg_t identity;
    rc = zmq_msg_init (&identity);
    assert (rc == 0);
    rc = zmq_msg_recv (&identity, stream, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    // Verify the existence of Peer-Address metadata
    char const* peer_address = zmq_msg_gets (&identity, "Peer-Address");
    assert (peer_address != 0);
    assert (streq (peer_address, "127.0.0.1"));

    //  Second frame is zero
    byte buffer [255];
    rc = zmq_recv (stream, buffer, 255, 0);
    assert (rc == 0);

    // Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&identity, "Peer-Address");
    assert (peer_address != 0);
    assert (streq (peer_address, "127.0.0.1"));

    //  Real data follows
    //  First frame is identity
    rc = zmq_msg_recv (&identity, stream, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    // Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&identity, "Peer-Address");
    assert (peer_address != 0);
    assert (streq (peer_address, "127.0.0.1"));

    //  Second frame is greeting signature
    rc = zmq_recv (stream, buffer, 255, 0);
    assert (rc == 10);
    assert (memcmp (buffer, greeting.signature, 10) == 0);

    //  Send our own protocol greeting
    rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE);
    assert (rc > 0);
    rc = zmq_send (stream, &greeting, sizeof (greeting), 0);
    assert (rc == sizeof (greeting));

    //  Now we expect the data from the DEALER socket
    //  We want the rest of greeting along with the Ready command
    int bytes_read = 0;
    while (bytes_read < 97) {
        //  First frame is the identity of the connection (each time)
        rc = zmq_msg_recv (&identity, stream, 0);
        assert (rc > 0);
        assert (zmq_msg_more (&identity));
        //  Second frame contains the next chunk of data
        rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0);
        assert (rc >= 0);
        bytes_read += rc;
    }

    //  First two bytes are major and minor version numbers.
    assert (buffer [0] == 3);       //  ZMTP/3.0
    assert (buffer [1] == 0);

    //  Mechanism is "NULL"
    assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0);
    assert (memcmp (buffer + 54, "\4\51\5READY", 8) == 0);
    assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
    assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0);

    //  Announce we are ready
    memcpy (buffer, "\4\51\5READY", 8);
    memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22);
    memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);

    //  Send Ready command
    rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE);
    assert (rc > 0);
    rc = zmq_send (stream, buffer, 43, 0);
    assert (rc == 43);

    //  Now we expect the data from the DEALER socket
    //  First frame is, again, the identity of the connection
    rc = zmq_msg_recv (&identity, stream, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    //  Third frame contains Hello message from DEALER
    rc = zmq_recv (stream, buffer, sizeof buffer, 0);
    assert (rc == 7);

    //  Then we have a 5-byte message "Hello"
    assert (buffer [0] == 0);       //  Flags = 0
    assert (buffer [1] == 5);       //  Size = 5
    assert (memcmp (buffer + 2, "Hello", 5) == 0);

    //  Send "World" back to DEALER
    rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE);
    assert (rc > 0);
    byte world [] = { 0, 5, 'W', 'o', 'r', 'l', 'd' };
    rc = zmq_send (stream, world, sizeof (world), 0);
    assert (rc == sizeof (world));

    //  Expect response on DEALER socket
    rc = zmq_recv (dealer, buffer, 255, 0);
    assert (rc == 5);
    assert (memcmp (buffer, "World", 5) == 0);

    rc = zmq_close (dealer);
    assert (rc == 0);

    rc = zmq_close (stream);
    assert (rc == 0);

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
}
Beispiel #27
0
 inline bool has_more()
 {
     return zmq_msg_more(&msg);
 }
Beispiel #28
0
static int luazmq_msg_more(lua_State *L){
  zmessage *zmsg = luazmq_getmessage(L);
  lua_pushboolean(L, zmq_msg_more(&zmsg->msg));
  return 1;
}
 inline bool more ()
 {
     int rc = zmq_msg_more (&msg);
     return rc != 0;
 }
Beispiel #30
0
int main (void)
{
    int rc;

    //  Set up our context and sockets
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  We'll be using this socket in raw mode
    void *router = zmq_socket (ctx, ZMQ_ROUTER);
    assert (router);

    int on = 1;
    rc = zmq_setsockopt (router, ZMQ_ROUTER_RAW, &on, sizeof (on));
    assert (rc == 0);
    int zero = 0;
    rc = zmq_setsockopt (router, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    rc = zmq_bind (router, "tcp://*:5555");
    assert (rc == 0);

    //  We'll be using this socket as the other peer
    void *dealer = zmq_socket (ctx, ZMQ_DEALER);
    assert (dealer);
    rc = zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    rc = zmq_connect (dealer, "tcp://localhost:5555");

    //  Send a message on the dealer socket
    rc = zmq_send (dealer, "Hello", 5, 0);
    assert (rc == 5);

    //  First frame is identity
    zmq_msg_t identity;
    rc = zmq_msg_init (&identity);
    assert (rc == 0);
    rc = zmq_msg_recv (&identity, router, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    //  Second frame is greeting signature
    byte buffer [255];
    rc = zmq_recv (router, buffer, 255, 0);
    assert (rc == 10);
    assert (memcmp (buffer, greeting.signature, 10) == 0);

    //  Send our own protocol greeting
    rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE);
    assert (rc > 0);
    rc = zmq_send (router, &greeting, sizeof (greeting), 0);
    assert (rc == sizeof (greeting));

    //  Now we expect the data from the DEALER socket
    //  First frame is, again, the identity of the connection
    rc = zmq_msg_recv (&identity, router, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    //  Second frame contains the rest of greeting along with
    //  the Ready command
    rc = zmq_recv (router, buffer, 255, 0);
    assert (rc == 97);

    //  First two bytes are major and minor version numbers.
    assert (buffer [0] == 3);       //  ZMTP/3.0
    assert (buffer [1] == 0);

    //  Mechanism is "NULL"
    assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22) == 0);
    assert (memcmp (buffer + 54, "\0\51READY\0", 8) == 0);
    assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
    assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0);

    //  Announce we are ready
    memcpy (buffer, "\0\51READY\0", 8);
    memcpy (buffer + 8, "\13Socket-Type\0\0\0\6STREAM", 22);
    memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);

    //  Send Ready command
    rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE);
    assert (rc > 0);
    rc = zmq_send (router, buffer, 43, 0);
    assert (rc == 43);

    //  Now we expect the data from the DEALER socket
    //  First frame is, again, the identity of the connection
    rc = zmq_msg_recv (&identity, router, 0);
    assert (rc > 0);
    assert (zmq_msg_more (&identity));

    //  Third frame contains Hello message from DEALER
    rc = zmq_recv (router, buffer, sizeof buffer, 0);
    assert (rc == 7);

    //  Then we have a 5-byte message "Hello"
    assert (buffer [0] == 0);       //  Flags = 0
    assert (buffer [1] == 5);       //  Size = 5
    assert (memcmp (buffer + 2, "Hello", 5) == 0);

    //  Send "World" back to DEALER
    rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE);
    assert (rc > 0);
    byte world [] = { 0, 5, 'W', 'o', 'r', 'l', 'd' };
    rc = zmq_send (router, world, sizeof (world), 0);
    assert (rc == sizeof (world));

    //  Expect response on DEALER socket
    rc = zmq_recv (dealer, buffer, 255, 0);
    assert (rc == 5);
    assert (memcmp (buffer, "World", 5) == 0);

    rc = zmq_close (dealer);
    assert (rc == 0);

    rc = zmq_close (router);
    assert (rc == 0);

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0;
}