| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #include "tcp.h"
- #include <arpa/inet.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <unistd.h>
- #define DBG_ENABLE
- #define DBG_COLOR
- #define DBG_SECTION_NAME "tcp"
- #define DBG_LEVEL DBG_LOG
- #include "dbg_log.h"
- int tcp_listen(int port, int nb_connection)
- {
- int new_s;
- int enable;
- int flags;
- struct sockaddr_in addr;
- flags = SOCK_STREAM;
- #ifdef SOCK_CLOEXEC
- flags |= SOCK_CLOEXEC;
- #endif
- new_s = socket(PF_INET, flags, IPPROTO_TCP);
- if (new_s == -1) {
- return -1;
- }
- enable = 1;
- if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&enable, sizeof(enable)) == -1) {
- close(new_s);
- return -1;
- }
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- /* If the modbus port is < to 1024, we need the setuid root. */
- addr.sin_port = htons(port);
- /* Listen any addresses */
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- close(new_s);
- return -1;
- }
- if (listen(new_s, nb_connection) == -1) {
- close(new_s);
- return -1;
- }
- flags = fcntl(new_s, F_GETFL, 0);
- flags |= O_NONBLOCK;
- fcntl(new_s, F_SETFL, flags);
- flags = fcntl(new_s, F_GETFD);
- flags |= FD_CLOEXEC;
- fcntl(new_s, F_SETFD, flags);
- return new_s;
- }
- int tcp_accept(int s)
- {
- struct sockaddr_in addr;
- socklen_t addrlen;
- int new_s;
- addrlen = sizeof(addr);
- #ifdef HAVE_ACCEPT4
- /* Inherit socket flags and use accept4 call */
- new_s = accept4(s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
- #else
- new_s = accept(s, (struct sockaddr *)&addr, &addrlen);
- #endif
- if (new_s == -1) {
- return -1;
- }
- LOG_I("The client connection from %s is accepted", inet_ntoa(addr.sin_addr));
- return new_s;
- }
- void tcp_close(int s)
- {
- if (s != -1) {
- shutdown(s, SHUT_RDWR);
- close(s);
- }
- }
- int tcp_send(int s, const uint8_t *buf, int length)
- {
- return send(s, buf, length, MSG_NOSIGNAL);
- }
- int tcp_receive(int s, uint8_t *buf, int bufsz, int timeout)
- {
- int len = 0;
- int rc = 0;
- fd_set readset, exceptset;
- struct timeval tv;
- while (bufsz > 0) {
- FD_ZERO(&readset);
- FD_ZERO(&exceptset);
- FD_SET(s, &readset);
- FD_SET(s, &exceptset);
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- rc = select(s + 1, &readset, NULL, &exceptset, &tv);
- if (rc == -1) {
- if (errno == EINTR) {
- continue;
- }
- }
- if (rc <= 0)
- break;
- if (FD_ISSET(s, &exceptset)) {
- rc = -1;
- break;
- }
- rc = recv(s, buf + len, bufsz, MSG_DONTWAIT);
- if (rc < 0)
- break;
- if (rc == 0) {
- if (len == 0)
- rc = -1;
- break;
- }
- len += rc;
- bufsz -= rc;
- timeout = 50;
- }
- if (rc >= 0)
- rc = len;
- return rc;
- }
- int tcp_flush(int s)
- {
- int rc;
- do {
- uint8_t devnull[100];
- if (s == -1)
- break;
- rc = recv(s, devnull, sizeof(devnull), MSG_DONTWAIT);
- } while (rc == 100);
- return 0;
- }
- int tcp_connect(const char *ip, int port)
- {
- int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (s == -1)
- return -1;
- int option = 1;
- int rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *)&option, sizeof(int));
- if (rc == -1) {
- close(s);
- s = -1;
- return -1;
- }
- struct timeval tv;
- tv.tv_sec = 20;
- tv.tv_usec = 0;
- rc = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const void *)&tv, sizeof(struct timeval));
- if (rc == -1) {
- close(s);
- s = -1;
- return -1;
- }
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = inet_addr(ip);
- rc = connect(s, (struct sockaddr *)&addr, sizeof(addr));
- if (rc == -1) {
- close(s);
- s = -1;
- return -1;
- }
- return s;
- }
|