📄 conn.c
字号:
/* * OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway * * conn.c - connections management procedures * * Copyright (c) 2002-2003, Victor Antonovich (avmlink@vlink.ru) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: conn.c,v 1.1.1.1 2003/09/13 20:38:33 kapyar Exp $ */#include "conn.h"#include "queue.h"#include "state.h"/* global variables */extern int server_sd;extern queue_t queue;extern ttydata_t tty;extern cfg_t cfg;conn_t *actconn; /* last active connection */int max_sd; /* major descriptor in the select() sets */void conn_tty_start(ttydata_t *tty, conn_t *conn);ssize_t conn_read(int d, void *buf, size_t nbytes);ssize_t conn_write(int d, void *buf, size_t nbytes);int conn_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);#define FD_MSET(d, s) do { FD_SET(d, s); max_sd = MAX(d, max_sd); } while (0);/* * Connections startup initialization * Parameters: none * Return: RC_OK in case of success, RC_ERR otherwise */intconn_init(void){ /* tty device initialization */#ifdef TRXCTL tty_init(&tty, cfg.ttyport, cfg.ttyspeed, cfg.trxcntl);#else tty_init(&tty, cfg.ttyport, cfg.ttyspeed);#endif if (tty_open(&tty) != RC_OK) {#ifdef LOG log(0, "conn_init():" " can't open tty device %s (%s)", cfg.ttyport, strerror(errno));#endif return RC_ERR; } state_tty_set(&tty, TTY_READY); /* create server socket */ if ((server_sd = sock_create_server("", cfg.serverport, TRUE)) < 0) {#ifdef LOG log(0, "conn_init():" " can't create listen() socket (%s)", strerror(errno));#endif return RC_ERR; } /* connections queue initialization */ queue_init(&queue); return RC_OK;}/* * Open new client connection * Parameters: none * Return: none */voidconn_open(void){ int sd; conn_t *newconn; struct sockaddr_in rmt_addr; if ((sd = sock_accept(server_sd, &rmt_addr, TRUE)) == RC_ERR) { /* error in conn_accept() */#ifdef LOG log(0, "conn_open(): error in accept() (%s)", strerror(errno));#endif return; }#ifdef LOG log(2, "conn_open(): accepting connection from %s", inet_ntoa(rmt_addr.sin_addr));#endif /* compare descriptor of connection with FD_SETSIZE */ if (sd >= FD_SETSIZE) {#ifdef LOG log(1, "conn_open(): FD_SETSIZE limit reached," " connection from %s will be dropped", inet_ntoa(rmt_addr.sin_addr));#endif close(sd); return; } /* check current number of connections */ if (queue.len == cfg.maxconn) {#ifdef LOG log(1, "conn_open(): number of connections limit reached," " connection from %s will be dropped", inet_ntoa(rmt_addr.sin_addr));#endif close(sd); return; } /* enqueue connection */ newconn = queue_new_elem(&queue); newconn->sd = sd; memcpy((void *) &newconn->sockaddr, &rmt_addr, sizeof(struct sockaddr_in)); state_conn_set(newconn, CONN_HEADER);}/* * Close client connection * Parameters: CONN - ptr to connection to close * Return: pointer to next queue element */conn_t *conn_close(conn_t *conn){ conn_t *nextconn;#ifdef LOG log(2, "conn_close(): closing connection from %s", inet_ntoa(conn->sockaddr.sin_addr));#endif /* close socket */ close(conn->sd); /* get pointer to next element */ nextconn = queue_next_elem(&queue, conn); /* dequeue connection */ queue_delete_elem(&queue, conn); if (actconn == conn) actconn = nextconn; return nextconn;}/* * Start tty transaction * Parameters: TTY - ptr to tty structure, * CONN - ptr to active connection * Return: none */voidconn_tty_start(ttydata_t *tty, conn_t *conn){ (void)memcpy((void *)tty->txbuf, (void *)(conn->buf + HDRSIZE), MB_HDR(conn->buf, MB_LENGTH_L)); modbus_crc_write(tty->txbuf, MB_HDR(conn->buf, MB_LENGTH_L)); tty->txlen = MB_HDR(conn->buf, MB_LENGTH_L) + CRCSIZE; state_tty_set(tty, TTY_RQST); actconn = conn;}/* * Read() wrapper. Read nomore BYTES from descriptor D in buffer BUF * Return: number of successfully readed bytes, * RC_ERR in case of error. */ssize_tconn_read(int d, void *buf, size_t nbytes){ int rc; do { /* trying read from descriptor while breaked by signals */ rc = read(d, buf, nbytes); } while (rc == -1 && errno == EINTR); return (rc < 0) ? RC_ERR : rc;}/* * Write() wrapper. Write nomore BYTES to descriptor D from buffer BUF * Return: number of successfully written bytes, * RC_ERR in case of error. */ssize_tconn_write(int d, void *buf, size_t nbytes){ int rc; do { /* trying write to descriptor while breaked by signals */ rc = write(d, buf, nbytes); } while (rc == -1 && errno == EINTR); return (rc < 0) ? RC_ERR : rc;}#if 0/* * Select() wrapper with signal checking. * Return: number number of ready descriptors, * RC_ERR in case of error. */intconn_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ int rc; do { /* trying to select() while breaked by signals */ rc = select(nfds, readfds, writefds, exceptfds, timeout); } while (rc == -1 && errno == EINTR); return (rc < 0) ? RC_ERR : rc;}#endif/* * Connections serving loop * Parameters: none * Return: none */voidconn_loop(void){ int rc, max_sd, len, min_timeout; fd_set sdsetrd, sdsetwr; struct timeval ts, tts, t_out; unsigned long tval, tout_sec, tout = 0ul; conn_t *curconn = NULL; while (TRUE) { /* check for the signals */ if (sig_flag) sig_exec(); /* update FD_SETs */ FD_ZERO(&sdsetrd); max_sd = server_sd; FD_MSET(server_sd, &sdsetrd); FD_ZERO(&sdsetwr); /* update FD_SETs by TCP connections */ len = queue.len; curconn = queue.beg; min_timeout = cfg.conntimeout; while (len--) { switch (curconn->state) { case CONN_HEADER: case CONN_RQST: FD_MSET(curconn->sd, &sdsetrd); break; case CONN_RESP: FD_MSET(curconn->sd, &sdsetwr); break; } min_timeout = MIN(min_timeout, curconn->timeout); curconn = queue_next_elem(&queue, curconn); } /* update FD_SETs by tty connection */ FD_MSET(tty.fd, &sdsetrd); if (tty.state == TTY_RQST) FD_MSET(tty.fd, &sdsetwr); if (tty.timer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -