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

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

removed spaces

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