X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fnet%2Ftcp_socket.c;h=65db328fb99c7b06c856b7359f49546450b75b7d;hb=1a8a2b9b57118be3f52d1261ebefac3875e67bcf;hp=225d9ea33dd7b8315a7f10f2b9b19fb7868540ff;hpb=7ad028015399ac93ad526b06cf6f984b4f96c14e;p=bertos.git diff --git a/bertos/net/tcp_socket.c b/bertos/net/tcp_socket.c index 225d9ea3..65db328f 100644 --- a/bertos/net/tcp_socket.c +++ b/bertos/net/tcp_socket.c @@ -40,8 +40,10 @@ #include "tcp_socket.h" -#define LOG_LEVEL LOG_LVL_INFO -#define LOG_FORMAT LOG_FMT_TERSE +#include "cfg/cfg_tcpsocket.h" + +#define LOG_LEVEL TCPSOCKET_LOG_LEVEL +#define LOG_FORMAT TCPSOCKET_LOG_FORMAT #include #include @@ -51,102 +53,131 @@ #include #include -static int tcpConnect(TcpSocket *socket) + +INLINE int close_socket(TcpSocket *socket) { + /* Clean all previuos states */ + netbuf_delete(socket->rx_buf_conn); + socket->rx_buf_conn = NULL; socket->remaning_data_len = 0; - socket->sock = netconn_new(NETCONN_TCP); - ASSERT(socket->sock); + socket->error = 0; - if(netconn_bind(socket->sock, socket->local_addr, socket->port) != ERR_OK) - { - LOG_ERR("Connection error\n"); - goto error; - } + if (!socket->sock) + return 0; + + /* Close socket if was opened */ + socket->error = netconn_delete(socket->sock); + socket->sock = NULL; - if(netconn_connect(socket->sock, socket->remote_addr, socket->port) != ERR_OK) + if (socket->error != ERR_OK) { - LOG_ERR("Cannot create socket\n"); - goto error; + LOG_ERR("Closing socket\n"); + return -1; } - LOG_INFO("connected ip=%d.%d.%d.%d\n", IP_ADDR_TO_INT_TUPLE(socket->local_addr->addr)); return 0; - -error: - netconn_delete(socket->sock); - socket->sock = NULL; - return -1; } - -static bool reconnect(TcpSocket *socket) +static bool tcpsocket_reconnect(TcpSocket *socket) { LOG_INFO("Reconnecting...\n"); - // Release old socket if needed - if (socket->sock) - { - if (netconn_delete(socket->sock) != ERR_OK) - LOG_ERR("Error closing socket\n"); - socket->sock = NULL; + /* Close socket if was opened */ + close_socket(socket); + + /* If we are in server mode we do nothing */ + if (socket->handler) + return true; + + + /* Start with new connection */ + socket->sock = netconn_new(NETCONN_TCP); + if(!socket->sock) + { + LOG_ERR("Unabe to alloc new connection\n"); + socket->error = -1; + goto error; } - // Connect to our peer peer - if (tcpConnect(socket) < 0) + socket->error = netconn_bind(socket->sock, socket->local_addr, socket->port); + if(socket->error != ERR_OK) { - LOG_ERR("Reconnect error!\n"); - socket->error |= ERR_TCP_NOTCONN; - return false; + LOG_ERR("Connection error\n"); + goto error; } - LOG_INFO("Reconnecting DONE!\n"); + socket->error = netconn_connect(socket->sock, socket->remote_addr, socket->port); + if(socket->error != ERR_OK) + { + LOG_ERR("Cannot create socket\n"); + goto error; + } + LOG_INFO("connected ip=%d.%d.%d.%d\n", IP_ADDR_TO_INT_TUPLE(socket->remote_addr->addr)); return true; + +error: + netconn_delete(socket->sock); + socket->sock = NULL; + return false; } static int tcpsocket_close(KFile *fd) { TcpSocket *socket = TCPSOCKET_CAST(fd); - int ret = netconn_delete(socket->sock); - socket->sock = NULL; + return close_socket(socket); +} - if (ret) - { - LOG_ERR("Close error\n"); - socket->error |= ERR_CONN_CLOSE; - return EOF; - } - return 0; +static KFile *tcpsocket_reopen(KFile *fd) +{ + TcpSocket *socket = TCPSOCKET_CAST(fd); + if (tcpsocket_reconnect(socket)) + return fd; + + return NULL; } +/* + * Read data from socket. + * + * The read return the bytes that had been received if they are less than we request too. + * Otherwise if the byte that we want read are less that the received bytes, we return only + * the requested bytes. To get the remaning bytes we need to make an others read, until the + * buffer is empty. + * When there are not any more bytes, a new read takes data from remote socket. + */ static size_t tcpsocket_read(KFile *fd, void *buf, size_t len) { TcpSocket *socket = TCPSOCKET_CAST(fd); - char *_buf; + + char *data; uint16_t read_len = 0; - uint16_t recv_data_len = 0; - size_t _len = 0; - if (socket->remaning_data_len == 0) + if (socket->remaning_data_len <= 0) { LOG_INFO("No byte left.\n"); - if (socket->rx_buf_conn) - netbuf_delete(socket->rx_buf_conn); + netbuf_delete(socket->rx_buf_conn); } - else if (socket->remaning_data_len > 0) + else /* We had byte into buffer use that */ { - LOG_INFO("Return stored bytes.\n"); - ASSERT(socket->rx_buf_conn); - netbuf_data(socket->rx_buf_conn, (void **)&_buf, &recv_data_len); + LOG_INFO("Read stored bytes.\n"); + if (!socket->rx_buf_conn) + { + LOG_ERR("Byte stored are corrupted!\n"); + socket->remaning_data_len = 0; + return 0; + } + uint16_t tot_data_len = 0; + netbuf_data(socket->rx_buf_conn, (void **)&data, &tot_data_len); - if (_buf) + if (data) { - ASSERT((recv_data_len - socket->remaning_data_len) > 0); - _len = MIN((size_t)(socket->remaning_data_len), len); - memcpy((char *)buf, &_buf[recv_data_len - socket->remaning_data_len], _len); + ASSERT(((int)tot_data_len - (int)socket->remaning_data_len) >= 0); + size_t chunk_len = MIN((size_t)(socket->remaning_data_len), len); + memcpy((char *)buf, &data[tot_data_len - socket->remaning_data_len], chunk_len); - socket->remaning_data_len -= _len; - return _len; + socket->remaning_data_len -= chunk_len; + return chunk_len; } else { @@ -158,45 +189,47 @@ static size_t tcpsocket_read(KFile *fd, void *buf, size_t len) } /* Try reconnecting if our socket isn't valid */ - if (!socket->sock) - { - if (!reconnect(socket)) - return 0; - } + if (!socket->sock && !tcpsocket_reconnect(socket)) + return 0; while (len) { LOG_INFO("Get bytes from socket.\n"); socket->rx_buf_conn = netconn_recv(socket->sock); - socket->error = netconn_err(socket->sock); + socket->error = netconn_err(socket->sock); if (socket->error != ERR_OK) { LOG_ERR("While recv %d\n", socket->error); - socket->rx_buf_conn = NULL; + close_socket(socket); return 0; } + size_t chunk_len = 0; + uint16_t data_len = 0; if (socket->rx_buf_conn) { - netbuf_data(socket->rx_buf_conn, (void **)&_buf, &recv_data_len); - if (_buf) + netbuf_data(socket->rx_buf_conn, (void **)&data, &data_len); + + if (data) { - socket->remaning_data_len = recv_data_len; - _len = MIN((size_t)recv_data_len, len); - memcpy(buf, _buf, _len); - socket->remaning_data_len -= _len; + chunk_len = MIN((size_t)data_len, len); + memcpy(buf, data, chunk_len); + + socket->remaning_data_len = data_len - chunk_len; } if (socket->remaning_data_len <= 0) { netbuf_delete(socket->rx_buf_conn); - return _len; + socket->rx_buf_conn = NULL; + socket->remaning_data_len = 0; + return chunk_len; } } - len -= _len; - read_len += _len; + len -= chunk_len; + read_len += chunk_len; } return read_len; @@ -206,25 +239,15 @@ static size_t tcpsocket_write(KFile *fd, const void *buf, size_t len) { TcpSocket *socket = TCPSOCKET_CAST(fd); - // Try reconnecting if our socket isn't valid - if (!socket->sock) - { - if (!reconnect(socket)) - return 0; - } + /* Try reconnecting if our socket isn't valid */ + if (!socket->sock && !tcpsocket_reconnect(socket)) + return 0; - int result = netconn_write(socket->sock, buf, len, NETCONN_COPY); - if (result != ERR_OK) + socket->error = netconn_write(socket->sock, buf, len, NETCONN_COPY); + if (socket->error != ERR_OK) { - LOG_ERR("While writing %d\n", result); - if (result == ERR_RST) - { - LOG_INFO("Connection close\n"); - - if (tcpsocket_close(fd) == EOF) - LOG_ERR("Error closing socket, leak detected\n"); - return 0; - } + LOG_ERR("While writing %d\n", socket->error); + close_socket(socket); return 0; } @@ -243,9 +266,27 @@ static void tcpsocket_clearerr(KFile *fd) socket->error = 0; } +void tcpsocket_serverPoll(KFile *fd) +{ + TcpSocket *socket = TCPSOCKET_CAST(fd); + + + if (!socket->sock) + socket->sock = netconn_accept(socket->server_sock); + + if (!socket->sock) + { + LOG_ERR("Unable to connect with client\n"); + return; + } + + socket->handler(fd); +} + void tcpsocket_init(TcpSocket *socket, struct ip_addr *local_addr, struct ip_addr *remote_addr, uint16_t port) { - socket->sock = NULL; + memset(socket, 0, sizeof(TcpSocket)); + socket->local_addr = local_addr; socket->remote_addr = remote_addr; socket->port = port; @@ -256,5 +297,18 @@ void tcpsocket_init(TcpSocket *socket, struct ip_addr *local_addr, struct ip_add socket->fd.close = tcpsocket_close; socket->fd.write = tcpsocket_write; socket->fd.clearerr = tcpsocket_clearerr; + socket->fd.reopen = tcpsocket_reopen; } + +void tcpsocket_serverInit(TcpSocket *socket, struct ip_addr *local_addr, struct ip_addr *listen_addr, uint16_t port, tcphandler_t handler) +{ + tcpsocket_init(socket, local_addr, listen_addr, port); + socket->handler = handler; + + socket->server_sock = netconn_new(NETCONN_TCP); + socket->error = netconn_bind(socket->server_sock, listen_addr, port); + socket->error = netconn_listen(socket->server_sock); + if(socket->error != ERR_OK) + LOG_ERR("Init server\n"); +}