Beispiel #1
0
int main (int argc, const char *argv[])
{
    int rc;
    int pair;
    int pull;
    int timeo;
    char socket_address_tcp[128];

    test_addr_from(socket_address_tcp, "tcp", "127.0.0.1",
            get_test_port(argc, argv));

    /*  Inproc: Bind first, connect second. */
    pair = test_socket (AF_SP, NN_PAIR);
    test_bind (pair, SOCKET_ADDRESS_INPROC);
    pull = test_socket (AF_SP, NN_PULL);
    test_connect (pull, SOCKET_ADDRESS_INPROC);
    timeo = 100;
    test_setsockopt (pair, NN_SOL_SOCKET, NN_SNDTIMEO,
        &timeo, sizeof (timeo));
    rc = nn_send (pair, "ABC", 3, 0);
    errno_assert (rc < 0 && nn_errno () == ETIMEDOUT);
    test_close (pull);
    test_close (pair);

    /*  Inproc: Connect first, bind second. */
    pull = test_socket (AF_SP, NN_PULL);
    test_connect (pull, SOCKET_ADDRESS_INPROC);
    pair = test_socket (AF_SP, NN_PAIR);
    test_bind (pair, SOCKET_ADDRESS_INPROC);
    timeo = 100;
    test_setsockopt (pair, NN_SOL_SOCKET, NN_SNDTIMEO,
        &timeo, sizeof (timeo));
    rc = nn_send (pair, "ABC", 3, 0);
    errno_assert (rc < 0 && nn_errno () == ETIMEDOUT);
    test_close (pull);
    test_close (pair);

#if !defined NN_HAVE_WINDOWS

    /*  IPC */
    pair = test_socket (AF_SP, NN_PAIR);
    test_bind (pair, SOCKET_ADDRESS_IPC);
    pull = test_socket (AF_SP, NN_PULL);
    test_connect (pull, SOCKET_ADDRESS_IPC);
    timeo = 100;
    test_setsockopt (pair, NN_SOL_SOCKET, NN_SNDTIMEO,
        &timeo, sizeof (timeo));
    rc = nn_send (pair, "ABC", 3, 0);
    errno_assert (rc < 0 && nn_errno () == ETIMEDOUT);
    test_close (pull);
    test_close (pair);

#endif

    /*  TCP */
    pair = test_socket (AF_SP, NN_PAIR);
    test_bind (pair, socket_address_tcp);
    pull = test_socket (AF_SP, NN_PULL);
    test_connect (pull, socket_address_tcp);
    timeo = 100;
    test_setsockopt (pair, NN_SOL_SOCKET, NN_SNDTIMEO,
        &timeo, sizeof (timeo));
    rc = nn_send (pair, "ABC", 3, 0);
    errno_assert (rc < 0 && nn_errno () == ETIMEDOUT);
    test_close (pull);
    test_close (pair);

    return 0;
}
Beispiel #2
0
 exception () : err (nn_errno ()) {}
