예제 #1
0
파일: ws.c 프로젝트: zakharov/nanomsg
int nn_ws_send (int s, const void *msg, size_t len, uint8_t msg_type, int flags)
{
    int rc;
    struct nn_iovec iov;
    struct nn_msghdr hdr;
    struct nn_cmsghdr *cmsg;
    size_t cmsgsz;

    iov.iov_base = (void*) msg;
    iov.iov_len = len;
    
    cmsgsz = NN_CMSG_SPACE (sizeof (msg_type));
    cmsg = nn_allocmsg (cmsgsz, 0);
    if (cmsg == NULL)
        return -1;

    cmsg->cmsg_level = NN_WS;
    cmsg->cmsg_type = NN_WS_HDR_OPCODE;
    cmsg->cmsg_len = NN_CMSG_LEN (sizeof (msg_type));
    memcpy (NN_CMSG_DATA (cmsg), &msg_type, sizeof (msg_type));

    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;
    hdr.msg_control = &cmsg;
    hdr.msg_controllen = NN_MSG;

    rc = nn_sendmsg (s, &hdr, flags);

    return rc;
}
예제 #2
0
파일: tcpmux.c 프로젝트: TTimo/nanomsg
int tcpmux_accept (int s)
{
    int rc;
    ssize_t ssz;
    char c;
    struct iovec iov;
    struct msghdr hdr;
    unsigned char buf [256];
    struct cmsghdr *cmsg;

    iov.iov_base = &c;
    iov.iov_len = 1;
    memset (&hdr, 0, sizeof (hdr));
    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;
    hdr.msg_control = buf;
    hdr.msg_controllen = sizeof (buf);

    ssz = recvmsg (s, &hdr, 0);
    if (ssz < 0)
        return -1;
    nn_assert (ssz == 1);

    cmsg = CMSG_FIRSTHDR (&hdr);
    while (1) {
        nn_assert (cmsg);
        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SP_HDR)
            break;
        cmsg = CMSG_NXTHDR (&hdr, cmsg);
    }
    nn_assert (cmsg->cmsg_len == CMSG_LEN (sizeof (int)));
    return *((int*) NN_CMSG_DATA (cmsg));
}
예제 #3
0
파일: ws.c 프로젝트: zakharov/nanomsg
int nn_ws_recv (int s, void *msg, size_t len, uint8_t *msg_type, int flags)
{
    struct nn_iovec iov;
    struct nn_msghdr hdr;
    struct nn_cmsghdr *cmsg;
    void *cmsg_buf;
    int rc;

    iov.iov_base = msg;
    iov.iov_len = len;

    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;
    hdr.msg_control = &cmsg_buf;
    hdr.msg_controllen = NN_MSG;

    rc = nn_recvmsg (s, &hdr, flags);
    if (rc < 0)
        return rc;

    /* Find WebSocket opcode ancillary property. */
    cmsg = NN_CMSG_FIRSTHDR (&hdr);
    while (cmsg) {
        if (cmsg->cmsg_level == NN_WS && cmsg->cmsg_type == NN_WS_HDR_OPCODE) {
            *msg_type = *(uint8_t *) NN_CMSG_DATA (cmsg);
            break;
        }
        cmsg = NN_CMSG_NXTHDR (&hdr, cmsg);
    }

    /*  WebSocket transport should always report this header. */
    nn_assert (cmsg);

    /*  WebSocket transport should always reassemble fragmented messages. */
    nn_assert (*msg_type & NN_SWS_FRAME_BITMASK_FIN);

    /*  Return only the message type (opcode). */
    if (*msg_type == (NN_WS_MSG_TYPE_GONE | NN_SWS_FRAME_BITMASK_FIN))
        *msg_type = NN_WS_MSG_TYPE_GONE;
    else
        *msg_type &= NN_SWS_FRAME_BITMASK_OPCODE;

    nn_freemsg (cmsg_buf);

    return rc;
}
예제 #4
0
파일: global.c 프로젝트: TTimo/nanomsg
int nn_sendmsg (int s, const struct nn_msghdr *msghdr, int flags)
{
    int rc;
    size_t sz;
    size_t spsz;
    int i;
    struct nn_iovec *iov;
    struct nn_msg msg;
    void *chunk;
    int nnmsg;
    struct nn_cmsghdr *cmsg;

    NN_BASIC_CHECKS;

    if (nn_slow (!msghdr)) {
        errno = EINVAL;
        return -1;
    }

    if (nn_slow (msghdr->msg_iovlen < 0)) {
        errno = EMSGSIZE;
        return -1;
    }

    if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) {
        chunk = *(void**) msghdr->msg_iov [0].iov_base;
        if (nn_slow (chunk == NULL)) {
            errno = EFAULT;
            return -1;
        }
        sz = nn_chunk_size (chunk);
        nn_msg_init_chunk (&msg, chunk);
        nnmsg = 1;
    }
    else {

        /*  Compute the total size of the message. */
        sz = 0;
        for (i = 0; i != msghdr->msg_iovlen; ++i) {
            iov = &msghdr->msg_iov [i];
            if (nn_slow (iov->iov_len == NN_MSG)) {
               errno = EINVAL;
               return -1;
            }
            if (nn_slow (!iov->iov_base && iov->iov_len)) {
                errno = EFAULT;
                return -1;
            }
            if (nn_slow (sz + iov->iov_len < sz)) {
                errno = EINVAL;
                return -1;
            }
            sz += iov->iov_len;
        }

        /*  Create a message object from the supplied scatter array. */
        nn_msg_init (&msg, sz);
        sz = 0;
        for (i = 0; i != msghdr->msg_iovlen; ++i) {
            iov = &msghdr->msg_iov [i];
            memcpy (((uint8_t*) nn_chunkref_data (&msg.body)) + sz,
                iov->iov_base, iov->iov_len);
            sz += iov->iov_len;
        }

        nnmsg = 0;
    }

    /*  Add ancillary data to the message. */
    if (msghdr->msg_control) {

        /*  Copy all headers. */
        /*  TODO: SP_HDR should not be copied here! */
        if (msghdr->msg_controllen == NN_MSG) {
            chunk = *((void**) msghdr->msg_control);
            nn_chunkref_term (&msg.hdrs);
            nn_chunkref_init_chunk (&msg.hdrs, chunk);
        }
        else {
            nn_chunkref_term (&msg.hdrs);
            nn_chunkref_init (&msg.hdrs, msghdr->msg_controllen);
            memcpy (nn_chunkref_data (&msg.hdrs),
                msghdr->msg_control, msghdr->msg_controllen);
        }

        /* Search for SP_HDR property. */
        cmsg = NN_CMSG_FIRSTHDR (msghdr);
        while (cmsg) {
            if (cmsg->cmsg_level == PROTO_SP && cmsg->cmsg_type == SP_HDR) {
                /*  Copy body of SP_HDR property into 'sphdr'. */
                nn_chunkref_term (&msg.sphdr);
                spsz = cmsg->cmsg_len - NN_CMSG_SPACE (0);
                nn_chunkref_init (&msg.sphdr, spsz);
                memcpy (nn_chunkref_data (&msg.sphdr),
                    NN_CMSG_DATA (cmsg), spsz);
                break;
            }
            cmsg = NN_CMSG_NXTHDR (msghdr, cmsg);
        }
    }

    /*  Send it further down the stack. */
    rc = nn_sock_send (self.socks [s], &msg, flags);
    if (nn_slow (rc < 0)) {

        /*  If we are dealing with user-supplied buffer, detach it from
            the message object. */
        if (nnmsg)
            nn_chunkref_init (&msg.body, 0);

        nn_msg_term (&msg);
        errno = -rc;
        return -1;
    }

    /*  Adjust the statistics. */
    nn_sock_stat_increment (self.socks [s], NN_STAT_MESSAGES_SENT, 1);
    nn_sock_stat_increment (self.socks [s], NN_STAT_BYTES_SENT, sz);

    return (int) sz;
}
예제 #5
0
파일: cmsg.c 프로젝트: Abioy/nanomsg
int main ()
{
    int rc;
    int rep;
    int req;
    struct nn_msghdr hdr;
    struct nn_iovec iovec;
    unsigned char body [3];
    unsigned char ctrl [256];
    struct nn_cmsghdr *cmsg;
    unsigned char *data;
    void *buf;
    
    rep = test_socket (AF_SP_RAW, NN_REP);
    test_bind (rep, SOCKET_ADDRESS);
    req = test_socket (AF_SP, NN_REQ);
    test_connect (req, SOCKET_ADDRESS);

    /* Test ancillary data in static buffer. */

    test_send (req, "ABC");

    iovec.iov_base = body;
    iovec.iov_len = sizeof (body);
    hdr.msg_iov = &iovec;
    hdr.msg_iovlen = 1;
    hdr.msg_control = ctrl;
    hdr.msg_controllen = sizeof (ctrl);
    rc = nn_recvmsg (rep, &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);

    rc = nn_sendmsg (rep, &hdr, 0);
    nn_assert (rc == 3);
    test_recv (req, "ABC");

    /* Test ancillary data in dynamically allocated buffer (NN_MSG). */

    test_send (req, "ABC");

    iovec.iov_base = body;
    iovec.iov_len = sizeof (body);
    hdr.msg_iov = &iovec;
    hdr.msg_iovlen = 1;
    hdr.msg_control = &buf;
    hdr.msg_controllen = NN_MSG;
    rc = nn_recvmsg (rep, &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);

    rc = nn_sendmsg (rep, &hdr, 0);
    nn_assert (rc == 3);
    test_recv (req, "ABC");

    test_close (req);
    test_close (rep);

    return 0;
}
예제 #6
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;
}