blob: 6b641b2ad09dc357a3f587b2a8822939b686d57d [file] [log] [blame]
/*
*
* Copyright (C) 2000 Paul Davis, pdavis@lpccomp.bc.ca
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* This program acts as a bridge either between a socket(2) and a
* serial/parallel port or between a socket and a pseudo-tty.
*/
#include "../zlog_com.h"
/**
* ºê¶¨Òå
*/
#define RECVBUF_MODEM_MAX_LEN 2048
#define RECVBUF_SOCK_CLIENT_LEN 512
/**
* Íⲿ±äÁ¿ÒýÓÃ
*/
extern char* ptsname(int fd);
/**
* Íⲿº¯ÊýÒýÓÃ
*/
extern int set_tty(int fd, char *settings);
/**
* È«¾Ö±äÁ¿¶¨Òå
*/
struct sockaddr_in addr, remoteaddr;
int devfd;
int *remotefd;
char *machinename;
char *sttyparms;
char *sdevname;
char *linkname;
int sockfd = -1;
int port = 23000;
int debug = 0;
int isdaemon = 0;
int curConnects = 0;
int maxConnects = 1;
int writeonly;
fd_set fdsread, fdsreaduse;
struct hostent *remotehost;
char devbuf[RECVBUF_MODEM_MAX_LEN];
/**
* ¾Ö²¿º¯ÊýÉùÃ÷
*/
void zLogAgt_SigHandler(int sig);
int zLogAgt_connect_to(struct sockaddr_in *addr);
void usage(char *progname);
void link_slave(int fd);
/**
* @brief ÐźŴ¦Àíº¯Êý
* @param[in] sigÐźÅÖµ
* @return VOID
* @note
* @see
*/
void zLogAgt_SigHandler(int sig)
{
int i;
if (sockfd != -1)
close(sockfd);
for (i=0; i<curConnects; i++)
close(remotefd[i]);
if (devfd != -1)
close(devfd);
if (linkname)
unlink(linkname);
printf("Terminating on signal %d", sig);
exit(8);
}
void link_slave(int fd)
{
char *slavename;
int status = grantpt(devfd);
if (status != -1)
status = unlockpt(devfd);
if (status != -1) {
slavename = ptsname(devfd);
if (slavename) {
// Safety first
unlink(linkname);
status = symlink(slavename, linkname);
}
else
status = -1;
}
if (status == -1) {
printf( "Cannot create link for pseudo-tty: %m");
exit(9);
}
}
/**
* @brief socketÍøÂçͨÐÅ´¦ÀíÁ÷³Ì
* @param[in] addr
* @return socket Ì×½Ó×Ö
* @note
* @see
*/
int zLogAgt_connect_to(struct sockaddr_in *addr)
{
int waitlogged = 0;
int stat;
int sockfd;
extern int errno;
if (debug > 0) {
unsigned long ip = ntohl(addr->sin_addr.s_addr);
printf("Trying to connect to %d.%d.%d.%d",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
}
while (1) {
/* Open the socket for communications */
sockfd = socket(AF_INET, SOCK_STREAM, 6);
if (sockfd == -1) {
printf( "Can't open socket: %m");
exit(10);
}
/* Try to connect to the remote server,
if it fails, keep trying */
stat = connect(sockfd, (struct sockaddr*)addr,
sizeof(struct sockaddr_in));
if (debug>1)
if (stat == -1)
printf( "Connect status %d, errno %d: %m\n", stat,errno);
else
printf( "Connect status %d\n", stat);
if (stat == 0)
break;
/* Write a message to printf once */
if (!waitlogged) {
printf( "Waiting for server on %s port %d: %m", machinename, port);
waitlogged = 1;
}
close(sockfd);
sleep(10);
}
if (waitlogged || debug > 0)
printf("Connected to server %s port %d", machinename, port);
return sockfd;
}
/**
* main º¯Êý¶¨Òå
*/
/**
* @brief net <-> serial ģʽÖ÷´¦Àíº¯Êý
* @param[in] usb É豸Îļþ¾ä±ú
* @return Á÷³Ì´¦Àí½á¹û
* @note
* @see
*/
int zLogAgt_NetSerial_Main(int fd_usb)
{
int result;
extern char *optarg;
extern int optind;
int maxfd = -1;
int devbytes;
int remoteaddrlen;
int waitlogged = 0;
register int i;
PRINTF_DBG_INFO("Net and Serial Enter\n");
printf("sdevname=%s, port=%d, stty=%s\n",sdevname,port,sttyparms);//sdevname=/dev/ttyUSB0, port=23000, stty=921600 raw, optind=5
devfd = fd_usb;
signal(SIGINT, zLogAgt_SigHandler);
signal(SIGHUP, zLogAgt_SigHandler);
signal(SIGTERM, zLogAgt_SigHandler);
remotefd = (int *) malloc (maxConnects * sizeof(int));
openlog("remserial", LOG_PID, LOG_USER);
if (linkname)
link_slave(devfd);
/* remserial -r server-name -p 23000 -s "9600 raw" /dev/ttyS0 */
if (machinename) {
/* We are the client,
Find the IP address for the remote machine */
remotehost = gethostbyname(machinename);
if (!remotehost) {
printf("Couldn't determine address of %s\n", machinename);
exit(3);
}
/* Copy it into the addr structure */
addr.sin_family = AF_INET;
memcpy(&(addr.sin_addr), remotehost->h_addr_list[0],
sizeof(struct in_addr));
addr.sin_port = htons(port);
remotefd[curConnects++] = zLogAgt_connect_to(&addr);
}
else {
/* We are the server */
/* Open the initial socket for communications */
sockfd = socket(AF_INET, SOCK_STREAM, 6);
if (sockfd == -1) {
printf("Can't open socket: %m\n");
exit(4);
}
addr.sin_family = AF_INET;
//addr.sin_addr.s_addr = 0;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* Set up to listen on the given port */
if(bind(sockfd, (struct sockaddr*)(&addr),
sizeof(struct sockaddr_in)) < 0) {
printf("Couldn't bind port %d, aborting: %m",port);
exit(5);
}
if (debug > 1)
printf("Bound port\n");
/* Tell the system we want to listen on this socket */
result = listen(sockfd, 4);
if (result == -1) {
printf( "Socket listen failed: %m");
exit(6);
}
if (debug > 1)
printf("Done listen\n");
}
if (isdaemon) {
setsid();
close(0);
close(1);
close(2);
}
/* Set up the files/sockets for the select() call */
if (sockfd != -1) {
FD_SET(sockfd, &fdsread);
if (sockfd >= maxfd)
maxfd = sockfd + 1;
}
for (i = 0; i < curConnects; i++) {
FD_SET(remotefd[i], &fdsread);
if (remotefd[i] >= maxfd)
maxfd = remotefd[i] + 1;
}
if (!writeonly) {
FD_SET(devfd, &fdsread);
if (devfd >= maxfd)
maxfd = devfd + 1;
}
while (1) {
/* Wait for data from the listening socket, the device
or the remote connection */
fdsreaduse = fdsread;
if (select(maxfd, &fdsreaduse, NULL, NULL, NULL) == -1)
break;
/* Activity on the controlling socket, only on server */
if (!machinename && FD_ISSET(sockfd, &fdsreaduse)) {
int fd;
/* Accept the remote systems attachment */
remoteaddrlen = sizeof(struct sockaddr_in);
fd = accept(sockfd, (struct sockaddr*)(&remoteaddr), &remoteaddrlen);
if (fd == -1)
printf("accept failed: \n");
else if (curConnects < maxConnects) {
unsigned long ip;
remotefd[curConnects++] = fd;
/* Tell select to watch this new socket */
FD_SET(fd, &fdsread);
if ( fd >= maxfd )
maxfd = fd + 1;
ip = ntohl(remoteaddr.sin_addr.s_addr);
printf( "Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
}
else {
// Too many connections, just close it to reject
close(fd);
}
}
/* Data to read from the device */
if (FD_ISSET(devfd, &fdsreaduse)) {
devbytes = read(devfd, devbuf, RECVBUF_MODEM_MAX_LEN - 1);
if (debug > 1)
printf("Device: %d bytes\n", devbytes);
if (devbytes <= 0) {
if (debug > 0)
printf("%s closed\n", sdevname);
close(devfd);
FD_CLR(devfd, &fdsread);
while (1) {
devfd = open(sdevname, O_RDWR);
if (devfd != -1)
break;
printf("Open of %s failed: %m\n", sdevname);
if (errno != EIO)
exit(7);
sleep(1);
}
if (debug > 0)
printf("%s re-opened", sdevname);
if (sttyparms)
set_tty(devfd, sttyparms);
if (linkname)
link_slave(devfd);
FD_SET(devfd, &fdsread);
if (devfd >= maxfd)
maxfd = devfd + 1;
}
else
for (i = 0; i < curConnects; i++)
write(remotefd[i], devbuf, devbytes);
}
if (debug > 1)
printf("read Remotefd data start\n");
/* Data to read from the remote system */
for (i = 0; i < curConnects; i++)
if (FD_ISSET(remotefd[i], &fdsreaduse)) {
devbytes = read(remotefd[i], devbuf, RECVBUF_SOCK_CLIENT_LEN);
//if ( debug>1 && devbytes>0 )
if (debug > 1)
printf("Remote: %d bytes", devbytes);
if (devbytes == 0) {
register int j;
printf("Connection closed\n");
close(remotefd[i]);
FD_CLR(remotefd[i], &fdsread);
curConnects--;
for (j=i; j<curConnects; j++)
remotefd[j] = remotefd[j+1];
if (machinename) {
/* Wait for the server again */
remotefd[curConnects++] = zLogAgt_connect_to(&addr);
FD_SET(remotefd[curConnects-1], &fdsread);
if (remotefd[curConnects-1] >= maxfd)
maxfd = remotefd[curConnects-1] + 1;
}
}
else if (devfd != -1)
/* Write the data to the device */
write(devfd, devbuf, devbytes);
}
}
close(sockfd);
for (i=0; i<curConnects; i++)
close(remotefd[i]);
return 0;
}