source: ntrip/trunk/ntripserver/NtripLinuxServer.c@ 15

Last change on this file since 15 was 15, checked in by stoecker, 19 years ago

minor fix

File size: 16.2 KB
Line 
1/*
2 * main.c
3 *
4 * Copyright (c) 2003...2005
5 * German Federal Agency for Cartography and Geodesy (BKG)
6 *
7 * Developed for Networked Transport of RTCM via Internet Protocol (NTRIP)
8 * for streaming GNSS data over the Internet.
9 *
10 * Designed by Informatik Centrum Dortmund http://www.icd.de
11 *
12 * NTRIP is currently an experimental technology.
13 * The BKG disclaims any liability nor responsibility to any person or
14 * entity with respect to any loss or damage caused, or alleged to be
15 * caused, directly or indirectly by the use and application of the NTRIP
16 * technology.
17 *
18 * For latest information and updates, access:
19 * http://igs.ifag.de/index_ntrip.htm
20 *
21 * Georg Weber
22 * BKG, Frankfurt, Germany, June 2003-06-13
23 * E-mail: euref-ip@bkg.bund.de
24 *
25 * Based on the GNU General Public License published nmead
26 *
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version 2
30 * of the License, or (at your option) any later version.
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
40 * USA.
41 */
42
43/* $Id: NtripLinuxServer.c,v 1.6 2005/02/16 15:23:36 stoecker Exp $
44 * Changes - Version 0.7
45 * Thu Sep 22 08:10:45 2003 actina AG <http://www.actina.de>
46 *
47 * Steffen Tschirpke <St.Tschirpke@actina.de>
48 * * main.c
49 * - socket support
50 * - command line option handling
51 * - error handling
52 * - help screen
53 */
54
55/* Changes - Version 0.9
56 * Feb 15 2005 Dirk Stoecker <soft@dstoecker.de>
57 */
58
59#include <stdio.h>
60#include <string.h>
61#include <unistd.h>
62#include <stdlib.h>
63#include <sys/types.h>
64#include <sys/socket.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <netdb.h>
68#include <getopt.h>
69#include <sys/termios.h>
70#include <fcntl.h>
71#include "NtripServerLinux.h"
72
73#define VERSION "NTRIP NtripServerLinux/0.9"
74
75#define SIMULATE 0
76#define SERIAL 1
77#define TCPSOCKET 2
78
79/* default socket source */
80#define SERV_HOST_ADDR "127.0.0.1"
81#define SERV_TCP_PORT 1025
82
83/* default destination */
84#define NTRIP_CASTER "www.euref-ip.net"
85#define NTRIP_PORT 80
86
87int verbose = 0;
88int simulate = 0;
89int tickinterval = 1;
90int ttybaud = 19200;
91char * ttyport = "/dev/gps";
92int mode = 0;
93
94/* Forward references */
95int openserial (u_char * tty, int blocksz, int ttybaud);
96int send_receive_loop(int socket, int fd);
97void usage (int);
98
99/*
100* main
101*
102* Main entry point for the program. Processes command-line arguments and
103* prepares for action.
104*
105* Parameters:
106* argc : integer : Number of command-line arguments.
107* argv : array of char : Command-line arguments as an array of zero-terminated
108* pointers to strings.
109*
110* Return Value:
111* The function does not return a value (although its return type is int).
112*
113* Remarks:
114*
115*/
116
117int main (int argc, char ** argv)
118{
119 u_char * ttyin = ttyport;
120 char * logfilepath = NULL;
121 FILE * fp = NULL;
122 int c, gpsfd = -1;
123 int size = 2048; //for setting send buffer size
124
125 unsigned int out_port = 0;
126 unsigned int in_port = 0;
127 char *mountpoint = NULL;
128 char *password = NULL;
129 int sock_id;
130 char szSendBuffer[BUFSZ];
131 int nBufferBytes;
132 int sockfd;
133
134 struct hostent *inhost;
135 struct hostent *outhost;
136
137 struct sockaddr_in in_addr;
138 struct sockaddr_in out_addr;
139
140 //get and check program arguments
141 if (argc <=1)
142 {
143 usage(2);
144 exit(1);
145 }
146 while ((c = getopt (argc, argv, "M:i:h:b:p:s:a:m:c:H:P:")) != EOF)
147 {
148 switch (c)
149 {
150 case 'M':
151 mode = atoi(optarg);
152 if ((mode == 0) || (mode > 3))
153 {
154 fprintf (stderr, "can't convert %s to a valid mode\n\n", optarg);
155 usage(-1);
156 }
157 break;
158 case 'i': /* gps serial ttyin */
159 ttyin = optarg;
160 break;
161 case 'b': /* serial ttyin speed */
162 ttybaud = atoi (optarg);
163 if (ttybaud <= 1)
164 {
165 fprintf (stderr, "can't convert %s to valid ttyin speed\n\n", optarg);
166 usage(1);
167 }
168 break;
169 case 'a': /* http server IP address A.B.C.D*/
170 outhost = gethostbyname(optarg);
171 if (outhost == NULL)
172 {
173 fprintf (stderr, "host %s unknown\n\n", optarg);
174 usage(-2);
175 }
176 memset((char *) &out_addr, 0x00, sizeof(out_addr));
177 memcpy(&out_addr.sin_addr, outhost->h_addr, outhost->h_length);
178 break;
179 case 'p': /* http server port*/
180 out_port = atoi(optarg);
181 if (out_port <= 1)
182 {
183 fprintf (stderr, "can't convert %s to a valid http server port\n\n", optarg);
184 usage(1);
185 }
186 break;
187 case 'm': /* http server mountpoint*/
188 mountpoint = optarg;
189 break;
190 case 's': /* simulate datastream from file */
191 logfilepath = optarg;
192 break;
193 case 'c': /* password */
194 password=optarg;
195 break;
196 case 'H': /* host */
197 inhost = gethostbyname(optarg);
198 if (inhost == NULL)
199 {
200 /* TODO Errorhandling/Debugging - Output */
201 fprintf (stderr, "host %s unknown\n\n", optarg);
202 usage(-2);
203 }
204 memset((char *) &in_addr, 0x00, sizeof(in_addr));
205 memcpy(&in_addr.sin_addr, inhost->h_addr, inhost->h_length);
206 break;
207 case 'P': /* port */
208 in_port = atoi(optarg);
209 if (in_port <= 1)
210 {
211 /* TODO Errorhandling/Debugging - Output */
212 fprintf (stderr, "can't convert %s to a valid receiver port\n\n", optarg);
213 usage(1);
214 }
215 break;
216 case 'h': /* help */
217 case '?':
218 usage(0);
219 break;
220 default:
221 usage(2);
222 break;
223 }
224
225 if (in_port <= 0 )
226 {
227 in_port = SERV_TCP_PORT;
228 }
229 if (out_port <= 0 )
230 {
231 out_port = NTRIP_PORT;
232 }
233 }
234
235 argc -= optind;
236 argv += optind;
237
238 if (argc > 0)
239 {
240 /* TODO Errorhandling/Debugging - Output */
241 fprintf (stderr, "Extra args on command line.\n");
242 for (; argc > 0; argc--)
243 {
244 fprintf (stderr, " %s", *argv++);
245 }
246 fprintf (stderr, "\n");
247 usage (1); /* never returns */
248 }
249
250 if ((mode ==SIMULATE) && (tickinterval <= 0))
251 {
252 /* TODO Errorhandling/Debugging - Output */
253 fprintf (stderr, "-t parameter must be positive in simulator mode\n");
254 exit (1);
255 }
256
257 if (verbose >= 1)
258 fprintf (stderr, "%s\n", VERSION);
259 if (mountpoint == NULL)
260 {
261 /* TODO Errorhandling/Debugging - Output */
262 fprintf(stderr,"missing mountpoint arguement\n");
263 exit(1);
264 }
265 //print program arguments on screen
266 /* TODO Errorhandling/Debugging - Output */
267 // printf("\ncaster IP :\t%s\nport :\t%d\nmountpoint :\t%s\npassword :\t%s\n\n",address,port,mountpoint,(password==NULL)?"none":"yes");
268 if (password == NULL)
269 {
270 password="\0";
271 }
272
273 switch (mode)
274 {
275 case SIMULATE:
276 {
277 fp = fopen (logfilepath, "r");
278 if (!fp)
279 {
280 /* TODO Errorhandling/Debugging - Output */
281 perror ("fopen logfile");
282 exit (1);
283 }
284 }
285 break;
286 case SERIAL: //open serial port
287 {
288 gpsfd = openserial (ttyin, 1, ttybaud);
289 fp = fdopen (gpsfd, "r");
290 if (!fp)
291 {
292 /* TODO Errorhandling/Debugging - Output */
293 perror ("fdopen gps");
294 exit (1);
295 }
296 }
297 break;
298 case TCPSOCKET:
299 {
300 in_addr.sin_family = AF_INET;
301 in_addr.sin_port = htons(in_port);
302
303 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
304 {
305 /* TODO Errorhandling/Debugging - Output */
306 fprintf (stderr, "can't create socket\n");
307 exit(1);
308 }
309
310 /* TODO Errorhandling/Debugging - Output */
311 printf("connecting input ...\n");
312 fprintf (stderr, "socket input:\n");
313 fprintf (stderr, "\tHost: %s\n", inet_ntoa(in_addr.sin_addr));
314 fprintf (stderr, "\tPort: %d\n", in_port);
315
316 if (connect(sockfd, (struct sockaddr *) &in_addr, sizeof(in_addr)) < 0)
317 {
318 /* TODO Errorhandling/Debugging - Output */
319 fprintf (stderr, "can't connect input to %s at port %d\n", inet_ntoa(in_addr.sin_addr), in_port);
320 // exit(1);
321 }
322 gpsfd = sockfd;
323 }
324 break;
325 default:
326 usage(-1);
327 break;
328 }
329
330 out_addr.sin_family = AF_INET;
331 out_addr.sin_port = htons((u_short)(out_port));
332
333 // ----- main part -----
334 while(1)
335 {
336 //create socket
337 if ((sock_id = socket(AF_INET, SOCK_STREAM, 0)) < 0)
338 {
339 /* TODO Errorhandling/Debugging - Output */
340 printf("ERROR : could not create socket\n");
341 // sleep(5);
342 exit(2);
343 }
344 //connect to caster
345 printf("connecting output ...\n");
346 fprintf (stderr, "caster output:\n");
347 fprintf (stderr, "\tHost: %s\n", inet_ntoa(out_addr.sin_addr));
348 fprintf (stderr, "\tPort: %d\n", out_port);
349 if (connect(sock_id, (struct sockaddr *) &out_addr, sizeof(out_addr)) < 0)
350 {
351 /* TODO Errorhandling/Debugging - Output */
352 fprintf (stderr, "can't connect output to %s at port %d\n", inet_ntoa(out_addr.sin_addr), out_port);
353 close(sock_id);
354 // sleep(5);
355 exit(3);
356 }
357
358 /* TODO Errorhandling/Debugging - Output */
359 printf("connection succesfull\n");
360 //set socket buffer size
361 setsockopt(sock_id,SOL_SOCKET,SO_SNDBUF,(const char *) &size,sizeof(const char *));
362 //send message to caster
363 szSendBuffer[0] = '\0';
364 sprintf(szSendBuffer,"SOURCE %s /%s\r\n",password,mountpoint);
365 strcat(szSendBuffer,"Source-Agent: ");
366 strcat(szSendBuffer,VERSION);
367 strcat(szSendBuffer, "\r\n");
368 strcat(szSendBuffer, "\r\n");
369 strcat(szSendBuffer, "\0");
370 nBufferBytes=strlen(szSendBuffer);
371 if ((send(sock_id, szSendBuffer, nBufferBytes, 0)) != nBufferBytes)
372 {
373 /* TODO Errorhandling/Debugging - Output */
374 fprintf(stderr, "ERROR : could not send to caster\n");
375 close(sock_id);
376 sleep(5);
377 exit(0);
378 }
379 //check caster's response
380 nBufferBytes=recv(sock_id,szSendBuffer,sizeof(szSendBuffer),0);
381 szSendBuffer[nBufferBytes]='\0';
382 if(strcmp(szSendBuffer,"OK\r\n"))
383 {
384 /* TODO Errorhandling/Debugging - Output */
385 fprintf(stderr,"caster's reply is not OK\n");
386 close(sock_id);
387 sleep(5);
388 exit(0);
389 }
390 send_receive_loop(sock_id, gpsfd);
391 }
392 exit(0);
393}
394
395int send_receive_loop(int socket, int fd)
396{
397 char buffer[BUFSZ]={0};
398 int nBufferBytes=0;
399 //data transmission
400 printf("transfering data ...\n");
401 while(1)
402 {
403 // recieving data
404 nBufferBytes = read(fd, buffer, BUFSZ);
405 if (nBufferBytes<=0)
406 {
407 /* TODO Errorhandling/Debugging - Output */
408 printf("ERROR : no data recieved from serial port or socket\n");
409 }
410 // send data
411 if((send(socket, buffer, nBufferBytes, MSG_DONTWAIT)) != nBufferBytes)
412 { //MSG_DONTWAIT : send works in non-blocking mode
413 /* TODO Errorhandling/Debugging - Output */
414 fprintf(stderr,"ERROR : could not send data\n");
415 close(socket);
416 sleep(5);
417 exit(4);
418 }
419 }
420}
421
422/*
423 * openserial
424 *
425 * Open the serial port with the given device name and configure it for
426 * reading NMEA data from a GPS receiver.
427 *
428 * Parameters:
429 * tty : pointer to : A zero-terminated string containing the device
430 * unsigned char name of the appropriate serial port.
431 * blocksz : integer : Block size for port I/O
432 * ttybaud : integer : Baud rate for port I/O
433 *
434 * Return Value:
435 * The function returns a file descriptor for the opened port if successful.
436 * The function returns -1 in the event of an error.
437 *
438 * Remarks:
439 *
440 */
441
442int openserial (u_char * tty, int blocksz, int ttybaud)
443{
444 int fd;
445 struct termios termios;
446
447 fd = open(tty, O_RDWR | O_NONBLOCK
448#ifdef O_EXLOCK /* for Linux */
449 | O_EXLOCK
450#endif
451 );
452 if (fd < 0) {
453 perror("open");
454 return (-1);
455 }
456 if (tcgetattr(fd, &termios) < 0) {
457
458 perror("tcgetattr");
459 return (-1);
460 }
461 termios.c_iflag = 0;
462 termios.c_oflag = 0; /* (ONLRET) */
463 termios.c_cflag = CS8 | CLOCAL | CREAD;
464 termios.c_lflag = 0;
465 {
466 int cnt;
467 for (cnt = 0; cnt < NCCS; cnt++)
468 termios.c_cc[cnt] = -1;
469 }
470 termios.c_cc[VMIN] = blocksz;
471 termios.c_cc[VTIME] = 2;
472
473#if (B4800 != 4800)
474 /*
475 * Not every system has speed settings equal to absolute speed value.
476 */
477
478 switch (ttybaud)
479 {
480 case 300:
481 ttybaud = B300;
482 break;
483 case 1200:
484 ttybaud = B1200;
485 break;
486 case 2400:
487 ttybaud = B2400;
488 break;
489 case 4800:
490 ttybaud = B4800;
491 break;
492 case 9600:
493 ttybaud = B9600;
494 break;
495 case 19200:
496 ttybaud = B19200;
497 break;
498 case 38400:
499 ttybaud = B38400;
500 break;
501#ifdef B57600
502 case 57600:
503 ttybaud = B57600;
504 break;
505#endif
506#ifdef B115200
507 case 115200:
508 ttybaud = B115200;
509 break;
510#endif
511#ifdef B230400
512 case 230400:
513 ttybaud = B230400;
514 break;
515#endif
516 default:
517 fprintf(stderr, "Baud settings not useful, using 19200\n");
518 ttybaud = B19200;
519 break;
520 }
521#endif
522
523 if (cfsetispeed(&termios, ttybaud) != 0)
524 {
525 perror("cfsetispeed");
526 return (-1);
527 }
528 if (cfsetospeed(&termios, ttybaud) != 0)
529 {
530 perror("cfsetospeed");
531 return (-1);
532 }
533 if (tcsetattr(fd, TCSANOW, &termios) < 0)
534 {
535 perror("tcsetattr");
536 return (-1);
537 }
538#if 1 /* WANT_BLOCKING_READ */
539 if (fcntl(fd, F_SETFL, 0) == -1)
540 {
541 perror("fcntl: set nonblock");
542 }
543#endif
544 return (fd);
545}
546
547/*
548 * usage
549 *
550 * Send a usage message to standard error and quit the program.
551 *
552 * Parameters:
553 * None.
554 *
555 * Return Value:
556 * The function does not return a value.
557 *
558 * Remarks:
559 *
560 */
561
562void usage (int rc)
563{
564 fprintf (stderr, "%s: application\n",VERSION);
565 fprintf (stderr, "Usage: %s [OPTIONS]\n",VERSION);
566 fprintf (stderr, " Options are:\n");
567 fprintf (stderr, " -a caster name or address (default: %s)\n", NTRIP_CASTER);
568 fprintf (stderr, " -p caster port (default: %d)\n", NTRIP_PORT);
569 fprintf (stderr, " -m caster mountpoint\n");
570 fprintf (stderr, " -c password for caster login\n");
571 fprintf (stderr, " -h|? print this help screen\n");
572 fprintf (stderr, " -M <mode> sets the mode\n");
573 fprintf (stderr, " (1=serial, 2=tcpsocket, 3=simulate)\n");
574 fprintf (stderr, " Mode = simulate:\n");
575 fprintf (stderr, " -s file, simulate data stream by reading log file\n");
576 fprintf (stderr, " default/current setting is %s\n", (simulate ? "enabled" : "disabled"));
577 fprintf (stderr, " Mode = serial:\n");
578 fprintf (stderr, " -b baud_rate, sets serial input baud rate\n");
579 fprintf (stderr, " default/current value is %d\n", ttybaud);
580 fprintf (stderr, " -i input_device, sets name of serial input device\n");
581 fprintf (stderr, " default/current value is %s\n", ttyport);
582 fprintf (stderr, " (normally a symbolic link to /dev/tty\?\?)\n");
583 fprintf (stderr, " Mode = tcpsocket:\n");
584 fprintf (stderr, " -P receiver port (default: 1025)\n");
585 fprintf (stderr, " -H hostname of TCP server (default: 127.0.0.1)\n");
586 fprintf (stderr, " \n");
587 exit (rc);
588}
Note: See TracBrowser for help on using the repository browser.