/* Server.cpp - Server class for Raspberry Pi Copyright (c) 2016 Hristo Gochkov All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "NetworkServer.h" #include #include #undef write #undef close int NetworkServer::setTimeout(uint32_t seconds) { struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) { return -1; } return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); } NetworkClient NetworkServer::available() { return accept(); } NetworkClient NetworkServer::accept() { if (!_listening) { return NetworkClient(); } int client_sock; if (_accepted_sockfd >= 0) { client_sock = _accepted_sockfd; _accepted_sockfd = -1; } else { #if CONFIG_LWIP_IPV6 struct sockaddr_in6 _client; int cs = sizeof(struct sockaddr_in6); #else struct sockaddr_in _client; int cs = sizeof(struct sockaddr_in); #endif #ifdef ESP_IDF_VERSION_MAJOR client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #else client_sock = lwip_accept_r(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #endif } if (client_sock >= 0) { int val = 1; if (setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(int)) == ESP_OK) { val = _noDelay; if (setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(int)) == ESP_OK) { return NetworkClient(client_sock); } } } return NetworkClient(); } void NetworkServer::begin(uint16_t port) { begin(port, 1); } void NetworkServer::begin(uint16_t port, int enable) { if (_listening) { return; } if (port) { _port = port; } #if CONFIG_LWIP_IPV6 struct sockaddr_in6 server; sockfd = socket(AF_INET6, SOCK_STREAM, 0); if (sockfd < 0) { return; } setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); server.sin6_family = AF_INET6; if (_addr.type() == IPv4) { memcpy(server.sin6_addr.s6_addr + 11, (uint8_t *)&_addr[0], 4); server.sin6_addr.s6_addr[10] = 0xFF; server.sin6_addr.s6_addr[11] = 0xFF; } else { memcpy(server.sin6_addr.s6_addr, (uint8_t *)&_addr[0], 16); } memset(server.sin6_addr.s6_addr, 0x0, 16); server.sin6_port = htons(_port); #else struct sockaddr_in server; memset(&server, 0x0, sizeof(sockaddr_in)); server.sin_family = AF_INET; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { return; } setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); memcpy((uint8_t *)&(server.sin_addr.s_addr), (uint8_t *)&_addr[0], 4); server.sin_port = htons(_port); #endif if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { return; } if (listen(sockfd, _max_clients) < 0) { return; } fcntl(sockfd, F_SETFL, O_NONBLOCK); _listening = true; _noDelay = false; _accepted_sockfd = -1; } void NetworkServer::setNoDelay(bool nodelay) { _noDelay = nodelay; } bool NetworkServer::getNoDelay() { return _noDelay; } bool NetworkServer::hasClient() { if (_accepted_sockfd >= 0) { return true; } #if CONFIG_LWIP_IPV6 struct sockaddr_in6 _client; int cs = sizeof(struct sockaddr_in6); #else struct sockaddr _client; int cs = sizeof(struct sockaddr); #endif #ifdef ESP_IDF_VERSION_MAJOR _accepted_sockfd = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #else _accepted_sockfd = lwip_accept_r(sockfd, (struct sockaddr *)&_client, (socklen_t *)&cs); #endif if (_accepted_sockfd >= 0) { return true; } return false; } void NetworkServer::end() { #ifdef ESP_IDF_VERSION_MAJOR lwip_close(sockfd); #else lwip_close_r(sockfd); #endif sockfd = -1; _listening = false; } void NetworkServer::close() { end(); } void NetworkServer::stop() { end(); }