int dup2(int sockfd1, int sockfd2) #endif { FAR struct socket *psock1; FAR struct socket *psock2; int err; int ret; /* Lock the scheduler throughout the following */ sched_lock(); /* Get the socket structures underly both descriptors */ psock1 = sockfd_socket(sockfd1); psock2 = sockfd_socket(sockfd2); /* Verify that the sockfd1 and sockfd2 both refer to valid socket * descriptors and that sockfd2 corresponds to allocated socket */ if (!psock1 || !psock2 || psock1->s_crefs <= 0) { err = EBADF; goto errout; } /* If sockfd2 also valid, allocated socket, then we will have to * close it! */ if (psock2->s_crefs > 0) { net_close(sockfd2); } /* Duplicate the socket state */ ret = net_clone(psock1, psock2); if (ret < 0) { err = -ret; goto errout; } sched_unlock(); return OK; errout: sched_unlock(); errno = err; return ERROR; }
ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { FAR struct socket *psock; ssize_t ret; /* sendto() is a cancellation point */ (void)enter_cancellation_point(); /* Get the underlying socket structure */ psock = sockfd_socket(sockfd); /* And let psock_sendto do all of the work */ ret = psock_sendto(psock, buf, len, flags, to, tolen); if (ret < 0) { set_errno((int)-ret); ret = ERROR; } leave_cancellation_point(); return ret; }
int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) { /* Get the underlying socket structure */ FAR struct socket *psock = sockfd_socket(sockfd); /* Then let psock_connect() do all of the work */ return psock_connect(psock, addr, addrlen); }
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { /* Make the socket descriptor to the underlying socket structure */ FAR struct socket *psock = sockfd_socket(sockfd); /* Then let psock_bind do all of the work */ return psock_bind(psock, addr, addrlen); }
int netdev_ioctl(int sockfd, int cmd, unsigned long arg) { FAR struct socket *psock = sockfd_socket(sockfd); int ret; /* Check if this is a valid command. In all cases, arg is a pointer that has * been cast to unsigned long. Verify that the value of the to-be-pointer is * non-NULL. */ if (!_SIOCVALID(cmd)) { ret = -ENOTTY; goto errout; } /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { ret = -EBADF; goto errout; } /* Execute the command */ ret = netdev_ifrioctl(psock, cmd, (FAR struct ifreq*)((uintptr_t)arg)); #ifdef CONFIG_NET_IGMP if (ret == -ENOTTY) { ret = netdev_imsfioctl(psock, cmd, (FAR struct ip_msfilter*)((uintptr_t)arg)); } #endif #ifdef CONFIG_NET_ROUTE if (ret == -ENOTTY) { ret = netdev_rtioctl(psock, cmd, (FAR struct rtentry*)((uintptr_t)arg)); } #endif /* Check for success or failure */ if (ret >= 0) { return ret; } /* On failure, set the errno and return -1 */ errout: errno = -ret; return ERROR; }
void sockfd_release(int sockfd) { /* Get the socket structure for this sockfd */ FAR struct socket *psock = sockfd_socket(sockfd); /* Get the socket structure for this sockfd */ if (psock) { sock_release(psock); } }
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, FAR struct sockaddr *from, FAR socklen_t *fromlen) { FAR struct socket *psock; /* Get the underlying socket structure */ psock = sockfd_socket(sockfd); /* Then let psock_recvfrom() do all of the work */ return psock_recvfrom(psock, buf, len, flags, from, fromlen); }
ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { FAR struct socket *psock; /* Get the underlying socket structure */ psock = sockfd_socket(sockfd); /* And let psock_sendto do all of the work */ return psock_sendto(psock, buf, len, flags, to, tolen); }
int net_poll(int sockfd, struct pollfd *fds, bool setup) { #ifndef HAVE_NETPOLL return -ENOSYS; #else FAR struct socket *psock; int ret; /* Get the underlying socket structure and verify that the sockfd * corresponds to valid, allocated socket */ psock = sockfd_socket(sockfd); if (!psock || psock->s_crefs <= 0) { ret = -EBADF; goto errout; } #ifdef CONFIG_NET_UDP /* poll() not supported for UDP */ if (psock->s_type != SOCK_STREAM) { ret = -ENOSYS; goto errout; } #endif /* Check if we are setting up or tearing down the poll */ if (setup) { /* Perform the TCP/IP poll() setup */ ret = net_pollsetup(psock, fds); } else { /* Perform the TCP/IP poll() teardown */ ret = net_pollteardown(psock, fds); } errout: return ret; #endif /* HAVE_NETPOLL */ }
int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len) { FAR struct socket *psock; /* Get the underlying socket structure */ /* Verify that the sockfd corresponds to valid, allocated socket */ psock = sockfd_socket(sockfd); if (!psock || psock->s_crefs <= 0) { set_errno(EBADF); return ERROR; } /* Then let psock_setockopt() do all of the work */ return psock_setsockopt(psock, level, option, value, value_len); }
ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags) { FAR struct socket *psock; ssize_t ret; /* send() is a cancellation point */ (void)enter_cancellation_point(); /* Get the underlying socket structure */ psock = sockfd_socket(sockfd); /* And let psock_send do all of the work */ ret = psock_send(psock, buf, len, flags); leave_cancellation_point(); return ret; }
int socket(int domain, int type, int protocol) { FAR struct socket *psock; int sockfd; int ret; /* Allocate a socket descriptor */ sockfd = sockfd_allocate(0); if (sockfd < 0) { set_errno(ENFILE); return ERROR; } /* Get the underlying socket structure */ psock = sockfd_socket(sockfd); if (!psock) { set_errno(ENOSYS); /* should not happen */ goto errout; } /* Initialize the socket structure */ ret = psock_socket(domain, type, protocol, psock); if (ret < 0) { /* Error already set by psock_socket() */ goto errout; } return sockfd; errout: sockfd_release(sockfd); return ERROR; }
int net_poll(int sockfd, struct pollfd *fds, bool setup) { #ifndef HAVE_NETPOLL return -ENOSYS; #else FAR struct socket *psock; /* Get the underlying socket structure and verify that the sockfd * corresponds to valid, allocated socket */ psock = sockfd_socket(sockfd); if (!psock || psock->s_crefs <= 0) { return -EBADF; } /* Then let psock_poll() do the heavy lifting */ return psock_poll(psock, fds, setup); #endif /* HAVE_NETPOLL */ }
FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon) { FAR struct telnetd_dev_s *priv; FAR struct socket *psock; FAR char *devpath = NULL; int ret; /* Allocate instance data for this driver */ priv = (FAR struct telnetd_dev_s*)malloc(sizeof(struct telnetd_dev_s)); if (!priv) { nlldbg("Failed to allocate the driver data structure\n"); return NULL; } /* Initialize the allocated driver instance */ sem_init(&priv->td_exclsem, 0, 1); priv->td_state = STATE_NORMAL; priv->td_crefs = 0; priv->td_pending = 0; priv->td_offset = 0; /* Clone the internal socket structure. We do this so that it will be * independent of threads and of socket descriptors (the original socket * instance resided in the daemon's socket array). */ psock = sockfd_socket(sd); if (!psock) { nlldbg("Failed to convert sd=%d to a socket structure\n", sd); goto errout_with_dev; } ret = net_clone(psock, &priv->td_psock); if (ret < 0) { nlldbg("net_clone failed: %d\n", ret); goto errout_with_dev; } /* And close the original */ psock_close(psock); /* Allocation a unique minor device number of the telnet drvier */ do { ret = sem_wait(&g_telnetdcommon.exclsem); if (ret < 0 && errno != -EINTR) { goto errout_with_dev; } } while (ret < 0); priv->td_minor = g_telnetdcommon.minor; g_telnetdcommon.minor++; sem_post(&g_telnetdcommon.exclsem); /* Create a path and name for the driver. */ ret = asprintf(&devpath, TELNETD_DEVFMT, priv->td_minor); if (ret < 0) { nlldbg("Failed to allocate the driver path\n"); goto errout_with_dev; } /* Register the driver */ ret = register_driver(devpath, &g_telnetdfops, 0666, priv); if (ret < 0) { nlldbg("Failed to register the driver %s: %d\n", devpath, ret); goto errout_with_devpath; } /* Return the path to the new telnet driver */ return devpath; errout_with_devpath: free(devpath); errout_with_dev: free(priv); return NULL; }
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); FAR struct socket *pnewsock; FAR struct uip_conn *conn; struct accept_s state; #ifdef CONFIG_NET_IPv6 FAR struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)addr; #else FAR struct sockaddr_in *inaddr = (struct sockaddr_in *)addr; #endif uip_lock_t save; int newfd; int err; int ret; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { /* It is not a valid socket description. Distinguish between the cases * where sockfd is a just valid and when it is a valid file descriptor used * in the wrong context. */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) { err = ENOTSOCK; } else #endif { err = EBADF; } goto errout; } /* We have a socket descriptor, but it is a stream? */ if (psock->s_type != SOCK_STREAM) { err = EOPNOTSUPP; goto errout; } /* Is the socket listening for a connection? */ if (!_SS_ISLISTENING(psock->s_flags)) { err = EINVAL; goto errout; } /* Verify that a valid memory block has been provided to receive the * address */ if (addr) { #ifdef CONFIG_NET_IPv6 if (*addrlen < sizeof(struct sockaddr_in6)) #else if (*addrlen < sizeof(struct sockaddr_in)) #endif { err = EBADF; goto errout; } } /* Allocate a socket descriptor for the new connection now (so that it * cannot fail later) */ newfd = sockfd_allocate(0); if (newfd < 0) { err = ENFILE; goto errout; } pnewsock = sockfd_socket(newfd); if (!pnewsock) { err = ENFILE; goto errout_with_socket; } /* Check the backlog to see if there is a connection already pending for * this listener. */ save = uip_lock(); conn = (struct uip_conn *)psock->s_conn; #ifdef CONFIG_NET_TCPBACKLOG state.acpt_newconn = uip_backlogremove(conn); if (state.acpt_newconn) { /* Yes... get the address of the connected client */ nvdbg("Pending conn=%p\n", state.acpt_newconn); accept_tcpsender(state.acpt_newconn, inaddr); } /* In general, this uIP-based implementation will not support non-blocking * socket operations... except in a few cases: Here for TCP accept with backlog * enabled. If this socket is configured as non-blocking then return EAGAIN * if there is no pending connection in the backlog. */ else if (_SS_ISNONBLOCK(psock->s_flags)) { err = EAGAIN; goto errout_with_lock; } else #endif { /* Set the socket state to accepting */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); /* Perform the TCP accept operation */ /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ state.acpt_addr = inaddr; state.acpt_newconn = NULL; state.acpt_result = OK; sem_init(&state.acpt_sem, 0, 0); /* Set up the callback in the connection */ conn->accept_private = (void*)&state; conn->accept = accept_interrupt; /* Wait for the send to complete or an error 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. */ ret = uip_lockedwait(&state.acpt_sem); /* Make sure that no further interrupts are processed */ conn->accept_private = NULL; conn->accept = NULL; sem_destroy(&state. acpt_sem); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signaled by negative errno values * for the send length. */ if (state.acpt_result != 0) { err = state.acpt_result; goto errout_with_lock; } /* If uip_lockedwait failed, then we were probably reawakened by a signal. In * this case, uip_lockedwait will have set errno appropriately. */ if (ret < 0) { err = -ret; goto errout_with_lock; } } /* Initialize the socket structure and mark the socket as connected. * (The reference count on the new connection structure was set in the * interrupt handler). */ pnewsock->s_type = SOCK_STREAM; pnewsock->s_conn = state.acpt_newconn; pnewsock->s_flags |= _SF_CONNECTED; pnewsock->s_flags &= ~_SF_CLOSED; /* Begin monitoring for TCP connection events on the newly connected socket */ net_startmonitor(pnewsock); uip_unlock(save); return newfd; errout_with_lock: uip_unlock(save); errout_with_socket: sockfd_release(newfd); errout: errno = err; return ERROR; }
int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); int ret; int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Some sanity checking... Shouldn't need this on a buckled up embedded * system (?) */ #ifdef CONFIG_DEBUG if (!addr || !addrlen) { err = EINVAL; goto errout; } #endif /* Handle by address domain */ switch (psock->s_domain) { #ifdef CONFIG_NET_IPv4 case PF_INET: ret = ipv4_getsockname(psock, addr, addrlen); break; #endif #ifdef CONFIG_NET_IPv6 case PF_INET6: ret = ipv6_getsockname(psock, addr, addrlen); break; #endif case PF_PACKET: default: err = EAFNOSUPPORT; goto errout; } /* Check for failure */ if (ret < 0) { err = -ret; goto errout; } return OK; errout: set_errno(err); return ERROR; }
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp) { FAR struct aio_container_s *aioc; union { #ifdef AIO_HAVE_FILEP FAR struct file *filep; #endif #ifdef AIO_HAVE_FILEP FAR struct socket *psock; #endif FAR void *ptr; } u; #ifdef CONFIG_PRIORITY_INHERITANCE struct sched_param param; #endif #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) if (aiocbp->aio_fildes >= CONFIG_NFILE_DESCRIPTORS) #endif #ifdef AIO_HAVE_FILEP { /* Get the file structure corresponding to the file descriptor. */ u.filep = fs_getfilep(aiocbp->aio_fildes); if (!u.filep) { /* The errno value has already been set */ return NULL; } } #endif #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) else #endif #ifdef AIO_HAVE_PSOCK { /* Get the socket structure corresponding to the socket descriptor */ u.psock = sockfd_socket(aiocbp->aio_fildes); if (!u.psock) { /* Does not set the errno. EBADF is the most likely explanation. */ set_errno(EBADF); return NULL; } } #endif /* Allocate the AIO control block container, waiting for one to become * available if necessary. This should never fail. */ aioc = aioc_alloc(); DEBUGASSERT(aioc); /* Initialize the container */ memset(aioc, 0, sizeof(struct aio_container_s)); aioc->aioc_aiocbp = aiocbp; aioc->u.aioc_filep = u.ptr; aioc->aioc_pid = getpid(); #ifdef CONFIG_PRIORITY_INHERITANCE DEBUGVERIFY(sched_getparam (aioc->aioc_pid, ¶m)); aioc->aioc_prio = param.sched_priority; #endif /* Add the container to the pending transfer list. */ aio_lock(); dq_addlast(&aioc->aioc_link, &g_aio_pending); aio_unlock(); return aioc; }
ssize_t send(int sockfd, const void *buf, size_t len, int flags) { FAR struct socket *psock = sockfd_socket(sockfd); struct send_s state; uip_lock_t save; int err; int ret = OK; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* If this is an un-connected socket, then return ENOTCONN */ if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) { err = ENOTCONN; goto errout; } /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); /* Perform the TCP send 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(); memset(&state, 0, sizeof(struct send_s)); (void)sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */ state.snd_sock = psock; /* Socket descriptor to use */ state.snd_buflen = len; /* Number of bytes to send */ state.snd_buffer = buf; /* Buffer to send from */ if (len > 0) { struct uip_conn *conn = (struct uip_conn*)psock->s_conn; /* Allocate resources to receive a callback */ state.snd_cb = uip_tcpcallbackalloc(conn); if (state.snd_cb) { /* Get the initial sequence number that will be used */ state.snd_isn = uip_tcpgetsequence(conn->sndseq); /* There is no outstanding, unacknowledged data after this * initial sequence number. */ conn->unacked = 0; /* Update the initial time for calculating timeouts */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) state.snd_time = clock_systimer(); #endif /* Set up the callback in the connection */ state.snd_cb->flags = UIP_ACKDATA|UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; state.snd_cb->priv = (void*)&state; state.snd_cb->event = send_interrupt; /* Notify the device driver of the availaibilty of TX data */ netdev_txnotify(&conn->ripaddr); /* Wait for the send to complete or an error 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. */ ret = uip_lockedwait(&state. snd_sem); /* Make sure that no further interrupts are processed */ uip_tcpcallbackfree(conn, state.snd_cb); } } sem_destroy(&state. snd_sem); uip_unlock(save); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signaled by negative errno values * for the send length */ if (state.snd_sent < 0) { err = state.snd_sent; goto errout; } /* If uip_lockedwait failed, then we were probably reawakened by a signal. In * this case, uip_lockedwait will have set errno appropriately. */ if (ret < 0) { err = -ret; goto errout; } /* Return the number of bytes actually sent */ return state.snd_sent; errout: *get_errno_ptr() = err; return ERROR; }
int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); FAR struct uip_driver_s *dev; #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr; #else FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr; #endif #endif int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Some sanity checking... Shouldn't need this on a buckled up embedded * system (?) */ #ifdef CONFIG_DEBUG if (!addr || !addrlen) { err = EINVAL; goto errout; } #endif /* Check if enough space has been provided for the full address */ #ifdef CONFIG_NET_IPv6 if (*addrlen < sizeof(struct sockaddr_in6)) #else if (*addrlen < sizeof(struct sockaddr_in)) #endif { /* This function is supposed to return the partial address if * a smaller buffer has been provided. This support has not * been implemented. */ err = ENOSYS; goto errout; } /* Set the port number */ switch (psock->s_type) { #ifdef CONFIG_NET_TCP case SOCK_STREAM: { struct uip_conn *tcp_conn = (struct uip_conn *)psock->s_conn; outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { struct uip_udp_conn *udp_conn = (struct uip_udp_conn *)psock->s_conn; outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ } break; #endif default: err = EOPNOTSUPP; goto errout; } /* ISSUE: As of this writing, the socket/connection does not know its IP * address. This is because the uIP design is only intended to support * a single network device and, therefore, only the network device knows * the IP address. * * Right now, we can just pick the first network device. But that may * not work in the future. */ netdev_semtake(); dev = g_netdevices; if (!dev) { netdev_semgive(); err = EINVAL; goto errout; } /* Set the address family and the IP address */ #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 #error "Not big enough for IPv6 address" outaddr->sin_family = AF_INET6; memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16); *addrlen = sizeof(struct sockaddr_in6); #else outaddr->sin_family = AF_INET; outaddr->sin_addr.s_addr = dev->d_ipaddr; *addrlen = sizeof(struct sockaddr_in); #endif #endif netdev_semgive(); /* Return success */ return OK; errout: set_errno(err); return ERROR; }
int netdev_ioctl(int sockfd, int cmd, unsigned long arg) { FAR struct socket *psock = sockfd_socket(sockfd); return psock_ioctl(psock, cmd, arg); }
ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, size_t count) { FAR struct socket *psock = sockfd_socket(outfd); FAR struct tcp_conn_s *conn; struct sendfile_s state; net_lock_t save; int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { ndbg("ERROR: Invalid socket\n"); err = EBADF; goto errout; } /* If this is an un-connected socket, then return ENOTCONN */ if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) { ndbg("ERROR: Not connected\n"); err = ENOTCONN; goto errout; } /* Make sure that we have the IP address mapping */ conn = (FAR struct tcp_conn_s *)psock->s_conn; DEBUGASSERT(conn); #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND #ifdef CONFIG_NET_ICMPv6_NEIGHBOR if (psock->s_domain == PF_INET) #endif { /* Make sure that the IP address mapping is in the ARP table */ ret = arp_send(conn->u.ipv4.raddr); } #endif /* CONFIG_NET_ARP_SEND */ #ifdef CONFIG_NET_ICMPv6_NEIGHBOR #ifdef CONFIG_NET_ARP_SEND else #endif { /* Make sure that the IP address mapping is in the Neighbor Table */ ret = icmpv6_neighbor(conn->u.ipv6.raddr); } #endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ /* Did we successfully get the address mapping? */ if (ret < 0) { ndbg("ERROR: Not reachable\n"); err = ENETUNREACH; goto errout; } #endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */ /* 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 = net_lock(); memset(&state, 0, sizeof(struct sendfile_s)); sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */ state.snd_sock = psock; /* Socket descriptor to use */ state.snd_foffset = offset ? *offset : 0; /* Input file offset */ state.snd_flen = count; /* Number of bytes to send */ state.snd_file = infile; /* File to read from */ /* Allocate resources to receive a callback */ state.snd_datacb = tcp_callback_alloc(conn); if (state.snd_datacb == NULL) { nlldbg("Failed to allocate data callback\n"); err = ENOMEM; goto errout_locked; } state.snd_ackcb = tcp_callback_alloc(conn); if (state.snd_ackcb == NULL) { nlldbg("Failed to allocate ack callback\n"); err = ENOMEM; goto errout_datacb; } /* Get the initial sequence number that will be used */ state.snd_isn = tcp_getsequence(conn->sndseq); /* There is no outstanding, unacknowledged data after this * initial sequence number. */ conn->unacked = 0; #ifdef CONFIG_NET_SOCKOPTS /* Set the initial time for calculating timeouts */ state.snd_time = clock_systimer(); #endif /* Set up the ACK callback in the connection */ state.snd_ackcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_DISCONN_EVENTS); state.snd_ackcb->priv = (FAR void *)&state; state.snd_ackcb->event = ack_interrupt; /* Perform the TCP send operation */ do { state.snd_datacb->flags = TCP_POLL; state.snd_datacb->priv = (FAR void *)&state; state.snd_datacb->event = sendfile_interrupt; /* Notify the device driver of the availability of TX data */ sendfile_txnotify(psock, conn); net_lockedwait(&state.snd_sem); } while (state.snd_sent >= 0 && state.snd_acked < state.snd_flen); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); tcp_callback_free(conn, state.snd_ackcb); errout_datacb: tcp_callback_free(conn, state.snd_datacb); errout_locked: sem_destroy(&state. snd_sem); net_unlock(save); errout: if (err) { set_errno(err); return ERROR; } else if (state.snd_sent < 0) { set_errno(-state.snd_sent); return ERROR; } else { return state.snd_sent; } }
ssize_t send(int sockfd, const void *buf, size_t len, int flags) { return psock_send(sockfd_socket(sockfd), buf, len, flags); }
int net_vfcntl(int sockfd, int cmd, va_list ap) { FAR struct socket *psock = sockfd_socket(sockfd); net_lock_t flags; int err = 0; int ret = 0; nvdbg("sockfd=%d cmd=%d\n", sockfd, cmd); /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Interrupts must be disabled in order to perform operations on socket structures */ flags = net_lock(); switch (cmd) { case F_DUPFD: /* Return a new file descriptor which shall be the lowest numbered * available (that is, not already open) file descriptor greater than * or equal to the third argument, arg, taken as an integer of type * int. The new file descriptor shall refer to the same open file * description as the original file descriptor, and shall share any * locks. The FD_CLOEXEC flag associated with the new file descriptor * shall be cleared to keep the file open across calls to one of the * exec functions. */ { ret = net_dupsd(sockfd, va_arg(ap, int)); } break; case F_GETFD: /* Get the file descriptor flags defined in <fcntl.h> that are associated * with the file descriptor fd. File descriptor flags are associated * with a single file descriptor and do not affect other file descriptors * that refer to the same file. */ case F_SETFD: /* Set the file descriptor flags defined in <fcntl.h>, that are associated * with fd, to the third argument, arg, taken as type int. If the * FD_CLOEXEC flag in the third argument is 0, the file shall remain open * across the exec functions; otherwise, the file shall be closed upon * successful execution of one of the exec functions. */ err = ENOSYS; /* F_GETFD and F_SETFD not implemented */ break; case F_GETFL: /* Get the file status flags and file access modes, defined in * <fcntl.h>, for the file description associated with fd. The file * access modes can be extracted from the return value using the * mask O_ACCMODE, which is defined in <fcntl.h>. File status flags * and file access modes are associated with the file description * and do not affect other file descriptors that refer to the same * file with different open file descriptions. */ { /* This summarizes the behavior of all NuttX sockets */ ret = O_RDWR | O_SYNC | O_RSYNC; #if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_TCP_READAHEAD) || \ defined(CONFIG_NET_UDP_READAHEAD) /* Unix domain sockets may be non-blocking. TCP/IP and UDP/IP * sockets may also be non-blocking if read-ahead is enabled */ if ((0 #ifdef CONFIG_NET_LOCAL || psock->s_domain == PF_LOCAL /* Unix domain stream or datagram */ #endif #ifdef CONFIG_NET_TCP_READAHEAD || psock->s_type == SOCK_STREAM /* IP or Unix domain stream */ #endif #ifdef CONFIG_NET_UDP_READAHEAD || psock->s_type == SOCK_DGRAM /* IP or Unix domain datagram */ #endif ) && _SS_ISNONBLOCK(psock->s_flags)) { ret |= O_NONBLOCK; } #endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */ } break; case F_SETFL: /* Set the file status flags, defined in <fcntl.h>, for the file description * associated with fd from the corresponding bits in the third argument, * arg, taken as type int. Bits corresponding to the file access mode and * the file creation flags, as defined in <fcntl.h>, that are set in arg shall * be ignored. If any bits in arg other than those mentioned here are changed * by the application, the result is unspecified. */ { #if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_TCP_READAHEAD) || \ defined(CONFIG_NET_UDP_READAHEAD) /* Non-blocking is the only configurable option. And it applies * only Unix domain sockets and to read operations on TCP/IP * and UDP/IP sockets when read-ahead is enabled. */ int mode = va_arg(ap, int); #if defined(CONFIG_NET_LOCAL_STREAM) || defined(CONFIG_NET_TCP_READAHEAD) if (psock->s_type == SOCK_STREAM) /* IP or Unix domain stream */ { if ((mode & O_NONBLOCK) != 0) { psock->s_flags |= _SF_NONBLOCK; } else { psock->s_flags &= ~_SF_NONBLOCK; } } else #endif #if defined(CONFIG_NET_LOCAL_DGRAM) || defined(CONFIG_NET_UDP_READAHEAD) if (psock->s_type == SOCK_DGRAM) /* IP or Unix domain datagram */ { if ((mode & O_NONBLOCK) != 0) { psock->s_flags |= _SF_NONBLOCK; } else { psock->s_flags &= ~_SF_NONBLOCK; } } else #endif #endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */ { ndbg("ERROR: Non-blocking not supported for this socket\n"); } } break; case F_GETOWN: /* If fd refers to a socket, get the process or process group ID specified * to receive SIGURG signals when out-of-band data is available. Positive values * indicate a process ID; negative values, other than -1, indicate a process group * ID. If fd does not refer to a socket, the results are unspecified. */ case F_SETOWN: /* If fd refers to a socket, set the process or process group ID specified * to receive SIGURG signals when out-of-band data is available, using the value * of the third argument, arg, taken as type int. Positive values indicate a * process ID; negative values, other than -1, indicate a process group ID. If * fd does not refer to a socket, the results are unspecified. */ case F_GETLK: /* Get the first lock which blocks the lock description pointed to by the third * argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>. * The information retrieved shall overwrite the information passed to fcntl() in * the structure flock. If no lock is found that would prevent this lock from being * created, then the structure shall be left unchanged except for the lock type * which shall be set to F_UNLCK. */ case F_SETLK: /* Set or clear a file segment lock according to the lock description pointed to * by the third argument, arg, taken as a pointer to type struct flock, defined in * <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive * (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). * F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive * lock cannot be set, fcntl() shall return immediately with a return value of -1. */ case F_SETLKW: /* This command shall be equivalent to F_SETLK except that if a shared or exclusive * lock is blocked by other locks, the thread shall wait until the request can be * satisfied. If a signal that is to be caught is received while fcntl() is waiting * for a region, fcntl() shall be interrupted. Upon return from the signal handler, * fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall * not be done. */ err = ENOSYS; /* F_GETOWN, F_SETOWN, F_GETLK, F_SETLK, F_SETLKW */ break; default: err = EINVAL; break; } net_unlock(flags); errout: if (err != 0) { set_errno(err); return ERROR; } return ret; }
int net_close(int sockfd) { return psock_close(sockfd_socket(sockfd)); }
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; #else FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; #endif int ret; #endif int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Verify that a valid address has been provided */ #ifdef CONFIG_NET_IPv6 if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) #else if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) #endif { err = EBADF; goto errout; } /* Perform the connection depending on the protocol type */ switch (psock->s_type) { #ifdef CONFIG_NET_TCP case SOCK_STREAM: { /* Verify that the socket is not already connected */ if (_SS_ISCONNECTED(psock->s_flags)) { err = EISCONN; goto errout; } /* Its not ... connect it */ ret = tcp_connect(psock, inaddr); if (ret < 0) { err = -ret; goto errout; } } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { ret = uip_udpconnect(psock->s_conn, inaddr); if (ret < 0) { err = -ret; goto errout; } } break; #endif default: err = EBADF; goto errout; } return OK; errout: errno = err; return ERROR; }
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; #else FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; #endif #endif int err; int ret; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Verify that a valid address has been provided */ #ifdef CONFIG_NET_IPv6 if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6)) #else if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) #endif { err = EBADF; goto errout; } /* Perform the binding depending on the protocol type */ switch (psock->s_type) { #ifdef CONFIG_NET_TCP case SOCK_STREAM: ret = uip_tcpbind(psock->s_conn, inaddr); psock->s_flags |= _SF_BOUND; break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: ret = uip_udpbind(psock->s_conn, inaddr); break; #endif default: err = EBADF; goto errout; } /* Was the bind successful */ if (ret < 0) { err = -ret; goto errout; } return OK; errout: *get_errno_ptr() = err; return ERROR; }