blob: 6b641b2ad09dc357a3f587b2a8822939b686d57d [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
2 *
3 * Copyright (C) 2000 Paul Davis, pdavis@lpccomp.bc.ca
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * This program acts as a bridge either between a socket(2) and a
21 * serial/parallel port or between a socket and a pseudo-tty.
22 */
23#include "../zlog_com.h"
24
25/**
26 * ºê¶¨Òå
27 */
28#define RECVBUF_MODEM_MAX_LEN 2048
29#define RECVBUF_SOCK_CLIENT_LEN 512
30
31/**
32 * Íⲿ±äÁ¿ÒýÓÃ
33 */
34extern char* ptsname(int fd);
35
36/**
37 * Íⲿº¯ÊýÒýÓÃ
38 */
39extern int set_tty(int fd, char *settings);
40
41/**
42 * È«¾Ö±äÁ¿¶¨Òå
43 */
44struct sockaddr_in addr, remoteaddr;
45int devfd;
46int *remotefd;
47char *machinename;
48char *sttyparms;
49char *sdevname;
50char *linkname;
51int sockfd = -1;
52int port = 23000;
53int debug = 0;
54int isdaemon = 0;
55int curConnects = 0;
56int maxConnects = 1;
57int writeonly;
58
59fd_set fdsread, fdsreaduse;
60struct hostent *remotehost;
61char devbuf[RECVBUF_MODEM_MAX_LEN];
62
63/**
64 * ¾Ö²¿º¯ÊýÉùÃ÷
65 */
66void zLogAgt_SigHandler(int sig);
67int zLogAgt_connect_to(struct sockaddr_in *addr);
68void usage(char *progname);
69void link_slave(int fd);
70
71/**
72 * @brief ÐźŴ¦Àíº¯Êý
73 * @param[in] sigÐźÅÖµ
74 * @return VOID
75 * @note
76 * @see
77 */
78void zLogAgt_SigHandler(int sig)
79{
80 int i;
81
82 if (sockfd != -1)
83 close(sockfd);
84
85 for (i=0; i<curConnects; i++)
86 close(remotefd[i]);
87
88 if (devfd != -1)
89 close(devfd);
90
91 if (linkname)
92 unlink(linkname);
93
94 printf("Terminating on signal %d", sig);
95 exit(8);
96}
97
98void link_slave(int fd)
99{
100 char *slavename;
101 int status = grantpt(devfd);
102 if (status != -1)
103 status = unlockpt(devfd);
104 if (status != -1) {
105 slavename = ptsname(devfd);
106 if (slavename) {
107 // Safety first
108 unlink(linkname);
109 status = symlink(slavename, linkname);
110 }
111 else
112 status = -1;
113 }
114 if (status == -1) {
115 printf( "Cannot create link for pseudo-tty: %m");
116 exit(9);
117 }
118}
119
120/**
121 * @brief socketÍøÂçͨÐÅ´¦ÀíÁ÷³Ì
122 * @param[in] addr
123 * @return socket Ì×½Ó×Ö
124 * @note
125 * @see
126 */
127int zLogAgt_connect_to(struct sockaddr_in *addr)
128{
129 int waitlogged = 0;
130 int stat;
131 int sockfd;
132 extern int errno;
133
134 if (debug > 0) {
135 unsigned long ip = ntohl(addr->sin_addr.s_addr);
136 printf("Trying to connect to %d.%d.%d.%d",
137 (int)(ip>>24)&0xff,
138 (int)(ip>>16)&0xff,
139 (int)(ip>>8)&0xff,
140 (int)(ip>>0)&0xff);
141 }
142
143 while (1) {
144 /* Open the socket for communications */
145 sockfd = socket(AF_INET, SOCK_STREAM, 6);
146
147 if (sockfd == -1) {
148 printf( "Can't open socket: %m");
149 exit(10);
150 }
151
152 /* Try to connect to the remote server,
153 if it fails, keep trying */
154
155 stat = connect(sockfd, (struct sockaddr*)addr,
156 sizeof(struct sockaddr_in));
157 if (debug>1)
158 if (stat == -1)
159 printf( "Connect status %d, errno %d: %m\n", stat,errno);
160 else
161 printf( "Connect status %d\n", stat);
162
163 if (stat == 0)
164 break;
165 /* Write a message to printf once */
166 if (!waitlogged) {
167 printf( "Waiting for server on %s port %d: %m", machinename, port);
168 waitlogged = 1;
169 }
170 close(sockfd);
171 sleep(10);
172 }
173 if (waitlogged || debug > 0)
174 printf("Connected to server %s port %d", machinename, port);
175
176 return sockfd;
177}
178
179/**
180 * main º¯Êý¶¨Òå
181 */
182 /**
183 * @brief net <-> serial ģʽÖ÷´¦Àíº¯Êý
184 * @param[in] usb É豸Îļþ¾ä±ú
185 * @return Á÷³Ì´¦Àí½á¹û
186 * @note
187 * @see
188 */
189int zLogAgt_NetSerial_Main(int fd_usb)
190{
191 int result;
192 extern char *optarg;
193 extern int optind;
194 int maxfd = -1;
195 int devbytes;
196 int remoteaddrlen;
197 int waitlogged = 0;
198 register int i;
199
200 PRINTF_DBG_INFO("Net and Serial Enter\n");
201
202 printf("sdevname=%s, port=%d, stty=%s\n",sdevname,port,sttyparms);//sdevname=/dev/ttyUSB0, port=23000, stty=921600 raw, optind=5
203
204 devfd = fd_usb;
205
206 signal(SIGINT, zLogAgt_SigHandler);
207 signal(SIGHUP, zLogAgt_SigHandler);
208 signal(SIGTERM, zLogAgt_SigHandler);
209
210 remotefd = (int *) malloc (maxConnects * sizeof(int));
211 openlog("remserial", LOG_PID, LOG_USER);
212
213 if (linkname)
214 link_slave(devfd);
215
216 /* remserial -r server-name -p 23000 -s "9600 raw" /dev/ttyS0 */
217 if (machinename) {
218 /* We are the client,
219 Find the IP address for the remote machine */
220 remotehost = gethostbyname(machinename);
221 if (!remotehost) {
222 printf("Couldn't determine address of %s\n", machinename);
223 exit(3);
224 }
225
226 /* Copy it into the addr structure */
227 addr.sin_family = AF_INET;
228 memcpy(&(addr.sin_addr), remotehost->h_addr_list[0],
229 sizeof(struct in_addr));
230 addr.sin_port = htons(port);
231
232 remotefd[curConnects++] = zLogAgt_connect_to(&addr);
233 }
234 else {
235 /* We are the server */
236 /* Open the initial socket for communications */
237 sockfd = socket(AF_INET, SOCK_STREAM, 6);
238 if (sockfd == -1) {
239 printf("Can't open socket: %m\n");
240 exit(4);
241 }
242
243 addr.sin_family = AF_INET;
244 //addr.sin_addr.s_addr = 0;
245 addr.sin_port = htons(port);
246 addr.sin_addr.s_addr = htonl(INADDR_ANY);
247
248 /* Set up to listen on the given port */
249 if(bind(sockfd, (struct sockaddr*)(&addr),
250 sizeof(struct sockaddr_in)) < 0) {
251 printf("Couldn't bind port %d, aborting: %m",port);
252 exit(5);
253 }
254 if (debug > 1)
255 printf("Bound port\n");
256
257 /* Tell the system we want to listen on this socket */
258 result = listen(sockfd, 4);
259 if (result == -1) {
260 printf( "Socket listen failed: %m");
261 exit(6);
262 }
263
264 if (debug > 1)
265 printf("Done listen\n");
266 }
267
268 if (isdaemon) {
269 setsid();
270 close(0);
271 close(1);
272 close(2);
273 }
274
275 /* Set up the files/sockets for the select() call */
276 if (sockfd != -1) {
277 FD_SET(sockfd, &fdsread);
278 if (sockfd >= maxfd)
279 maxfd = sockfd + 1;
280 }
281
282 for (i = 0; i < curConnects; i++) {
283 FD_SET(remotefd[i], &fdsread);
284 if (remotefd[i] >= maxfd)
285 maxfd = remotefd[i] + 1;
286 }
287
288 if (!writeonly) {
289 FD_SET(devfd, &fdsread);
290 if (devfd >= maxfd)
291 maxfd = devfd + 1;
292 }
293
294 while (1) {
295 /* Wait for data from the listening socket, the device
296 or the remote connection */
297 fdsreaduse = fdsread;
298 if (select(maxfd, &fdsreaduse, NULL, NULL, NULL) == -1)
299 break;
300
301 /* Activity on the controlling socket, only on server */
302 if (!machinename && FD_ISSET(sockfd, &fdsreaduse)) {
303 int fd;
304
305 /* Accept the remote systems attachment */
306 remoteaddrlen = sizeof(struct sockaddr_in);
307 fd = accept(sockfd, (struct sockaddr*)(&remoteaddr), &remoteaddrlen);
308
309 if (fd == -1)
310 printf("accept failed: \n");
311 else if (curConnects < maxConnects) {
312 unsigned long ip;
313 remotefd[curConnects++] = fd;
314 /* Tell select to watch this new socket */
315 FD_SET(fd, &fdsread);
316 if ( fd >= maxfd )
317 maxfd = fd + 1;
318 ip = ntohl(remoteaddr.sin_addr.s_addr);
319 printf( "Connection from %d.%d.%d.%d\n",
320 (int)(ip>>24)&0xff,
321 (int)(ip>>16)&0xff,
322 (int)(ip>>8)&0xff,
323 (int)(ip>>0)&0xff);
324 }
325 else {
326 // Too many connections, just close it to reject
327 close(fd);
328 }
329 }
330
331 /* Data to read from the device */
332 if (FD_ISSET(devfd, &fdsreaduse)) {
333 devbytes = read(devfd, devbuf, RECVBUF_MODEM_MAX_LEN - 1);
334
335 if (debug > 1)
336 printf("Device: %d bytes\n", devbytes);
337 if (devbytes <= 0) {
338 if (debug > 0)
339 printf("%s closed\n", sdevname);
340 close(devfd);
341 FD_CLR(devfd, &fdsread);
342 while (1) {
343 devfd = open(sdevname, O_RDWR);
344 if (devfd != -1)
345 break;
346 printf("Open of %s failed: %m\n", sdevname);
347 if (errno != EIO)
348 exit(7);
349 sleep(1);
350 }
351 if (debug > 0)
352 printf("%s re-opened", sdevname);
353 if (sttyparms)
354 set_tty(devfd, sttyparms);
355 if (linkname)
356 link_slave(devfd);
357 FD_SET(devfd, &fdsread);
358 if (devfd >= maxfd)
359 maxfd = devfd + 1;
360 }
361 else
362 for (i = 0; i < curConnects; i++)
363 write(remotefd[i], devbuf, devbytes);
364 }
365
366 if (debug > 1)
367 printf("read Remotefd data start\n");
368 /* Data to read from the remote system */
369 for (i = 0; i < curConnects; i++)
370 if (FD_ISSET(remotefd[i], &fdsreaduse)) {
371 devbytes = read(remotefd[i], devbuf, RECVBUF_SOCK_CLIENT_LEN);
372 //if ( debug>1 && devbytes>0 )
373 if (debug > 1)
374 printf("Remote: %d bytes", devbytes);
375
376 if (devbytes == 0) {
377 register int j;
378 printf("Connection closed\n");
379 close(remotefd[i]);
380 FD_CLR(remotefd[i], &fdsread);
381 curConnects--;
382
383 for (j=i; j<curConnects; j++)
384 remotefd[j] = remotefd[j+1];
385
386 if (machinename) {
387 /* Wait for the server again */
388 remotefd[curConnects++] = zLogAgt_connect_to(&addr);
389 FD_SET(remotefd[curConnects-1], &fdsread);
390 if (remotefd[curConnects-1] >= maxfd)
391 maxfd = remotefd[curConnects-1] + 1;
392 }
393 }
394 else if (devfd != -1)
395 /* Write the data to the device */
396 write(devfd, devbuf, devbytes);
397 }
398 }
399 close(sockfd);
400 for (i=0; i<curConnects; i++)
401 close(remotefd[i]);
402
403 return 0;
404}
405