Beispiel #3
0
int main ()
{
    int rc;
    int surveyor;
    int respondent1;
    int respondent2;
    int respondent3;
    int deadline;
    char buf [7];

    /*  Test a simple survey with three respondents. */
    surveyor = test_socket (AF_SP, NN_SURVEYOR);
    deadline = 500;
    rc = nn_setsockopt (surveyor, NN_SURVEYOR, NN_SURVEYOR_DEADLINE,
        &deadline, sizeof (deadline));
    errno_assert (rc == 0);
    test_bind (surveyor, SOCKET_ADDRESS);
    respondent1 = test_socket (AF_SP, NN_RESPONDENT);
    test_connect (respondent1, SOCKET_ADDRESS);
    respondent2 = test_socket (AF_SP, NN_RESPONDENT);
    test_connect (respondent2, SOCKET_ADDRESS);
    respondent3 = test_socket (AF_SP, NN_RESPONDENT);
    test_connect (respondent3, SOCKET_ADDRESS);

    /* Check that attempt to recv with no survey pending is EFSM. */
    rc = nn_recv (surveyor, buf, sizeof (buf), 0);
    errno_assert (rc == -1 && nn_errno () == EFSM);

    /*  Send the survey. */
    test_send (surveyor, "ABC");

    /*  First respondent answers. */
    test_recv (respondent1, "ABC");
    test_send (respondent1, "DEF");

    /*  Second respondent answers. */
    test_recv (respondent2, "ABC");
    test_send (respondent2, "DEF");

    /*  Surveyor gets the responses. */
    test_recv (surveyor, "DEF");
    test_recv (surveyor, "DEF");

    /*  There are no more responses. Surveyor hits the deadline. */
    rc = nn_recv (surveyor, buf, sizeof (buf), 0);
    errno_assert (rc == -1 && nn_errno () == ETIMEDOUT);

    /*  Third respondent answers (it have already missed the deadline). */
    test_recv (respondent3, "ABC");
    test_send (respondent3, "GHI");

    /*  Surveyor initiates new survey. */
    test_send (surveyor, "ABC");

    /*  Check that stale response from third respondent is not delivered. */
    rc = nn_recv (surveyor, buf, sizeof (buf), 0);
    errno_assert (rc == -1 && nn_errno () == ETIMEDOUT);

    /* Check that subsequent attempt to recv with no survey pending is EFSM. */
    rc = nn_recv (surveyor, buf, sizeof (buf), 0);
    errno_assert (rc == -1 && nn_errno () == EFSM);

    test_close (surveyor);
    test_close (respondent1);
    test_close (respondent2);
    test_close (respondent3);

    return 0;
}
Beispiel #4
0
JNIEXPORT jint JNICALL Java_org_nanomsg_NanoLibrary_nn_1errno(JNIEnv* env,
                                                              jobject obj)
{
    return nn_errno();
}
Beispiel #5
0
int zmq_errno ()
{
    return nn_errno ();
}
int outprocessControlThread(void *param)
{
	OUTPROCESS_HANDLE_DATA * handleData = (OUTPROCESS_HANDLE_DATA*)param;
	if (handleData == NULL)
	{
		LogError("outprocessControlThread: parameter is NULL");
	}
	else
	{
		int should_continue = 1;
		int needs_to_attach = 0;

		while (should_continue)
		{
			/*Codes_SRS_OUTPROCESS_MODULE_17_056: [ This thread shall ensure thread safety on the module data. ]*/
			if (Lock(handleData->control_thread.thread_lock) != LOCK_OK)
			{
				LogError("unable to Lock");
				should_continue = 0;
				break;
			}
			if (handleData->control_thread.thread_flag == THREAD_FLAG_STOP)
			{
				should_continue = 0;
				(void)Unlock(handleData->control_thread.thread_lock);
				break;
			}
			if (Unlock(handleData->control_thread.thread_lock) != LOCK_OK)
			{
				should_continue = 0;
				break;
			}

			if (needs_to_attach)
			{
				// our remote has detached.  Attempt to reattach.
				/*Codes_SRS_OUTPROCESS_MODULE_17_059: [ If a Module Reply message has been received, and the status indicates the module has failed or has been terminated, this thread shall attempt to restart communications with module host process. ]*/

				/*Codes_SRS_OUTPROCESS_MODULE_17_060: [ Once the control channel has been restarted, it shall follow the same process in Outprocess_Create to send a Create Message to the module host. ]*/
				if (outprocessCreate(handleData) < 0)
				{
					LogError("attempting to reattach to remote failed");
				}
				else
				{
                    /*Codes_SRS_OUTPROCESS_MODULE_24_061: [ Once the control channel has been restarted and Create Message was sent, it shall send a Start Message to the module host. ]*/
                    send_start_message(handleData);
					needs_to_attach = 0;
				}
			}

			/*Codes_SRS_OUTPROCESS_MODULE_17_056: [ This thread shall ensure thread safety on the module data. ]*/
			if (Lock(handleData->handle_lock) != LOCK_OK)
			{
				LogError("unable to Lock handle data");
				should_continue = 0;
				break;
			}
			int nn_fd = handleData->control_socket;
			if (Unlock(handleData->handle_lock) != LOCK_OK)
			{
				should_continue = 0;
				break;
			}

			int nbytes;
			unsigned char *buf = NULL;
			errno = 0;
			/*Codes_SRS_OUTPROCESS_MODULE_17_057: [ This thread shall periodically attempt to receive a meesage from the module host process. ]*/
			nbytes = nn_recv(nn_fd, (void *)&buf, NN_MSG, NN_DONTWAIT);
			if (nbytes < 0)
			{
				int receive_error = nn_errno();
				if (receive_error != EAGAIN)
					should_continue = 0;
			}
			else
			{
				CONTROL_MESSAGE * msg = ControlMessage_CreateFromByteArray((const unsigned char*)buf, nbytes);
				nn_freemsg(buf);
				if (msg != NULL)
				{
					/*Codes_SRS_OUTPROCESS_MODULE_17_058: [ If a message has been received, it shall look for a Module Reply message. ]*/
					if (msg->type == CONTROL_MESSAGE_TYPE_MODULE_REPLY)
					{
						CONTROL_MESSAGE_MODULE_REPLY * resp_msg = (CONTROL_MESSAGE_MODULE_REPLY*)msg;
						if (resp_msg->status != 0)
						{
							/*Codes_SRS_OUTPROCESS_MODULE_17_059: [ If a Module Reply message has been received, and the status indicates the module has failed or has been terminated, this thread shall attempt to restart communications with module host process. ]*/
							needs_to_attach = 1;
						}
					}
					ControlMessage_Destroy(msg);
				}
			}
			ThreadAPI_Sleep(250);
		}
	}
	return 0;
}
Beispiel #7
0
int main ()
{
    int rc;
    int push1;
    int push2;
    int pull1;
    int pull2;
    int sndprio;
    int rcvprio;

    /*  Test send priorities. */

    pull1 = test_socket (AF_SP, NN_PULL);
    test_bind (pull1, SOCKET_ADDRESS_A);
    pull2 = test_socket (AF_SP, NN_PULL);
    test_bind (pull2, SOCKET_ADDRESS_B);
    push1 = test_socket (AF_SP, NN_PUSH);
    sndprio = 1;
    rc = nn_setsockopt (push1, NN_SOL_SOCKET, NN_SNDPRIO,
        &sndprio, sizeof (sndprio));
    errno_assert (rc == 0);
    test_connect (push1, SOCKET_ADDRESS_A);
    sndprio = 2;
    rc = nn_setsockopt (push1, NN_SOL_SOCKET, NN_SNDPRIO,
        &sndprio, sizeof (sndprio));
    errno_assert (rc == 0);
    test_connect (push1, SOCKET_ADDRESS_B);

    test_send (push1, "ABC");
    test_send (push1, "DEF");
    test_recv (pull1, "ABC");
    test_recv (pull1, "DEF");

    test_close (pull1);
    test_close (push1);
    test_close (pull2);

    /*  Test receive priorities. */

    push1 = test_socket (AF_SP, NN_PUSH);
    test_bind (push1, SOCKET_ADDRESS_A);
    push2 = test_socket (AF_SP, NN_PUSH);
    test_bind (push2, SOCKET_ADDRESS_B);
    pull1 = test_socket (AF_SP, NN_PULL);
    rcvprio = 2;
    rc = nn_setsockopt (pull1, NN_SOL_SOCKET, NN_RCVPRIO,
        &rcvprio, sizeof (rcvprio));
    errno_assert (rc == 0);
    test_connect (pull1, SOCKET_ADDRESS_A);
    rcvprio = 1;
    rc = nn_setsockopt (pull1, NN_SOL_SOCKET, NN_RCVPRIO,
        &rcvprio, sizeof (rcvprio));
    errno_assert (rc == 0);
    test_connect (pull1, SOCKET_ADDRESS_B);

    test_send (push1, "ABC");
    test_send (push2, "DEF");
    nn_sleep (100);
    test_recv (pull1, "DEF");
    test_recv (pull1, "ABC");

    test_close (pull1);
    test_close (push2);
    test_close (push1);

    /*  Test removing a pipe from the list. */

    push1 = test_socket (AF_SP, NN_PUSH);
    test_bind (push1, SOCKET_ADDRESS_A);
    pull1 = test_socket (AF_SP, NN_PULL);
    test_connect (pull1, SOCKET_ADDRESS_A);

    test_send (push1, "ABC");
    test_recv (pull1, "ABC");
    test_close (pull1);

    rc = nn_send (push1, "ABC", 3, NN_DONTWAIT);
    nn_assert (rc == -1 && nn_errno() == EAGAIN);

    pull1 = test_socket (AF_SP, NN_PULL);
    test_connect (pull1, SOCKET_ADDRESS_A);

    test_send (push1, "ABC");
    test_recv (pull1, "ABC");
    test_close (pull1);
    test_close (push1);

    return 0;
}
Beispiel #8
0
int main ()
{
    int rc;
    int rep1;
    int rep2;
    int req1;
    int req2;
    int resend_ivl;
    char buf [7];
    int timeo;

    /*  Test req/rep with full socket types. */
    rep1 = nn_socket (AF_SP, NN_REP);
    errno_assert (rep1 != -1);
    rc = nn_bind (rep1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    req1 = nn_socket (AF_SP, NN_REQ);
    errno_assert (req1 != -1);
    rc = nn_connect (req1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    req2 = nn_socket (AF_SP, NN_REQ);
    errno_assert (req2 != -1);
    rc = nn_connect (req2, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    /*  Check invalid sequence of sends and recvs. */
    rc = nn_send (rep1, "ABC", 3, 0);
    nn_assert (rc == -1 && nn_errno () == EFSM);
    rc = nn_recv (req1, buf, sizeof (buf), 0);
    nn_assert (rc == -1 && nn_errno () == EFSM);

    /*  Check fair queueing the requests. */
    rc = nn_send (req2, "ABC", 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_send (rep1, buf, 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (req2, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_send (req1, "ABC", 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_send (rep1, buf, 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (req1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_close (rep1);
    errno_assert (rc == 0);
    rc = nn_close (req1);
    errno_assert (rc == 0);    
    rc = nn_close (req2);
    errno_assert (rc == 0);

    /*  Check load-balancing of requests. */
    req1 = nn_socket (AF_SP, NN_REQ);
    errno_assert (req1 != -1);
    rc = nn_bind (req1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    rep1 = nn_socket (AF_SP, NN_REP);
    errno_assert (rep1 != -1);
    rc = nn_connect (rep1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    rep2 = nn_socket (AF_SP, NN_REP);
    errno_assert (rep2 != -1);
    rc = nn_connect (rep2, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    rc = nn_send (req1, "ABC", 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_send (rep1, buf, 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (req1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_send (req1, "ABC", 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep2, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_send (rep2, buf, 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (req1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_close (rep2);
    errno_assert (rc == 0);
    rc = nn_close (rep1);
    errno_assert (rc == 0);    
    rc = nn_close (req1);
    errno_assert (rc == 0);

    /*  Test re-sending of the request. */
    rep1 = nn_socket (AF_SP, NN_REP);
    errno_assert (rep1 != -1);
    rc = nn_bind (rep1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    req1 = nn_socket (AF_SP, NN_REQ);
    errno_assert (req1 != -1);
    rc = nn_connect (req1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    resend_ivl = 100;
    rc = nn_setsockopt (req1, NN_REQ, NN_REQ_RESEND_IVL,
        &resend_ivl, sizeof (resend_ivl));
    errno_assert (rc == 0);

    rc = nn_send (req1, "ABC", 3, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_close (req1);
    errno_assert (rc == 0);
    rc = nn_close (rep1);
    errno_assert (rc == 0);

    /*  Check sending a request when the peer is not available. (It should
        be sent immediatelly when the peer comes online rather than relying
        on the resend algorithm. */
    req1 = nn_socket (AF_SP, NN_REQ);
    errno_assert (req1 != -1);
    rc = nn_connect (req1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    rc = nn_send (req1, "ABC", 3, 0);
    errno_assert (rc >= 0);

    rep1 = nn_socket (AF_SP, NN_REP);
    errno_assert (rep1 != -1);
    rc = nn_bind (rep1, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    timeo = 100;
    rc = nn_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO,
       &timeo, sizeof (timeo));
    errno_assert (rc == 0);
    rc = nn_recv (rep1, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    rc = nn_close (req1);
    errno_assert (rc == 0);
    rc = nn_close (rep1);
    errno_assert (rc == 0);

    return 0;
}
Beispiel #9
0
bool pnet_internal_create_socket(pnet_socket *socket, pint16 type)
{
    if (unlikely(!socket)) {
        plog_error("pnet_internal_create_socket() нет объекта socket");
        return false;
    }

    int sock = nn_socket(AF_SP_RAW, type);
    if (unlikely(sock < 0)) {
        plog_error("pnet_internal_create_socket() не удалось создать сокет | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    socket->socket_fd = sock;

    int val = 1;
    if (unlikely(nn_setsockopt(socket->socket_fd, NN_TCP, NN_TCP_NODELAY, &val, sizeof(val)))) {
        plog_error("pnet_internal_create_socket() не удалось выставить NN_TCP_NODELAY | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    val = 0;
    if (unlikely(nn_setsockopt(socket->socket_fd, NN_SOL_SOCKET, NN_LINGER, &val, sizeof(val)))) {
        plog_error("pnet_internal_create_socket() не удалось выставить NN_LINGER | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    val = 10000;
    if (unlikely(nn_setsockopt(socket->socket_fd, NN_SOL_SOCKET, NN_RECONNECT_IVL_MAX, &val, sizeof(val)))) {
        plog_error("pnet_internal_create_socket() не удалось выставить NN_RECONNECT_IVL_MAX | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    return true;
}
Beispiel #10
0
int nn_device_entry (struct nn_device_recipe *device, int s1, int s2,
    NN_UNUSED int flags) 
{
    int rc;
    int op1;
    int op2;
    nn_fd s1rcv;
    nn_fd s1snd;
    nn_fd s2rcv;
    nn_fd s2snd;
    size_t opsz;

    /*  At least one socket must be specified. */
    if (device->required_checks & NN_CHECK_AT_LEAST_ONE_SOCKET) {
        if (s1 < 0 && s2 < 0) {
            errno = EBADF;
            return -1;
        }
    }

    /*  Handle the case when there's only one socket in the device. */
    if (device->required_checks & NN_CHECK_ALLOW_LOOPBACK) {
        if (s2 < 0)
            return nn_device_loopback (device,s1);
        if (s1 < 0)
            return nn_device_loopback (device,s2);
    }

    /*  Check whether both sockets are "raw" sockets. */
    if (device->required_checks & NN_CHECK_REQUIRE_RAW_SOCKETS) {
        opsz = sizeof (op1);
        rc = nn_getsockopt (s1, NN_SOL_SOCKET, NN_DOMAIN, &op1, &opsz);
        errno_assert (rc == 0);
        nn_assert (opsz == sizeof (op1));
        opsz = sizeof (op2);
        rc = nn_getsockopt (s2, NN_SOL_SOCKET, NN_DOMAIN, &op2, &opsz);
        errno_assert (rc == 0);
        nn_assert (opsz == sizeof (op2));
        if (op1 != AF_SP_RAW || op2 != AF_SP_RAW) {
            errno = EINVAL;
            return -1;
        }
    }

    /*  Check whether both sockets are from the same protocol. */
    if (device->required_checks & NN_CHECK_SAME_PROTOCOL_FAMILY) {
        opsz = sizeof (op1);
        rc = nn_getsockopt (s1, NN_SOL_SOCKET, NN_PROTOCOL, &op1, &opsz);
        errno_assert (rc == 0);
        nn_assert (opsz == sizeof (op1));
        opsz = sizeof (op2);
        rc = nn_getsockopt (s2, NN_SOL_SOCKET, NN_PROTOCOL, &op2, &opsz);
        errno_assert (rc == 0);
        nn_assert (opsz == sizeof (op2));
        if (op1 / 16 != op2 / 16) {
            errno = EINVAL;
            return -1;
        }
    }

    /*  Get the file descriptors for polling. */
    opsz = sizeof (s1rcv);
    rc = nn_getsockopt (s1, NN_SOL_SOCKET, NN_RCVFD, &s1rcv, &opsz);
    if (rc < 0 && nn_errno () == ENOPROTOOPT)
        s1rcv = -1;
    else {
        nn_assert (rc == 0);
        nn_assert (opsz == sizeof (s1rcv));
        nn_assert (s1rcv >= 0);
    }
    opsz = sizeof (s1snd);
    rc = nn_getsockopt (s1, NN_SOL_SOCKET, NN_SNDFD, &s1snd, &opsz);
    if (rc < 0 && nn_errno () == ENOPROTOOPT)
        s1snd = -1;
    else {
        nn_assert (rc == 0);
        nn_assert (opsz == sizeof (s1snd));
        nn_assert (s1snd >= 0);
    }
    opsz = sizeof (s2rcv);
    rc = nn_getsockopt (s2, NN_SOL_SOCKET, NN_RCVFD, &s2rcv, &opsz);
    if (rc < 0 && nn_errno () == ENOPROTOOPT)
        s2rcv = -1;
    else {
        nn_assert (rc == 0);
        nn_assert (opsz == sizeof (s2rcv));
        nn_assert (s2rcv >= 0);
    }
    opsz = sizeof (s2snd);
    rc = nn_getsockopt (s2, NN_SOL_SOCKET, NN_SNDFD, &s2snd, &opsz);
    if (rc < 0 && nn_errno () == ENOPROTOOPT)
        s2snd = -1;
    else {
        nn_assert (rc == 0);
        nn_assert (opsz == sizeof (s2snd));
        nn_assert (s2snd >= 0);
    }
    if (device->required_checks & NN_CHECK_SOCKET_DIRECTIONALITY) {
        /*  Check the directionality of the sockets. */
        if (s1rcv != -1 && s2snd == -1) {
            errno = EINVAL;
            return -1;
        }
        if (s1snd != -1 && s2rcv == -1) {
            errno = EINVAL;
            return -1;
        }
        if (s2rcv != -1 && s1snd == -1) {
            errno = EINVAL;
            return -1;
        }
        if (s2snd != -1 && s1rcv == -1) {
            errno = EINVAL;
            return -1;
        }
    }

    /*  Two-directional device. */
    if (device->required_checks & NN_CHECK_ALLOW_BIDIRECTIONAL) {
        if (s1rcv != -1 && s1snd != -1 && s2rcv != -1 && s2snd != -1)
            return nn_device_twoway (device, s1, s1rcv, s1snd,
                s2, s2rcv, s2snd);
    }

    if (device->required_checks & NN_CHECK_ALLOW_UNIDIRECTIONAL) {
        /*  Single-directional device passing messages from s1 to s2. */
        if (s1rcv != -1 && s1snd == -1 && s2rcv == -1 && s2snd != -1)
            return nn_device_oneway (device,s1, s1rcv, s2, s2snd);

        /*  Single-directional device passing messages from s2 to s1. */
        if (s1rcv == -1 && s1snd != -1 && s2rcv != -1 && s2snd == -1)
            return nn_device_oneway (device,s2, s2rcv, s1, s1snd);
    }

    /*  This should never happen. */
    nn_assert (0);
}
Beispiel #11
0
int main ()
{
    int rc;
    int sb;
    char buf [3];
    struct nn_thread thread;
    struct nn_pollfd pfd [2];

    /* Test nn_poll() function. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);
    test_send (sc, "ABC");
    nn_sleep (100);
    pfd [0].fd = sb;
    pfd [0].events = NN_POLLIN | NN_POLLOUT;
    pfd [1].fd = sc;
    pfd [1].events = NN_POLLIN | NN_POLLOUT;
    rc = nn_poll (pfd, 2, -1);
    errno_assert (rc >= 0);
    nn_assert (rc == 2);
    nn_assert (pfd [0].revents == (NN_POLLIN | NN_POLLOUT));
    nn_assert (pfd [1].revents == NN_POLLOUT);
    test_close (sc);
    test_close (sb);

    /*  Create a simple topology. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);

    /*  Check the initial state of the socket. */
    rc = getevents (sb, NN_IN | NN_OUT, 1000);
    nn_assert (rc == NN_OUT);

    /*  Poll for IN when there's no message available. The call should
        time out. */
    rc = getevents (sb, NN_IN, 10);
    nn_assert (rc == 0);

    /*  Send a message and start polling. This time IN event should be
        signaled. */
    test_send (sc, "ABC");
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);

    /*  Receive the message and make sure that IN is no longer signaled. */
    test_recv (sb, "ABC");
    rc = getevents (sb, NN_IN, 10);
    nn_assert (rc == 0);

    /*  Check signalling from a different thread. */
    nn_thread_init (&thread, routine1, NULL);
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);
    test_recv (sb, "ABC");
    nn_thread_term (&thread);

    /*  Check terminating the library from a different thread. */
    nn_thread_init (&thread, routine2, NULL);
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);
    rc = nn_recv (sb, buf, sizeof (buf), 0);
    nn_assert (rc < 0 && nn_errno () == ETERM);
    nn_thread_term (&thread);

    /*  Clean up. */
    test_close (sc);
    test_close (sb);

    return 0;
}
Beispiel #12
0
int ss_nn_queue_create(json_object* items, nn_queue_t* nn_queue) {
    // int rv;
    int so_value;
    char* value = NULL;
    
    memset(nn_queue, 0, sizeof(nn_queue_t));
    
    value = ss_json_string_get(items, "nm_url");
    if (value == NULL) {
        fprintf(stderr, "nm_url is null\n");
        goto error_out;
    }
    strlcpy(nn_queue->url, value, sizeof(nn_queue->url));
    je_free(value);
    
    value = ss_json_string_get(items, "nm_type");
    if (value == NULL) {
        fprintf(stderr, "nm_type is null\n");
        goto error_out;
    }
    if      (!strcasecmp(value, "BUS"))        nn_queue->type = NN_BUS;
    else if (!strcasecmp(value, "PAIR"))       nn_queue->type = NN_PAIR;
    else if (!strcasecmp(value, "PUSH"))       nn_queue->type = NN_PUSH;
    else if (!strcasecmp(value, "PULL"))       nn_queue->type = NN_PULL;
    else if (!strcasecmp(value, "PUB"))        nn_queue->type = NN_PUB;
    else if (!strcasecmp(value, "SUB"))        nn_queue->type = NN_SUB;
    else if (!strcasecmp(value, "REQ"))        nn_queue->type = NN_REQ;
    else if (!strcasecmp(value, "REP"))        nn_queue->type = NN_REP;
    else if (!strcasecmp(value, "SURVEYOR"))   nn_queue->type = NN_SURVEYOR;
    else if (!strcasecmp(value, "RESPONDENT")) nn_queue->type = NN_RESPONDENT;
    else {
        fprintf(stderr, "unknown nm_type %s\n", value);
        goto error_out;
    }
    je_free(value);
    
    value = ss_json_string_get(items, "nm_format");
    if      (!strcasecmp(value, "metadata")) nn_queue->format = NN_FORMAT_METADATA;
    else if (!strcasecmp(value, "packet"))   nn_queue->format = NN_FORMAT_PACKET;
    else {
        fprintf(stderr, "unknown nm_format %s\n", value);
        goto error_out;
    }
    je_free(value);
    
    nn_queue->conn = nn_socket(AF_SP, nn_queue->type);
    if (nn_queue->conn < 0) {
        fprintf(stderr, "could not allocate nm queue socket: %s\n", nn_strerror(nn_errno()));
        goto error_out;
    }
    so_value = 0;
    /*
    rv = nn_setsockopt(nn_queue->conn, NN_SOL_SOCKET, NN_IPV4ONLY, &so_value, sizeof(so_value));
    if (rv != 0) {
        fprintf(stderr, "could not enable nm ipv6 support: %s\n", nn_strerror(nn_errno()));
        goto error_out;
    }
    */
    nn_queue->remote_id = nn_connect(nn_queue->conn, nn_queue->url);
    if (nn_queue->remote_id < 0) {
        fprintf(stderr, "could not connect nm queue socket: %s\n", nn_strerror(nn_errno()));
        goto error_out;
    }
    
    fprintf(stderr, "created nm_queue type %s url %s\n", ss_nn_queue_type_dump(nn_queue->type), nn_queue->url);
    return 0;
    
    error_out:
    if (nn_queue) ss_nn_queue_destroy(nn_queue);
    if (value) je_free(value);
    return -1;
}
Beispiel #13
0
int main ()
{
    int rc;
    int sb;
    int sc;
    int i;
    char buf [3];
    int opt;
    size_t sz;

    /*  Try closing bound but unconnected socket. */
#if 0
    sb = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sb >= 0);
    rc = nn_bind (sb, SOCKET_ADDRESS);
    errno_assert (rc > 0);
    rc = nn_close (sb);
    errno_assert (rc == 0);
#endif

    /*  Try closing a TCP socket while it not connected. At the same time
        test specifying the local address for connection. */
    sc = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sc != -1);
    rc = nn_connect (sc, "tcp://127.0.0.1;127.0.0.1:5555");
    errno_assert (rc >= 0);
    rc = nn_close (sc);
    errno_assert (rc == 0);

    /*  Open the socket anew. */
    sc = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sc != -1);

    /*  Check NODELAY socket option. */
    sz = sizeof (opt);
    rc = nn_getsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, &sz);
    errno_assert (rc == 0);
    nn_assert (sz == sizeof (opt));
    nn_assert (opt == 0);
    opt = 2;
    rc = nn_setsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
    nn_assert (rc < 0 && nn_errno () == EINVAL);
    opt = 1;
    rc = nn_setsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
    errno_assert (rc == 0);
    sz = sizeof (opt);
    rc = nn_getsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, &sz);
    errno_assert (rc == 0);
    nn_assert (sz == sizeof (opt));
    nn_assert (opt == 1);

    /*  Try using invalid address strings. */
    rc = nn_connect (sc, "tcp://*:");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "tcp://*:1000000");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "tcp://*:some_port");
    nn_assert (rc < 0);
    rc = nn_connect (sc, "tcp://eth10000;127.0.0.1:5555");
    nn_assert (rc < 0);    
    errno_assert (nn_errno () == ENODEV);
    rc = nn_bind (sc, "tcp://127.0.0.1:");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_bind (sc, "tcp://127.0.0.1:1000000");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_bind (sc, "tcp://eth10000:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == ENODEV);

    /*  Connect correctly. Do so before binding the peer socket. */
    rc = nn_connect (sc, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    /*  Leave enough time for at least on re-connect attempt. */
    nn_sleep (200);

    sb = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sb != -1);
    rc = nn_bind (sb, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    /*  Ping-pong test. */
    for (i = 0; i != 100; ++i) {

        rc = nn_send (sc, "ABC", 3, 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 3);

        rc = nn_recv (sb, buf, sizeof (buf), 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 3);

        rc = nn_send (sb, "DEF", 3, 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 3);

        rc = nn_recv (sc, buf, sizeof (buf), 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 3);
    }

    /*  Batch transfer test. */
    for (i = 0; i != 100; ++i) {
        rc = nn_send (sc, "0123456789012345678901234567890123456789", 40, 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 40);
    }
    for (i = 0; i != 100; ++i) {
        rc = nn_recv (sb, buf, sizeof (buf), 0);
        errno_assert (rc >= 0);
        nn_assert (rc == 40);
    }

    rc = nn_close (sc);
    errno_assert (rc == 0);
    rc = nn_close (sb);
    errno_assert (rc == 0);

    return 0;
}
int outprocessIncomingMessageThread(void *param)
{
	/*Codes_SRS_OUTPROCESS_MODULE_17_037: [ This function shall receive the module handle data as the thread parameter. ]*/
	OUTPROCESS_HANDLE_DATA * handleData = (OUTPROCESS_HANDLE_DATA*)param;
	if (handleData == NULL)
	{
		LogError("outprocess thread: parameter is NULL");
	}
	else
	{
		int should_continue = 1;

		while (should_continue)
		{
			/*Codes_SRS_OUTPROCESS_MODULE_17_036: [ This function shall ensure thread safety on execution. ]*/
			if (Lock(handleData->handle_lock) != LOCK_OK)
			{
				LogError("unable to Lock handle data");
				should_continue = 0;
				break;
			}
			int nn_fd = handleData->message_socket;
			if (Unlock(handleData->handle_lock) != LOCK_OK)
			{
				should_continue = 0;
				break;
			}

			/*Codes_SRS_OUTPROCESS_MODULE_17_036: [ This function shall ensure thread safety on execution. ]*/
			if (Lock(handleData->message_receive_thread.thread_lock) != LOCK_OK)
			{
				LogError("unable to Lock");
				should_continue = 0;
				break;
			}
			if (handleData->message_receive_thread.thread_flag == THREAD_FLAG_STOP)
			{
				should_continue = 0;
				(void)Unlock(handleData->message_receive_thread.thread_lock);
				break;
			}
			if (Unlock(handleData->message_receive_thread.thread_lock) != LOCK_OK)
			{
				should_continue = 0;
				break;
			}

			int nbytes;
			unsigned char *buf = NULL;
			errno = 0;
			/*Codes_SRS_OUTPROCESS_MODULE_17_038: [ This function shall read from the message channel for gateway messages from the module host. ]*/
			nbytes = nn_recv(nn_fd, (void *)&buf, NN_MSG, 0);
			if (nbytes < 0)
			{
				int receive_error = nn_errno();
				if (receive_error != ETIMEDOUT && receive_error != EINTR)
					should_continue = 0;
			}
			else
			{
				/*Codes_SRS_OUTPROCESS_MODULE_17_039: [ Upon successful receiving a gateway message, this function shall deserialize the message. ]*/
				const unsigned char*buf_bytes = (const unsigned char*)buf;
				MESSAGE_HANDLE msg = Message_CreateFromByteArray(buf_bytes, nbytes);
				if (msg != NULL)
				{
					/*Codes_SRS_OUTPROCESS_MODULE_17_040: [ This function shall publish any successfully created gateway message to the broker. ]*/
					Broker_Publish(handleData->broker, (MODULE_HANDLE)handleData, msg);
					Message_Destroy(msg);
				}
				nn_freemsg(buf);
			}
			ThreadAPI_Sleep(1);
		}
	}
	return 0;
}
Beispiel #15
0
int main (int argc, const char *argv[])
{
    int rc;
    int sb;
    int sc;
    int sb2;
    int opt;
    size_t sz;
    int i;
    char any_address[128];

    test_addr_from (socket_address, "ws", "127.0.0.1",
            get_test_port (argc, argv));

    test_addr_from (any_address, "ws", "*",
            get_test_port (argc, argv));

    /*  Try closing bound but unconnected socket. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, any_address);
    test_close (sb);

    /*  Try closing a TCP socket while it not connected. At the same time
        test specifying the local address for the connection. */
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, socket_address);
    test_close (sc);

    /*  Open the socket anew. */
    sc = test_socket (AF_SP, NN_PAIR);

    /*  Check socket options. */
    sz = sizeof (opt);
    rc = nn_getsockopt (sc, NN_WS, NN_WS_MSG_TYPE, &opt, &sz);
    errno_assert (rc == 0);
    nn_assert (sz == sizeof (opt));
    nn_assert (opt == NN_WS_MSG_TYPE_BINARY);

    /*  Default port 80 should be assumed if not explicitly declared. */
    rc = nn_connect (sc, "ws://127.0.0.1");
    errno_assert (rc >= 0);

    /*  Try using invalid address strings. */
    rc = nn_connect (sc, "ws://*:");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://*:1000000");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://*:some_port");
    nn_assert (rc < 0);
    rc = nn_connect (sc, "ws://eth10000;127.0.0.1:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == ENODEV);

    rc = nn_bind (sc, "ws://127.0.0.1:");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_bind (sc, "ws://127.0.0.1:1000000");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_bind (sc, "ws://eth10000:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == ENODEV);

    rc = nn_connect (sc, "ws://:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://-hostname:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://abc.123.---.#:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://[::1]:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://abc.123.:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://abc...123:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    rc = nn_connect (sc, "ws://.123:5555");
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);

    test_close (sc);

    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, socket_address);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, socket_address);

    /*  Ping-pong test. */
    for (i = 0; i != 100; ++i) {

        test_send (sc, "ABC");
        test_recv (sb, "ABC");

        test_send (sb, "DEF");
        test_recv (sc, "DEF");
    }

    /*  Batch transfer test. */
    for (i = 0; i != 100; ++i) {
        test_send (sc, "0123456789012345678901234567890123456789");
    }
    for (i = 0; i != 100; ++i) {
        test_recv (sb, "0123456789012345678901234567890123456789");
    }

    test_close (sc);
    test_close (sb);

    /*  Test two sockets binding to the same address. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, socket_address);
    sb2 = test_socket (AF_SP, NN_PAIR);

    rc = nn_bind (sb2, socket_address);
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EADDRINUSE);
    test_close(sb);
    test_close(sb2);

    /*  Test that NN_RCVMAXSIZE can be -1, but not lower */
    sb = test_socket (AF_SP, NN_PAIR);
    opt = -1;
    rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
    nn_assert (rc >= 0);
    opt = -2;
    rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
    nn_assert (rc < 0);
    errno_assert (nn_errno () == EINVAL);
    test_close (sb);

    /*  Test NN_RCVMAXSIZE limit */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, socket_address);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, socket_address);
    opt = 1000;
    test_setsockopt (sc, NN_SOL_SOCKET, NN_SNDTIMEO, &opt, sizeof (opt));
    nn_assert (opt == 1000);
    opt = 1000;
    test_setsockopt (sb, NN_SOL_SOCKET, NN_RCVTIMEO, &opt, sizeof (opt));
    nn_assert (opt == 1000);
    opt = 4;
    test_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
    test_send (sc, "ABC");
    test_recv (sb, "ABC");
    test_send (sc, "ABCD");
    test_recv (sb, "ABCD");
    test_send (sc, "ABCDE");
    test_drop (sb, ETIMEDOUT);

    /*  Increase the size limit, reconnect, then try sending again. The reason a
        reconnect is necessary is because after a protocol violation, the
        connecting socket will not continue automatic reconnection attempts. */
    opt = 5;
    test_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
    test_connect (sc, socket_address);
    test_send (sc, "ABCDE");
    test_recv (sb, "ABCDE");
    test_close (sb);
    test_close (sc);

    test_text ();

    /*  Test closing a socket that is waiting to connect. */
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, socket_address);
    nn_sleep (100);
    test_close (sc);

    return 0;
}
Beispiel #16
0
bool pnet_internal_get_socketfd(pnet_socket *socket)
{
    size_t sd_size = sizeof(int);

    if (unlikely(nn_getsockopt(socket->socket_fd, NN_SOL_SOCKET, NN_RCVFD, &socket->recv_fd, &sd_size))) {
        plog_error("pnet_server_start() не удалось получить NN_RCVFD | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    if (unlikely(nn_getsockopt(socket->socket_fd, NN_SOL_SOCKET, NN_SNDFD, &socket->send_fd, &sd_size))) {
        plog_error("pnet_server_start() не удалось получить NN_SNDFD | %s (%d)", nn_strerror(nn_errno()), nn_errno());
        return false;
    }

    return true;
}
Beispiel #17
0
int main ()
{
    int rc;
    int sb;
    int sc;
    int s1, s2;
    int i;
    char buf [256];
    int val;
    struct nn_msghdr hdr;
    struct nn_iovec iovec;
    unsigned char body [3];
    void *control;
    struct nn_cmsghdr *cmsg;
    unsigned char *data;

    /*  Create a simple topology. */
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);

    /*  Try a duplicate bind. It should fail. */
    rc = nn_bind (sc, SOCKET_ADDRESS);
    nn_assert (rc < 0 && errno == EADDRINUSE);

    /*  Ping-pong test. */
    for (i = 0; i != 100; ++i) {

        test_send (sc, "ABC");
        test_recv (sb, "ABC");
        test_send (sb, "DEFG");
        test_recv (sc, "DEFG");
    }

    /*  Batch transfer test. */
    for (i = 0; i != 100; ++i) {
        test_send (sc, "XYZ");
    }
    for (i = 0; i != 100; ++i) {
        test_recv (sb, "XYZ");
    }

    test_close (sc);
    test_close (sb);

    /*  Test whether queue limits are observed. */
    sb = test_socket (AF_SP, NN_PAIR);
    val = 200;
    rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVBUF, &val, sizeof (val));
    errno_assert (rc == 0);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);

    val = 200;
    rc = nn_setsockopt (sc, NN_SOL_SOCKET, NN_SNDTIMEO, &val, sizeof (val));
    errno_assert (rc == 0);
    i = 0;
    while (1) {
        rc = nn_send (sc, "0123456789", 10, 0);
        if (rc < 0 && nn_errno () == EAGAIN)
            break;
        errno_assert (rc >= 0);
        nn_assert (rc == 10);
        ++i;
    }
    nn_assert (i == 20);
    test_recv (sb, "0123456789");
    test_send (sc, "0123456789");
    rc = nn_send (sc, "0123456789", 10, 0);
    nn_assert (rc < 0 && nn_errno () == EAGAIN);
    for (i = 0; i != 20; ++i) {
        test_recv (sb, "0123456789");
    }

    /*  Make sure that even a message that doesn't fit into the buffers
        gets across. */
    for (i = 0; i != sizeof (buf); ++i)
        buf [i] = 'A';
    rc = nn_send (sc, buf, 256, 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 256);
    rc = nn_recv (sb, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 256);

    test_close (sc);
    test_close (sb);

#if 0
    /*  Test whether connection rejection is handled decently. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    s1 = test_socket (AF_SP, NN_PAIR);
    test_connect (s1, SOCKET_ADDRESS);
    s2 = test_socket (AF_SP, NN_PAIR);
    test_connect (s2, SOCKET_ADDRESS);
    nn_sleep (100);
    test_close (s2);
    test_close (s1);
    test_close (sb);
#endif

    /* Check whether SP message header is transferred correctly. */
    sb = test_socket (AF_SP_RAW, NN_REP);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_REQ);
    test_connect (sc, SOCKET_ADDRESS);

    test_send (sc, "ABC");

    iovec.iov_base = body;
    iovec.iov_len = sizeof (body);
    hdr.msg_iov = &iovec;
    hdr.msg_iovlen = 1;
    hdr.msg_control = &control;
    hdr.msg_controllen = NN_MSG;
    rc = nn_recvmsg (sb, &hdr, 0);
    errno_assert (rc == 3);

    cmsg = NN_CMSG_FIRSTHDR (&hdr);
    while (1) {
        nn_assert (cmsg);
        if (cmsg->cmsg_level == PROTO_SP && cmsg->cmsg_type == SP_HDR)
            break;
        cmsg = NN_CMSG_NXTHDR (&hdr, cmsg);
    }
    nn_assert (cmsg->cmsg_len == NN_CMSG_SPACE (8));
    data = NN_CMSG_DATA (cmsg);
    nn_assert (!(data[0] & 0x80));
    nn_assert (data[4] & 0x80);

    nn_freemsg (control);

    test_close (sc);
    test_close (sb);

    /* Test binding a new socket after originally bound socket shuts down. */
    sb = test_socket (AF_SP, NN_BUS);
    test_bind (sb, SOCKET_ADDRESS);

    sc = test_socket (AF_SP, NN_BUS);
    test_connect (sc, SOCKET_ADDRESS);

    s1 = test_socket (AF_SP, NN_BUS);
    test_connect (s1, SOCKET_ADDRESS);

    /* Close bound socket, leaving connected sockets connect. */
    test_close (sb);

    nn_sleep (100);

    /* Rebind a new socket to the address to which our connected sockets are listening. */
    s2 = test_socket (AF_SP, NN_BUS);
    test_bind (s2, SOCKET_ADDRESS);

    /*  Ping-pong test. */
    for (i = 0; i != 100; ++i) {

        test_send (sc, "ABC");
        test_send (s1, "QRS");
        test_recv (s2, "ABC");
        test_recv (s2, "QRS");
        test_send (s2, "DEFG");
        test_recv (sc, "DEFG");
        test_recv (s1, "DEFG");
    }

    /*  Batch transfer test. */
    for (i = 0; i != 100; ++i) {
        test_send (sc, "XYZ");
    }
    for (i = 0; i != 100; ++i) {
        test_recv (s2, "XYZ");
    }
    for (i = 0; i != 100; ++i) {
        test_send (s1, "MNO");
    }
    for (i = 0; i != 100; ++i) {
        test_recv (s2, "MNO");
    }

    test_close (s1);
    test_close (sc);
    test_close (s2);

    return 0;
}
static int outprocessCreate(void *param)
{
	int thread_return;
	OUTPROCESS_HANDLE_DATA * handleData = (OUTPROCESS_HANDLE_DATA*)param;
	if (handleData == NULL)
	{
		LogError("async_create_receive_control thread: parameter is NULL");
		thread_return = -1;
	}
	else
	{
		/*Codes_SRS_OUTPROCESS_MODULE_17_056: [ This thread shall ensure thread safety on the module data. ]*/
		if (Lock(handleData->handle_lock) != LOCK_OK)
		{
			LogError("Unable to acquire handle data lock");
			thread_return = -1;
		}
		else
		{
			int control_fd = handleData->control_socket;
			int remote_message_wait = (int)handleData->remote_message_wait;
			(void)Unlock(handleData->handle_lock);
			int should_continue = 1;

			do {
				int32_t creationMessageSize = 0;

				void * creationMessage = construct_create_message(handleData, &creationMessageSize);
				if (creationMessage == NULL)
				{
					/*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/
					LogError("Unable to create create control message");
					should_continue = 0;
					thread_return = -1;
				}
				else
				{
					/*Codes_SRS_OUTPROCESS_MODULE_17_013: [ This function shall send the Create Message on the control channel. ]*/
					size_t default_wait_size = sizeof(remote_message_wait);
					if (nn_setsockopt(control_fd, NN_SOL_SOCKET, NN_RCVTIMEO, &remote_message_wait, default_wait_size) < 0)
					{
						LogError("Unable to set a receive timeout.");
						nn_freemsg(creationMessage); /* won't get to send that message we just created */
						should_continue = 0;
						thread_return = -1;
					}
					else
					{
						int sendBytes = nn_send(control_fd, &creationMessage, NN_MSG, NN_DONTWAIT);
						if (sendBytes != creationMessageSize)
						{
							int send_err = nn_errno();
							nn_freemsg(creationMessage);
							if (send_err != EAGAIN)
							{
								/*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/
								LogError("unable to send create message [%p]", creationMessage);
								should_continue = 0;
								thread_return = -1;
							}
							else
							{
								ThreadAPI_Sleep((unsigned int)remote_message_wait);
							}
						}
						else
						{
							unsigned char *buf = NULL;
							/* This receive should time out if no one sends a response. */
							int recvBytes = nn_recv(control_fd, (void *)&buf, NN_MSG, 0);
							if (recvBytes < 0)
							{
								int recv_error = nn_errno();
								if (recv_error != EAGAIN && recv_error != ETIMEDOUT && recv_error != EINTR)
								{
									LogError("unexpected error on control channel receive: %d", recv_error);
									should_continue = 0;
									thread_return = -1;
								}
							}
							else
							{
								should_continue = 0; /* Only continue until we receive a message */
								CONTROL_MESSAGE * msg = ControlMessage_CreateFromByteArray((const unsigned char*)buf, recvBytes);
								nn_freemsg(buf);
								if (msg == NULL)
								{
									thread_return = -1;
								}
								else
								{
									if (msg->type != CONTROL_MESSAGE_TYPE_MODULE_REPLY)
									{
										thread_return = -1;
									}
									else
									{
										CONTROL_MESSAGE_MODULE_REPLY * resp_msg = (CONTROL_MESSAGE_MODULE_REPLY*)msg;
										if (resp_msg->status != 0)
										{
											thread_return = -1;
										}
										else
										{
											/*Codes_SRS_OUTPROCESS_MODULE_17_015: [ This function shall expect a successful result from the Create Response to consider the module creation a success. ]*/
											// complete success!
											thread_return = 1;
										}
									}
									ControlMessage_Destroy(msg);
								}
							}
						}
					} 
				}
			} while (should_continue == 1);
		}
	}
	return thread_return;
}