static int _transfer(struct in_addr *addr, uint8_t *wbuf, size_t wlen, uint8_t *rbuf, size_t rlen) { struct sockaddr_in servaddr; socklen_t slen = sizeof(servaddr); int ret; int sockfd = open_udp_clientfd(); make_sockaddr(&servaddr, addr, VIRTUAL_SWITCH_LISTEN_PORT); sendto(sockfd, wbuf, wlen, 0, (struct sockaddr *)&servaddr, slen); struct timeval tv = { 3, 0 }; ret = recvfrom_timeout(sockfd, rbuf, rlen, NULL, NULL, &tv); if (ret <= 0) { hsb_critical("_transfer: get err pkt, len=%d\n", ret); close(sockfd); return -1; } close(sockfd); return ret; }
static int virtual_switch_probe(void) { struct sockaddr_in servaddr, devaddr; socklen_t slen = sizeof(servaddr); socklen_t devlen = sizeof(devaddr); uint8_t sbuf[64], rbuf[64]; int ret; size_t count = 0; //hsb_debug("probe virtual switch\n"); /* 1.create udp socket */ int sockfd = open_udp_clientfd(); /* 2.send broadcast packet, 192.168.2.255:19001 */ if (get_broadcast_address(sockfd, &servaddr.sin_addr)) { close(sockfd); return -1; } servaddr.sin_family = AF_INET; servaddr.sin_port = htons(VIRTUAL_SWITCH_LISTEN_PORT); set_broadcast(sockfd, true); memset(sbuf, 0, sizeof(sbuf)); count = 8; SET_CMD_FIELD(sbuf, 0, uint16_t, VS_CMD_DEVICE_DISCOVER); SET_CMD_FIELD(sbuf, 2, uint16_t, count); sendto(sockfd, sbuf, count, 0, (struct sockaddr *)&servaddr, slen); /* 3.wait for response in 1 second */ struct timeval tv = { 3, 0 }; do { ret = recvfrom_timeout(sockfd, rbuf, sizeof(rbuf), (struct sockaddr *)&devaddr, &devlen, &tv); if (ret < count) { hsb_critical("probe: get err pkt, len=%d\n", ret); continue; } count = 32; int cmd = GET_CMD_FIELD(rbuf, 0, uint16_t); int len = GET_CMD_FIELD(rbuf, 2, uint16_t); if (cmd != VS_CMD_DEVICE_DISCOVER_RESP || len != count) { hsb_critical("probe: get err pkt, cmd=%x, len=%d\n", cmd, len); continue; } _register_device(&devaddr.sin_addr, (VS_INFO_T *)(rbuf + 8)); } while (tv.tv_sec > 0 && tv.tv_usec > 0); close(sockfd); //hsb_debug("probe virtual switch done\n"); return 0; }
static uint16_t recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn, void *pvpriv, uint16_t flags) { struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv; nllvdbg("flags: %04x\n", flags); /* 'priv' might be null in some race conditions (?) */ if (pstate) { /* If new data is available, then complete the read action. */ if ((flags & UIP_NEWDATA) != 0) { /* Copy the data from the packet */ recvfrom_newudpdata(dev, pstate); /* We are finished. */ nllvdbg("UDP done\n"); /* Don't allow any further UDP call backs. */ pstate->rf_cb->flags = 0; pstate->rf_cb->priv = NULL; pstate->rf_cb->event = NULL; /* Save the sender's address in the caller's 'from' location */ recvfrom_udpsender(dev, pstate); /* Indicate that the data has been consumed */ flags &= ~UIP_NEWDATA; /* Wake up the waiting thread, returning the number of bytes * actually read. */ sem_post(&pstate->rf_sem); } /* No data has been received -- this is some other event... probably a * poll -- check for a timeout. */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) else if (recvfrom_timeout(pstate)) { /* Yes.. the timeout has elapsed... do not allow any further * callbacks */ nllvdbg("UDP timeout\n"); /* Stop further callbacks */ pstate->rf_cb->flags = 0; pstate->rf_cb->priv = NULL; pstate->rf_cb->event = NULL; /* Report a timeout error */ pstate->rf_result = -EAGAIN; /* Wake up the waiting thread */ sem_post(&pstate->rf_sem); } #endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ } return flags; }
static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn, void *pvpriv, uint16_t flags) { struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv; nllvdbg("flags: %04x\n", flags); /* 'priv' might be null in some race conditions (?) */ if (pstate) { /* If new data is available, then complete the read action. */ if ((flags & UIP_NEWDATA) != 0) { /* Copy the data from the packet (saving any unused bytes from the * packet in the read-ahead buffer). */ recvfrom_newtcpdata(dev, pstate); /* Save the sender's address in the caller's 'from' location */ recvfrom_tcpsender(dev, pstate); /* Indicate that the data has been consumed and that an ACK * should be sent. */ flags = (flags & ~UIP_NEWDATA) | UIP_SNDACK; /* Check for transfer complete. We will consider the transfer * complete in own of two different ways, depending on the setting * of CONFIG_NET_TCP_RECVDELAY. * * 1) If CONFIG_NET_TCP_RECVDELAY == 0 then we will consider the * TCP/IP transfer complete as soon as any data has been received. * This is safe because if any additional data is received, it * will be retained inthe TCP/IP read-ahead buffer until the * next receive is performed. * 2) CONFIG_NET_TCP_RECVDELAY > 0 may be set to wait a little * bit to determine if more data will be received. You might * do this if read-ahead buffereing is disabled and we want to * minimize the loss of back-to-back packets. In this case, * the transfer is complete when either a) the entire user buffer * is full or 2) when the receive timeout occurs (below). */ #if CONFIG_NET_TCP_RECVDELAY > 0 if (pstate->rf_buflen == 0) #else if (pstate->rf_recvlen > 0) #endif { nllvdbg("TCP resume\n"); /* The TCP receive buffer is full. Return now and don't allow * any further TCP call backs. */ pstate->rf_cb->flags = 0; pstate->rf_cb->priv = NULL; pstate->rf_cb->event = NULL; /* Wake up the waiting thread, returning the number of bytes * actually read. */ sem_post(&pstate->rf_sem); } /* Reset the timeout. We will want a short timeout to terminate * the TCP receive. */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) pstate->rf_starttime = clock_systimer(); #endif } /* Check for a loss of connection. * * UIP_CLOSE: The remote host has closed the connection * UIP_ABORT: The remote host has aborted the connection * UIP_TIMEDOUT: Connection aborted due to too many retransmissions. */ else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { nllvdbg("error\n"); /* Stop further callbacks */ pstate->rf_cb->flags = 0; pstate->rf_cb->priv = NULL; pstate->rf_cb->event = NULL; /* If the peer gracefully closed the connection, then return zero * (end-of-file). Otherwise, report a not-connected error */ if ((flags & UIP_CLOSE) != 0) { pstate->rf_result = 0; } else { pstate->rf_result = -ENOTCONN; } /* Wake up the waiting thread */ sem_post(&pstate->rf_sem); } /* No data has been received -- this is some other event... probably a * poll -- check for a timeout. */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) else if (recvfrom_timeout(pstate)) { /* Yes.. the timeout has elapsed... do not allow any further * callbacks */ nllvdbg("TCP timeout\n"); pstate->rf_cb->flags = 0; pstate->rf_cb->priv = NULL; pstate->rf_cb->event = NULL; /* Report an error only if no data has been received. (If * CONFIG_NET_TCP_RECVDELAY then rf_recvlen should always be * zero). */ #if CONFIG_NET_TCP_RECVDELAY > 0 if (pstate->rf_recvlen == 0) #endif { /* Report the timeout error */ pstate->rf_result = -EAGAIN; } /* Wake up the waiting thread, returning either the error -EAGAIN * that signals the timeout event or the data received up to * the point tht the timeout occured (no error). */ sem_post(&pstate->rf_sem); } #endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ } return flags; }