Beispiel #1
0
int conn_udp_sendto(const void *data, size_t len, const void *src, size_t src_len,
                    const void *dst, size_t dst_len, int family, uint16_t sport,
                    uint16_t dport)
{
    int res;
    _send_cmd_t send_cmd;

    if (!send_registered) {
        if (evproc_regCallback(EVENT_TYPE_CONN_SEND, _output_callback) != E_SUCCESS) {
            return -EIO;
        }
        else {
            send_registered = true;
        }
    }
    mutex_init(&send_cmd.mutex);
    if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
        (len > UINT16_MAX)) {
        return -EMSGSIZE;
    }
    if ((dst_len > sizeof(ipv6_addr_t)) || (family != AF_INET6)) {
        return -EAFNOSUPPORT;
    }
    mutex_lock(&send_cmd.mutex);
    send_cmd.data = data;
    send_cmd.data_len = (uint16_t)len;
    if ((res = _reg_and_bind(&send_cmd.sock, NULL, NULL, sport)) < 0) {
        mutex_unlock(&send_cmd.mutex);
        return res;
    }
    udp_socket_connect(&send_cmd.sock, (uip_ipaddr_t *)dst, dport); /* can't fail at this point */
    /* change to emb6 thread context */
    if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_CONN_SEND, &send_cmd) != E_SUCCESS) {
        udp_socket_close(&send_cmd.sock);
        mutex_unlock(&send_cmd.mutex);
        return -EIO;
    }
    /* block thread until data was send */
    mutex_lock(&send_cmd.mutex);
    udp_socket_close(&send_cmd.sock);
    mutex_unlock(&send_cmd.mutex);

    return send_cmd.res;
}
Beispiel #2
0
static int _reg_and_bind(struct udp_socket *c, void *ptr,
                         udp_socket_input_callback_t cb, uint16_t port)
{
    if (udp_socket_register(c, ptr, cb) < 0) {
        return -EMFILE;
    }
    if (udp_socket_bind(c, port) < 0) {
        udp_socket_close(c);
        return -EALREADY;
    }
    return 0;
}
Beispiel #3
0
void sock_udp_close(sock_udp_t *sock)
{
    assert(sock != NULL);
    if (sock->sock.input_callback != NULL) {
        while (atomic_fetch_sub(&sock->receivers, 1) > 0) {
            msg_t msg = { .type = _MSG_TYPE_CLOSE };
            mbox_put(&sock->mbox, &msg);
        }
        mutex_lock(&sock->mutex);
        udp_socket_close(&sock->sock);
        sock->sock.input_callback = NULL;
        mutex_unlock(&sock->mutex);
    }
}
Beispiel #4
0
void conn_udp_close(conn_udp_t *conn)
{
    if (conn->sock.input_callback != NULL) {
        mutex_lock(&conn->mutex);
        if (conn->waiting_thread != KERNEL_PID_UNDEF) {
            msg_t msg;
            msg.type = _MSG_TYPE_CLOSE;
            msg.content.ptr = conn;
            mutex_unlock(&conn->mutex);
            msg_send(&msg, conn->waiting_thread);
            mutex_lock(&conn->mutex);
        }
        udp_socket_close(&conn->sock);
        conn->sock.input_callback = NULL;
        mutex_unlock(&conn->mutex);
    }
}
Beispiel #5
0
static int _reg(struct udp_socket *c, void *ptr, udp_socket_input_callback_t cb,
                const sock_udp_ep_t *local, const sock_udp_ep_t *remote)
{
    if (((local != NULL) && (local->family != AF_INET6)) ||
        ((remote != NULL) && (remote->family != AF_INET6))) {
        return -EAFNOSUPPORT;
    }
    if (udp_socket_register(c, ptr, cb) < 0) {
        return -ENOMEM;
    }
    if (local != NULL) {
        if (udp_socket_bind(c, local->port) < 0) {
            udp_socket_close(c);
            return -EADDRINUSE;
        }
    }
    if (remote != NULL) {
        /* check of return value not necessary, since neither c nor
         * c->udp_conn is NULL (only error case) at this point */
        udp_socket_connect(c, (uip_ipaddr_t *)&remote->addr, remote->port);
    }
    return 0;
}
Beispiel #6
0
int sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
                  const sock_udp_ep_t *remote)
{
    struct udp_socket tmp;
    _send_cmd_t send_cmd = { .block = MUTEX_INIT,
                             .remote = remote,
                             .data = data,
                             .len = len };

    assert((sock != NULL) || (remote != NULL));
    assert((len == 0) || (data != NULL));   /* (len != 0) => (data != NULL) */
    /* we want the send in the uip thread (which udp_socket_send does not offer)
     * so we need to do it manually */
    if (!send_registered) {
        if (evproc_regCallback(EVENT_TYPE_SOCK_SEND, _output_callback) != E_SUCCESS) {
            return -ENOMEM;
        }
        else {
            send_registered = true;
        }
    }
    if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
        (len > UINT16_MAX)) {
        return -ENOMEM;
    }
    if (remote != NULL) {
        if (remote->family != AF_INET6) {
            return -EAFNOSUPPORT;
        }
        if (remote->port == 0) {
            return -EINVAL;
        }
        send_cmd.remote = remote;
    }
    else if (sock->sock.udp_conn->rport == 0) {
        return -ENOTCONN;
    }
    /* cppcheck-supress nullPointerRedundantCheck
     * remote == NULL implies that sock != NULL (see assert at start of
     * function) * that's why it is okay in the if-statement above to check
     * sock->... without checking (sock != NULL) first => this check afterwards
     * isn't redundant */
    if (sock == NULL) {
        int res;
        if ((res = _reg(&tmp, NULL, NULL, NULL, NULL)) < 0) {
            return res;
        }
        send_cmd.sock = &tmp;
    }
    else {
        send_cmd.sock = &sock->sock;
    }
    mutex_lock(&send_cmd.block);
    /* change to emb6 thread context */
    if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_SOCK_SEND, &send_cmd) == E_SUCCESS) {
        /* block thread until data was sent */
        mutex_lock(&send_cmd.block);
    }
    else {
        /* most likely error: event queue was full */
        send_cmd.res = -ENOMEM;
    }
    if (send_cmd.sock == &tmp) {
        udp_socket_close(&tmp);
    }
    mutex_unlock(&send_cmd.block);

    return send_cmd.res;
}