ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { #ifdef CONFIG_NET_UDP FAR struct uip_udp_conn *conn; #ifdef CONFIG_NET_IPv6 FAR const struct sockaddr_in6 *into = (const struct sockaddr_in6 *)to; #else FAR const struct sockaddr_in *into = (const struct sockaddr_in *)to; #endif struct sendto_s state; uip_lock_t save; int ret; #endif int err; /* If to is NULL or tolen is zero, then this function is same as send (for * connected socket types) */ if (!to || !tolen) { #ifdef CONFIG_NET_TCP return psock_send(psock, buf, len, flags); #else err = EINVAL; goto errout; #endif } /* Verify that a valid address has been provided */ #ifdef CONFIG_NET_IPv6 if (to->sa_family != AF_INET6 || tolen < sizeof(struct sockaddr_in6)) #else if (to->sa_family != AF_INET || tolen < sizeof(struct sockaddr_in)) #endif { err = EBADF; goto errout; } /* Verify that the psock corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* If this is a connected socket, then return EISCONN */ if (psock->s_type != SOCK_DGRAM) { err = EISCONN; goto errout; } /* Perform the UDP sendto operation */ #ifdef CONFIG_NET_UDP /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ save = uip_lock(); memset(&state, 0, sizeof(struct sendto_s)); sem_init(&state.st_sem, 0, 0); state.st_buflen = len; state.st_buffer = buf; /* Set the initial time for calculating timeouts */ #ifdef CONFIG_NET_SENDTO_TIMEOUT state.st_sock = psock; state.st_time = clock_systimer(); #endif /* Setup the UDP socket */ conn = (struct uip_udp_conn *)psock->s_conn; ret = uip_udpconnect(conn, into); if (ret < 0) { uip_unlock(save); err = -ret; goto errout; } /* Set up the callback in the connection */ state.st_cb = uip_udpcallbackalloc(conn); if (state.st_cb) { state.st_cb->flags = UIP_POLL; state.st_cb->priv = (void*)&state; state.st_cb->event = sendto_interrupt; /* Notify the device driver of the availabilty of TX data */ netdev_txnotify(conn->ripaddr); /* Wait for either the receive to complete or for an error/timeout to occur. * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) * interrupts may be disabled! They will be re-enabled while the task sleeps * and automatically re-enabled when the task restarts. */ uip_lockedwait(&state.st_sem); /* Make sure that no further interrupts are processed */ uip_udpcallbackfree(conn, state.st_cb); } uip_unlock(save); sem_destroy(&state.st_sem); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for errors */ if (state.st_sndlen < 0) { err = -state.st_sndlen; goto errout; } /* Sucess */ return state.st_sndlen; #else err = ENOSYS; #endif errout: set_errno(err); return ERROR; }
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, FAR struct sockaddr_in *infrom ) #endif { struct uip_udp_conn *conn = (struct uip_udp_conn *)psock->s_conn; struct recvfrom_s state; uip_lock_t save; int ret; /* Perform the UDP recvfrom() operation */ /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ save = uip_lock(); recvfrom_init(psock, buf, len, infrom, &state); /* Setup the UDP remote connection */ ret = uip_udpconnect(conn, NULL); if (ret < 0) { goto errout_with_state; } /* Set up the callback in the connection */ state.rf_cb = uip_udpcallbackalloc(conn); if (state.rf_cb) { /* Set up the callback in the connection */ state.rf_cb->flags = UIP_NEWDATA|UIP_POLL; state.rf_cb->priv = (void*)&state; state.rf_cb->event = recvfrom_udpinterrupt; /* Enable the UDP socket */ uip_udpenable(conn); /* Wait for either the receive to complete or for an error/timeout to occur. * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) * interrupts are disabled! They will be re-enabled while the task sleeps * and automatically re-enabled when the task restarts. */ ret = uip_lockedwait(&state. rf_sem); /* Make sure that no further interrupts are processed */ uip_udpdisable(conn); uip_udpcallbackfree(conn, state.rf_cb); ret = recvfrom_result(ret, &state); } else { ret = -EBUSY; } errout_with_state: uip_unlock(save); recvfrom_uninit(&state); return ret; }