28#include "mrtklib/mrtk_version.h"
37#define CRTSCTS 020000000000
42#include <netinet/in.h>
43#include <netinet/tcp.h>
44#include <sys/socket.h>
53#define SERIBUFFSIZE 4096
54#define TIMETAGH_LEN 64
57#define DEFAULT_MEMBUF_SIZE 4096
59#define NTRIP_AGENT MRTKLIB_SOFTNAME "/" MRTKLIB_VERSION_STRING
60#define NTRIP_CLI_PORT 2101
61#define NTRIP_SVR_PORT 80
62#define NTRIP_MAXRSP 32768
63#define NTRIP_MAXSTR 256
64#define NTRIP_RSP_OK_CLI "ICY 200 OK\r\n"
65#define NTRIP_RSP_OK_SVR "OK\r\n"
66#define NTRIP_RSP_SRCTBL "SOURCETABLE 200 OK\r\n"
67#define NTRIP_RSP_TBLEND "ENDSOURCETABLE"
68#define NTRIP_RSP_HTTP "HTTP/"
69#define NTRIP_RSP_ERROR "ERROR"
70#define NTRIP_RSP_UNAUTH "HTTP/1.0 401 Unauthorized\r\n"
71#define NTRIP_RSP_ERR_PWD "ERROR - Bad Password\r\n"
72#define NTRIP_RSP_ERR_MNTP "ERROR - Bad Mountpoint\r\n"
77#define MIN(x, y) ((x) < (y) ? (x) : (y))
105#define closesocket close
251 const int br[] = {300,
271 const int nbr = (int)(
sizeof(br) /
sizeof(br[0]));
273 int i, brate = 9600, bsize = 8, stopb = 1, tcp_port = 0;
274 char *p, parity =
'N', dev[128], port[128], fctr[64] =
"", path_tcp[32], msg_tcp[128];
275 const speed_t bs[] = {B300,
295 struct termios ios = {0};
297 tracet(NULL, 3,
"openserial: path=%s mode=%d\n", path, mode);
303 if ((p = strchr(path,
':'))) {
304 strncpy(port, path, p - path);
305 port[p - path] =
'\0';
306 sscanf(p,
":%d:%d:%c:%d:%s", &brate, &bsize, &parity, &stopb, fctr);
311 if ((p = strchr(path,
'#'))) {
312 sscanf(p,
"#%d", &tcp_port);
314 for (i = 0; i < nbr; i++) {
315 if (br[i] == brate) {
320 sprintf(msg,
"bitrate error (%d)", brate);
321 tracet(NULL, 1,
"openserial: %s path=%s\n", msg, path);
325 parity = (char)toupper((
int)parity);
327 sprintf(dev,
"/dev/%.*s", (
int)
sizeof(port) - 6, port);
337 if ((serial->
dev = open(dev, rw | O_NOCTTY | O_NONBLOCK)) < 0) {
338 sprintf(msg,
"%s open error (%d)", dev, errno);
339 tracet(NULL, 1,
"openserial: %s dev=%s\n", msg, dev);
343 tcgetattr(serial->
dev, &ios);
349 cfsetospeed(&ios, bs[i]);
350 cfsetispeed(&ios, bs[i]);
351 ios.c_cflag |= bsize == 7 ? CS7 : CS8;
353 ios.c_cflag |= (PARENB | PARODD);
354 }
else if (parity ==
'E') {
355 ios.c_cflag |= PARENB;
357 ios.c_cflag |= stopb == 2 ? CSTOPB : 0;
358 ios.c_cflag |= !strcmp(fctr,
"rts") ?
CRTSCTS : 0;
359 tcsetattr(serial->
dev, TCSANOW, &ios);
360 tcflush(serial->
dev, TCIOFLUSH);
361 sprintf(msg,
"%s", dev);
366 sprintf(path_tcp,
":%d", tcp_port);
369 tracet(NULL, 3,
"openserial: dev=%d\n", serial->
dev);
374 tracet(NULL, 3,
"closeserial: dev=%d\n", serial->
dev);
389 tracet(NULL, 4,
"readserial: dev=%d n=%d\n", serial->
dev, n);
393 if ((nr = read(serial->
dev, buff, n)) < 0) {
396 tracet(NULL, 5,
"readserial: exit dev=%d nr=%d\n", serial->
dev, nr);
399 if (serial->
tcpsvr && nr > 0) {
411 tracet(NULL, 3,
"writeserial: dev=%d n=%d\n", serial->
dev, n);
415 if ((ns = (
int)write(serial->
dev, buff, n)) < 0) {
416 if (errno != EAGAIN && errno != EWOULDBLOCK) {
421 tracet(NULL, 5,
"writeserial: exit dev=%d ns=%d\n", serial->
dev, ns);
429 int state = !serial ? 0 : (serial->
error ? -1 : 2);
431 p += sprintf(p,
"serial:\n");
432 p += sprintf(p,
" state = %d\n", state);
436 p += sprintf(p,
" dev = %d\n", serial->
dev);
437 p += sprintf(p,
" error = %d\n", serial->
error);
473 if (!(file->
fp = fopen(file->
openpath, rw))) {
474 sprintf(msg,
"file open error: %s", file->
openpath);
475 tracet(NULL, 1,
"openfile: %s\n", msg);
478 tracet(NULL, 4,
"openfile_: open file %s (%s)\n", file->
openpath, rw);
480 sprintf(tagpath,
"%s.tag", file->
openpath);
484 if (!(file->
fp_tag = fopen(tagpath, rw))) {
485 sprintf(msg,
"tag open error: %s", tagpath);
486 tracet(NULL, 1,
"openfile: %s\n", msg);
490 tracet(NULL, 4,
"openfile_: open tag file %s (%s)\n", tagpath, rw);
494 fread(&time_time,
sizeof(time_time), 1, file->
fp_tag) == 1 &&
495 fread(&time_sec,
sizeof(time_sec), 1, file->
fp_tag) == 1) {
497 file->
time.
time = (time_t)time_time;
506 sprintf(tagh,
"TIMETAG %s %s", MRTKLIB_SOFTNAME, MRTKLIB_VERSION_STRING);
508 time_time = (uint32_t)file->
time.
time;
511 fwrite(&time_time, 1,
sizeof(time_time), file->
fp_tag);
512 fwrite(&time_sec, 1,
sizeof(time_sec), file->
fp_tag);
519 if ((fp = fopen(tagpath,
"rb"))) {
528 tracet(NULL, 3,
"closefile_: path=%s\n", file->
path);
551 double speed = 1.0, start = 0.0, swapintv = 0.0;
553 int timetag = 0, size_fpos = 4;
555 tracet(NULL, 3,
"openfile: path=%s mode=%d\n", path, mode);
562 for (p = (
char*)path; (p = strstr(p,
"::")); p += 2) {
563 if (*(p + 2) ==
'T') {
565 }
else if (*(p + 2) ==
'+') {
566 sscanf(p + 2,
"+%lf", &start);
567 }
else if (*(p + 2) ==
'x') {
568 sscanf(p + 2,
"x%lf", &speed);
569 }
else if (*(p + 2) ==
'S') {
570 sscanf(p + 2,
"S=%lf", &swapintv);
571 }
else if (*(p + 2) ==
'P') {
572 sscanf(p + 2,
"P=%d", &size_fpos);
578 if (swapintv <= 0.0) {
587 strcpy(file->
path, path);
588 if ((p = strstr(file->
path,
"::"))) {
615 tracet(NULL, 3,
"closefile: fp=%d\n", file->
fp);
637 if (!strcmp(openpath, file->
openpath)) {
638 tracet(NULL, 2,
"swapfile: no need to swap %s\n", openpath);
650 tracet(NULL, 3,
"swapclose: fp_tmp=%d\n", file->
fp_tmp);
664 char *p = msg, tstr1[32], tstr2[32];
665 int state = file ? 2 : 0;
667 p += sprintf(p,
"file:\n");
668 p += sprintf(p,
" state = %d\n", state);
674 p += sprintf(p,
" path = %s\n", file->
path);
675 p += sprintf(p,
" openpath= %s\n", file->
openpath);
676 p += sprintf(p,
" mode = %d\n", file->
mode);
677 p += sprintf(p,
" timetag = %d\n", file->
timetag);
678 p += sprintf(p,
" repmode = %d\n", file->
repmode);
679 p += sprintf(p,
" offsete = %d\n", file->
offset);
680 p += sprintf(p,
" time = %s\n", tstr1);
681 p += sprintf(p,
" wtime = %s\n", tstr2);
682 p += sprintf(p,
" tick = %u\n", file->
tick);
683 p += sprintf(p,
" tick_f = %u\n", file->
tick_f);
684 p += sprintf(p,
" start = %.3f\n", file->
start);
685 p += sprintf(p,
" speed = %.3f\n", file->
speed);
686 p += sprintf(p,
" swapintv= %.3f\n", file->
swapintv);
691 struct timeval tv = {0};
694 uint32_t t, tick, fpos_4B;
698 tracet(NULL, 4,
"readfile: fp=%d nmax=%d\n", file->
fp, nmax);
704 if (file->
fp == stdin) {
708 if (!select(1, &rs, NULL, NULL, &tv)) {
711 if ((nr = (
int)read(0, buff, nmax)) < 0) {
725 while ((
int)(file->
tick_n - t) <= 0) {
726 if (fread(&file->
tick_n,
sizeof(tick), 1, file->
fp_tag) < 1 ||
729 file->
tick_n = (uint32_t)(-1);
730 pos = ftell(file->
fp);
731 fseek(file->
fp, 0L, SEEK_END);
733 fseek(file->
fp, pos, SEEK_SET);
738 if (file->
tick_n == (uint32_t)(-1)) {
741 sprintf(msg,
"T%+.1fs", (
int)t * 0.001);
745 if ((n = file->
fpos_n - ftell(file->
fp)) < nmax) {
750 nr = (int)fread(buff, 1, nmax, file->
fp);
752 if (feof(file->
fp)) {
755 tracet(NULL, 5,
"readfile: fp=%d nr=%d\n", file->
fp, nr);
762 uint32_t tick =
tickget(), fpos_4B;
763 int week1, week2, ns;
764 double tow1, tow2, intv;
765 long fpos, fpos_tmp = 0;
767 tracet(NULL, 4,
"writefile: fp=%d n=%d\n", file->
fp, n);
780 tow2 += 604800.0 * (week2 - week1);
795 ns = (int)fwrite(buff, 1, n, file->
fp);
796 fpos = ftell(file->
fp);
801 fwrite(buff, 1, n, file->
fp_tmp);
802 fpos_tmp = ftell(file->
fp_tmp);
807 fwrite(&tick, 1,
sizeof(tick), file->
fp_tag);
809 fpos_4B = (uint32_t)fpos;
810 fwrite(&fpos_4B, 1,
sizeof(fpos_4B), file->
fp_tag);
812 fpos_8B = (uint64_t)fpos;
813 fwrite(&fpos_8B, 1,
sizeof(fpos_8B), file->
fp_tag);
818 fwrite(&tick, 1,
sizeof(tick), file->
fp_tag_tmp);
820 fpos_4B = (uint32_t)fpos_tmp;
821 fwrite(&fpos_4B, 1,
sizeof(fpos_4B), file->
fp_tag_tmp);
823 fpos_8B = (uint64_t)fpos_tmp;
824 fwrite(&fpos_8B, 1,
sizeof(fpos_8B), file->
fp_tag_tmp);
829 tracet(NULL, 5,
"writefile: fp=%d ns=%d tick=%5d fpos=%d\n", file->
fp, ns, tick, fpos);
844 char *src = str, *dst = str;
846 if (*src ==
'%' && src[1] && src[2]) {
847 int hi = src[1], lo = src[2];
848 hi = (hi >=
'0' && hi <=
'9') ? hi -
'0'
849 : (hi >=
'A' && hi <=
'F') ? hi -
'A' + 10
850 : (hi >=
'a' && hi <=
'f') ? hi -
'a' + 10
852 lo = (lo >=
'0' && lo <=
'9') ? lo -
'0'
853 : (lo >=
'A' && lo <=
'F') ? lo -
'A' + 10
854 : (lo >=
'a' && lo <=
'f') ? lo -
'a' + 10
856 if (hi >= 0 && lo >= 0) {
857 char ch = (char)((hi << 4) | lo);
858 if (ch ==
'\0' || ch ==
'\r' || ch ==
'\n' || ch ==
' ') {
874static void decodetcppath(
const char* path,
char* addr,
char* port,
char* user,
char* passwd,
char* mntpnt,
char* str) {
877 tracet(NULL, 4,
"decodetcpepath: path=%s\n", path);
897 if (!(p = strrchr(buff,
'@'))) {
901 if ((p = strchr(p,
'/'))) {
902 if ((q = strchr(p + 1,
':'))) {
910 sprintf(mntpnt,
"%.255s", p + 1);
913 if ((p = strrchr(buff,
'@'))) {
915 if ((q = strchr(buff,
':'))) {
918 sprintf(passwd,
"%.255s", q + 1);
922 sprintf(user,
"%.255s", buff);
932 if ((q = strchr(p,
':'))) {
935 sprintf(port,
"%.255s", q + 1);
939 sprintf(addr,
"%.255s", p);
948 struct timeval tv = {0};
949 tracet(NULL, 3,
"setsock: sock=%d\n", sock);
951 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (
const char*)&tv,
sizeof(tv)) == -1 ||
952 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (
const char*)&tv,
sizeof(tv)) == -1) {
953 sprintf(msg,
"sockopt error: notimeo");
954 tracet(NULL, 1,
"setsock: setsockopt error 1 sock=%d err=%d\n", sock,
errsock());
958 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (
const char*)&bs,
sizeof(bs)) == -1 ||
959 setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (
const char*)&bs,
sizeof(bs)) == -1) {
960 tracet(NULL, 1,
"setsock: setsockopt error 2 sock=%d err=%d bs=%d\n", sock,
errsock(), bs);
961 sprintf(msg,
"sockopt error: bufsiz");
963 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (
const char*)&mode,
sizeof(mode)) == -1) {
964 tracet(NULL, 1,
"setsock: setsockopt error 3 sock=%d err=%d\n", sock,
errsock());
965 sprintf(msg,
"sockopt error: nodelay");
971 struct timeval tv = {0};
977 ret = select(sock + 1, &rs, NULL, NULL, &tv);
981 return accept(sock, addr, len);
985 struct timeval tv = {0};
989 flag = fcntl(sock, F_GETFL, 0);
990 fcntl(sock, F_SETFL, flag | O_NONBLOCK);
991 if (connect(sock, addr, len) == -1) {
993 if (err != EISCONN && err != EINPROGRESS && err != EALREADY) {
999 if (select(sock + 1, &rs, &ws, NULL, &tv) == 0) {
1007 struct timeval tv = {0};
1013 ret = select(sock + 1, &rs, NULL, NULL, &tv);
1017 nr = recv(sock, (
char*)buff, n, 0);
1018 return nr <= 0 ? -1 : nr;
1022 struct timeval tv = {0};
1028 ret = select(sock + 1, NULL, &ws, NULL, &tv);
1032 ns = send(sock, (
char*)buff, n, 0);
1033 return ns < n ? -1 : ns;
1042 tracet(NULL, 3,
"gentcp: type=%d\n", type);
1045 if ((tcp->
sock = socket(AF_INET, SOCK_STREAM, 0)) == (
socket_t)-1) {
1046 sprintf(msg,
"socket error (%d)",
errsock());
1047 tracet(NULL, 1,
"gentcp: socket error err=%d\n",
errsock());
1055 memset(&tcp->
addr, 0,
sizeof(tcp->
addr));
1056 tcp->
addr.sin_family = AF_INET;
1057 tcp->
addr.sin_port = htons(tcp->
port);
1063 setsockopt(tcp->
sock, SOL_SOCKET, SO_REUSEADDR, (
const char*)&opt,
sizeof(opt));
1065 if (bind(tcp->
sock, (
struct sockaddr*)&tcp->
addr,
sizeof(tcp->
addr)) == -1) {
1066 sprintf(msg,
"bind error (%d) : %d",
errsock(), tcp->
port);
1072 listen(tcp->
sock, 5);
1074 if (!(hp = gethostbyname(tcp->
saddr))) {
1075 sprintf(msg,
"address error (%s)", tcp->
saddr);
1076 tracet(NULL, 1,
"gentcp: gethostbyname error addr=%s err=%d\n", tcp->
saddr,
errsock());
1083 memcpy(&tcp->
addr.sin_addr, hp->h_addr_list[0], hp->h_length);
1087 tracet(NULL, 5,
"gentcp: exit sock=%d\n", tcp->
sock);
1092 tracet(NULL, 3,
"discontcp: sock=%d tcon=%d\n", tcp->
sock, tcon);
1102 char port[256] =
"";
1104 tracet(NULL, 3,
"opentcpsvr: path=%s\n", path);
1111 if (sscanf(port,
"%d", &tcpsvr->
svr.
port) < 1) {
1112 sprintf(msg,
"port error: %s", port);
1113 tracet(NULL, 1,
"opentcpsvr: port error port=%s\n", port);
1128 tracet(NULL, 3,
"closetcpsvr:\n");
1130 for (i = 0; i <
MAXCLI; i++) {
1140 char saddr[256] =
"";
1149 for (i = 0; i <
MAXCLI; i++) {
1153 strcpy(saddr, tcpsvr->
cli[i].
saddr);
1158 sprintf(msg,
"waiting...");
1163 sprintf(msg,
"%s", saddr);
1165 sprintf(msg,
"%d clients", n);
1170 struct sockaddr_in addr;
1172 socklen_t len =
sizeof(addr);
1177 for (i = 0; i <
MAXCLI; i++) {
1183 tracet(NULL, 2,
"accsock: too many clients sock=%d\n", tcpsvr->
svr.
sock);
1188 sprintf(msg,
"accept error (%d)", err);
1189 tracet(NULL, 1,
"accsock: accept error sock=%d err=%d\n", tcpsvr->
svr.
sock, err);
1202 memcpy(&tcpsvr->
cli[i].
addr, &addr,
sizeof(addr));
1203 strcpy(tcpsvr->
cli[i].
saddr, inet_ntoa(addr.sin_addr));
1204 sprintf(msg,
"%s", tcpsvr->
cli[i].
saddr);
1205 tracet(NULL, 3,
"accsock: connected sock=%d addr=%s i=%d\n", tcpsvr->
cli[i].
sock, tcpsvr->
cli[i].
saddr, i);
1218 while (
accsock(tcpsvr, msg)) {
1235 for (i = 0; i <
MAXCLI; i++) {
1242 tracet(NULL, 2,
"readtcpsvr: recv error sock=%d err=%d\n", tcpsvr->
cli[i].
sock, err);
1256 int i, ns = 0, nmax = 0, err;
1258 tracet(NULL, 4,
"writetcpsvr: state=%d n=%d\n", tcpsvr->
svr.
state, n);
1264 for (i = 0; i <
MAXCLI; i++) {
1271 tracet(NULL, 2,
"writetcpsvr: send error i=%d sock=%d err=%d\n", i, tcpsvr->
cli[i].
sock, err);
1292 p += sprintf(p,
" state = %d\n", tcp->
state);
1293 p += sprintf(p,
" saddr = %s\n", tcp->
saddr);
1294 p += sprintf(p,
" port = %d\n", tcp->
port);
1295 p += sprintf(p,
" sock = %d\n", (
int)tcp->
sock);
1297 p+=sprintf(p,
" tcon = %d\n",tcp->
tcon);
1298 p+=sprintf(p,
" tact = %u\n",tcp->
tact);
1299 p+=sprintf(p,
" tdis = %u\n",tcp->
tdis);
1301 return (
int)(p - msg);
1306 int i, state = tcpsvr ? tcpsvr->
svr.
state : 0;
1308 p += sprintf(p,
"tcpsvr:\n");
1309 p += sprintf(p,
" state = %d\n", state);
1313 p += sprintf(p,
" svr:\n");
1315 for (i = 0; i <
MAXCLI; i++) {
1319 p += sprintf(p,
" cli#%d:\n", i);
1337 sprintf(msg,
"connect error (%d)", err);
1338 tracet(NULL, 2,
"consock: connect error sock=%d err=%d\n", tcpcli->
svr.
sock, err);
1344 sprintf(msg,
"connecting...");
1347 sprintf(msg,
"%s", tcpcli->
svr.
saddr);
1356 char port[256] =
"";
1358 tracet(NULL, 3,
"opentcpcli: path=%s\n", path);
1365 if (sscanf(port,
"%d", &tcpcli->
svr.
port) < 1) {
1366 sprintf(msg,
"port error: %s", port);
1367 tracet(NULL, 2,
"opentcp: port error port=%s\n", port);
1378 tracet(NULL, 3,
"closetcpcli: sock=%d\n", tcpcli->
svr.
sock);
1403 sprintf(msg,
"timeout");
1404 tracet(NULL, 2,
"waittcpcli: inactive timeout sock=%d\n", tcpcli->
svr.
sock);
1423 tracet(NULL, 2,
"readtcpcli: recv error sock=%d err=%d\n", tcpcli->
svr.
sock, err);
1424 sprintf(msg,
"recv error (%d)", err);
1426 sprintf(msg,
"disconnected");
1434 tracet(NULL, 5,
"readtcpcli: exit sock=%d nr=%d\n", tcpcli->
svr.
sock, nr);
1449 tracet(NULL, 2,
"writetcp: send error sock=%d err=%d\n", tcpcli->
svr.
sock, err);
1450 sprintf(msg,
"send error (%d)", err);
1458 tracet(NULL, 5,
"writetcpcli: exit sock=%d ns=%d\n", tcpcli->
svr.
sock, ns);
1466static int encbase64(
char* str,
const uint8_t*
byte,
int n) {
1467 const char table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1470 tracet(NULL, 4,
"encbase64: n=%d\n", n);
1472 for (i = j = 0; i / 8 < n;) {
1473 for (k = b = 0; k < 6; k++, i++) {
1476 b |= (
byte[i / 8] >> (7 - i % 8)) & 0x1;
1479 str[j++] = table[b];
1485 tracet(NULL, 5,
"encbase64: str=%s\n", str);
1489#define BUFADD(p, rem, ...) \
1491 int _n = snprintf(p, rem, __VA_ARGS__); \
1492 if (_n > 0 && _n < (rem)) { \
1501 char buff[2048], user[514], *p = buff;
1502 int rem = (int)
sizeof(buff);
1506 tracet(NULL, 3,
"reqntrip_s: state=%d ver=%d\n", ntrip->
state, ntrip->
ver);
1513 BUFADD(p, rem,
"POST /%s HTTP/1.1\r\n", ntrip->
mntpnt);
1516 BUFADD(p, rem,
"Ntrip-Version: Ntrip/2.0\r\n");
1519 snprintf(user,
sizeof(user),
"%s:%s", ntrip->
user, ntrip->
passwd);
1520 BUFADD(p, rem,
"Authorization: Basic ");
1522 int b64_need = (int)(((strlen(user) + 2) / 3) * 4 + 1);
1523 if (b64_need > rem) {
1524 sprintf(msg,
"request buffer overflow");
1527 int n =
encbase64(p, (uint8_t*)user, strlen(user));
1533 BUFADD(p, rem,
"Transfer-Encoding: chunked\r\n");
1539 BUFADD(p, rem,
"STR: %s\r\n", ntrip->
str);
1544 sprintf(msg,
"request buffer overflow");
1547 if (
writetcpcli(ntrip->
tcp, (uint8_t*)buff, (
int)(p - buff), msg) != (
int)(p - buff)) {
1551 tracet(NULL, 3,
"reqntrip_s: send request state=%d ns=%d v2=%d\n", ntrip->
state, (
int)(p - buff), use_v2);
1552 tracet(NULL, 5,
"reqntrip_s: n=%d buff=\n%s\n", (
int)(p - buff), buff);
1558 char buff[2048], user[514], *p = buff;
1559 int rem = (int)
sizeof(buff);
1563 tracet(NULL, 3,
"reqntrip_c: state=%d ver=%d\n", ntrip->
state, ntrip->
ver);
1569 BUFADD(p, rem,
"Ntrip-Version: Ntrip/2.0\r\n");
1573 snprintf(user,
sizeof(user),
"%s:%s", ntrip->
user, ntrip->
passwd);
1574 BUFADD(p, rem,
"Authorization: Basic ");
1576 int b64_need = (int)(((strlen(user) + 2) / 3) * 4 + 1);
1577 if (b64_need > rem) {
1578 sprintf(msg,
"request buffer overflow");
1581 int n =
encbase64(p, (uint8_t*)user, strlen(user));
1587 BUFADD(p, rem,
"Connection: close\r\n");
1594 if (!*ntrip->
user) {
1595 BUFADD(p, rem,
"Accept: */*\r\n");
1596 BUFADD(p, rem,
"Connection: close\r\n");
1598 snprintf(user,
sizeof(user),
"%s:%s", ntrip->
user, ntrip->
passwd);
1599 BUFADD(p, rem,
"Authorization: Basic ");
1601 int b64_need = (int)(((strlen(user) + 2) / 3) * 4 + 1);
1602 if (b64_need > rem) {
1603 sprintf(msg,
"request buffer overflow");
1606 int n =
encbase64(p, (uint8_t*)user, strlen(user));
1616 sprintf(msg,
"request buffer overflow");
1619 if (
writetcpcli(ntrip->
tcp, (uint8_t*)buff, (
int)(p - buff), msg) != (
int)(p - buff)) {
1623 tracet(NULL, 3,
"reqntrip_c: send request state=%d ns=%d v2=%d\n", ntrip->
state, (
int)(p - buff), use_v2);
1624 tracet(NULL, 5,
"reqntrip_c: n=%d buff=\n%s\n", (
int)(p - buff), buff);
1630 int i, nb, body_off, status;
1633 tracet(NULL, 3,
"rspntrip_s: state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1634 ntrip->
buff[ntrip->
nb] =
'\0';
1635 tracet(NULL, 5,
"rspntrip_s: n=%d buff=\n%s\n", ntrip->
nb, ntrip->
buff);
1638 q = (
char*)ntrip->
buff;
1640 ntrip->
nb -= (int)(p - q);
1641 for (i = 0; i < ntrip->
nb; i++) {
1647 tracet(NULL, 3,
"rspntrip_s: v1 response ok nb=%d\n", ntrip->
nb);
1654 if (status == 200) {
1658 ntrip->
nb -= body_off;
1659 if (ntrip->
nb > 0) {
1660 memmove(ntrip->
buff, ntrip->
buff + body_off, ntrip->
nb);
1663 tracet(NULL, 3,
"rspntrip_s: v2 response ok nb=%d\n", ntrip->
nb);
1668 tracet(NULL, 3,
"rspntrip_s: http error %s nb=%d\n", msg, ntrip->
nb);
1670 ntrip->
buff[0] =
'\0';
1677 sprintf(msg,
"%.*s", nb, (
char*)ntrip->
buff);
1678 if ((p = strchr(msg,
'\r'))) {
1681 tracet(NULL, 3,
"rspntrip_s: %s nb=%d\n", msg, ntrip->
nb);
1683 ntrip->
buff[0] =
'\0';
1687 sprintf(msg,
"response overflow");
1688 tracet(NULL, 3,
"rspntrip_s: response overflow nb=%d\n", ntrip->
nb);
1690 ntrip->
buff[0] =
'\0';
1694 tracet(NULL, 5,
"rspntrip_s: exit state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1699 int i, body_off, status;
1700 char *p, *q, val[256];
1702 tracet(NULL, 3,
"rspntrip_c: state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1703 ntrip->
buff[ntrip->
nb] =
'\0';
1704 tracet(NULL, 5,
"rspntrip_c: n=%d buff=\n%s\n", ntrip->
nb, ntrip->
buff);
1707 q = (
char*)ntrip->
buff;
1709 ntrip->
nb -= (int)(p - q);
1710 for (i = 0; i < ntrip->
nb; i++) {
1720 tracet(NULL, 3,
"rspntrip_c: v1 response ok nb=%d\n", ntrip->
nb);
1727 if (status == 200) {
1730 strstr(val,
"sourcetable")) {
1741 ntrip->
nb -= body_off;
1742 memmove(ntrip->
buff, ntrip->
buff + body_off, ntrip->
nb);
1749 sprintf(msg,
"source table received");
1750 tracet(NULL, 3,
"rspntrip_c: v2 source table nb=%d\n", ntrip->
nb);
1753 sprintf(msg,
"no mountp. reconnect...");
1754 tracet(NULL, 2,
"rspntrip_c: v2 no mount point nb=%d\n", ntrip->
nb);
1756 ntrip->
buff[0] =
'\0';
1772 ntrip->
nb -= body_off;
1773 if (ntrip->
nb > 0) {
1774 memmove(ntrip->
buff, ntrip->
buff + body_off, ntrip->
nb);
1777 tracet(NULL, 3,
"rspntrip_c: v2 response ok chunked=%d nb=%d\n", ntrip->
chunked, ntrip->
nb);
1782 tracet(NULL, 3,
"rspntrip_c: http error %s nb=%d\n", msg, ntrip->
nb);
1784 ntrip->
buff[0] =
'\0';
1793 sprintf(msg,
"source table received");
1794 tracet(NULL, 3,
"rspntrip_c: receive source table nb=%d\n", ntrip->
nb);
1797 sprintf(msg,
"no mountp. reconnect...");
1798 tracet(NULL, 2,
"rspntrip_c: no mount point nb=%d\n", ntrip->
nb);
1800 ntrip->
buff[0] =
'\0';
1804 sprintf(msg,
"response overflow");
1805 tracet(NULL, 2,
"rspntrip_c: response overflow nb=%d\n", ntrip->
nb);
1807 ntrip->
buff[0] =
'\0';
1811 tracet(NULL, 5,
"rspntrip_c: exit state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1819 tracet(NULL, 4,
"waitntrip: state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1821 if (ntrip->
state < 0) {
1832 tracet(NULL, 3,
"waitntrip: v2 failed before response, falling back to v1\n");
1837 if (ntrip->
state == 0) {
1839 if (ntrip->
type == 0) {
1851 tracet(NULL, 3,
"waitntrip: state=%d nb=%d\n", ntrip->
state, ntrip->
nb);
1853 if (ntrip->
state == 1) {
1854 p = (
char*)ntrip->
buff + ntrip->
nb;
1856 tracet(NULL, 5,
"waitntrip: readtcp n=%d\n", n);
1860 ntrip->
buff[ntrip->
nb] =
'\0';
1863 if (ntrip->
type == 0) {
1876 char params[256], *p, *next;
1880 host_override[0] =
'\0';
1882 q = strchr(mntpnt,
'?');
1888 snprintf(params,
sizeof(params),
"%s", q + 1);
1891 tracet(NULL, 3,
"parse_ntrip_query: mntpnt=%s params=%s\n", mntpnt, params);
1897 next = strchr(p,
'&');
1902 if (strncmp(p,
"ver=", 4) == 0) {
1903 int v = atoi(p + 4);
1906 }
else if (v == 2) {
1909 }
else if (strncmp(p,
"host=", 5) == 0) {
1910 const char* h = p + 5;
1911 int valid = 1, hlen = 0;
1914 if ((
unsigned char)h[hlen] <= 0x20 || h[hlen] == 0x7F) {
1920 if (valid && hlen > 0) {
1921 snprintf(host_override, host_size,
"%s", h);
1931 tracet(NULL, 3,
"parse_ntrip_query: ver=%d host_override=%s\n", ver, host_override);
1938 char addr[256] =
"", port[256] =
"", tpath[
MAXSTRPATH];
1940 tracet(NULL, 3,
"openntrip: path=%s type=%d\n", path, type);
1953 ntrip->
url[0] =
'\0';
1954 ntrip->
host[0] =
'\0';
1966 char host_override[256] =
"";
1973 sprintf(tpath,
"%s:%s", addr, port);
1976 if (*host_override) {
1977 snprintf(ntrip->
host,
sizeof(ntrip->
host),
"%s", host_override);
1979 snprintf(ntrip->
host,
sizeof(ntrip->
host),
"%s:%s", addr, port);
1990 tracet(NULL, 2,
"openntrip: opentcp error\n");
1994 tracet(NULL, 3,
"openntrip: ver=%d host=%s mntpnt=%s\n", ntrip->
ver, ntrip->
host, ntrip->
mntpnt);
1999 tracet(NULL, 3,
"closentrip: state=%d\n", ntrip->
state);
2004 uint8_t term[] =
"0\r\n\r\n";
2014 tracet(NULL, 4,
"readntrip:\n");
2020 if (ntrip->
nb > 0) {
2023 const uint8_t* in = ntrip->
buff;
2024 int nin = ntrip->
nb;
2027 tracet(NULL, 2,
"readntrip: chunk decode error, resetting\n");
2034 memmove(ntrip->
buff, in, nin);
2039 nb = ntrip->
nb <= n ? ntrip->
nb : n;
2040 memcpy(buff, ntrip->
buff, nb);
2041 if (nb < ntrip->nb) {
2042 memmove(ntrip->
buff, ntrip->
buff + nb, ntrip->
nb - nb);
2054 const uint8_t* in = raw;
2058 tracet(NULL, 2,
"readntrip: chunk decode error, resetting\n");
2066 memcpy(ntrip->
buff + ntrip->
nb, in, nin);
2069 tracet(NULL, 2,
"readntrip: chunk buffer overflow, resetting\n");
2080 tracet(NULL, 3,
"writentrip: n=%d\n", n);
2088 uint8_t cbuf[4096 + 20];
2089 int remaining = n, sent = 0;
2091 while (remaining > 0) {
2092 int chunk = remaining < 4096 ? remaining : 4096;
2093 int cn =
chunk_encode(cbuf,
sizeof(cbuf), buff + sent, chunk);
2113 p += sprintf(p,
"ntrip:\n");
2114 p += sprintf(p,
" state = %d\n", state);
2118 p += sprintf(p,
" state = %d\n", state);
2119 p += sprintf(p,
" type = %d\n", ntrip->
type);
2120 p += sprintf(p,
" ver = %d\n", ntrip->
ver);
2121 p += sprintf(p,
" ver_neg = %d\n", ntrip->
ver_neg);
2122 p += sprintf(p,
" chunked = %d\n", ntrip->
chunked);
2123 p += sprintf(p,
" nb = %d\n", ntrip->
nb);
2124 p += sprintf(p,
" url = %s\n", ntrip->
url);
2125 p += sprintf(p,
" host = %s\n", ntrip->
host);
2126 p += sprintf(p,
" mntpnt = %s\n", ntrip->
mntpnt);
2127 p += sprintf(p,
" user = %s\n", ntrip->
user);
2128 p += sprintf(p,
" passwd = %s\n", ntrip->
passwd);
2129 p += sprintf(p,
" str = %s\n", ntrip->
str);
2130 p += sprintf(p,
" svr:\n");
2140 tracet(NULL, 3,
"openntripc: path=%s\n", path);
2148 for (i = 0; i <
MAXCLI; i++) {
2151 ntripc->
con[i].
nb = 0;
2158 tracet(NULL, 2,
"openntripc: no mountpoint path=%s\n", path);
2166 sprintf(tpath,
":%s", port);
2170 tracet(NULL, 2,
"openntripc: opentcpsvr error port=%d\n", port);
2179 tracet(NULL, 3,
"closentripc: state=%d\n", ntripc->
state);
2182 for (i = 0; i <
MAXCLI; i++) {
2184 uint8_t term[] =
"0\r\n\r\n";
2193 tracet(NULL, 3,
"discon_ntripc: i=%d\n", i);
2197 uint8_t term[] =
"0\r\n\r\n";
2201 ntripc->
con[i].
nb = 0;
2202 ntripc->
con[i].
buff[0] =
'\0';
2208 static const char* month[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
2209 static const char* wkday[] = {
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"};
2210 time_t tt = time(NULL);
2211 struct tm* tm = gmtime(&tt);
2213 sprintf(buff,
"%s, %02d %s %04d %02d:%02d:%02d GMT", wkday[tm->tm_wday], tm->tm_mday, month[tm->tm_mon],
2214 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
2218 char srctbl[512 +
NTRIP_MAXSTR], buff[256], tstr[64], *p = buff;
2225 p += sprintf(p,
"HTTP/1.1 200 OK\r\n");
2226 p += sprintf(p,
"Ntrip-Version: Ntrip/2.0\r\n");
2227 p += sprintf(p,
"Ntrip-Flags: \r\n");
2230 p += sprintf(p,
"Server: NTRIP %s/%s\r\n", MRTKLIB_SOFTNAME, MRTKLIB_VERSION_STRING);
2231 p += sprintf(p,
"Date: %s\r\n", tstr);
2232 p += sprintf(p,
"Connection: close\r\n");
2233 p += sprintf(p,
"Content-Type: %s\r\n", (ver == 1) ?
"text/plain" :
"gnss/sourcetable");
2234 p += sprintf(p,
"Content-Length: %d\r\n\r\n", (
int)strlen(srctbl));
2235 send_nb(sock, (uint8_t*)buff, (
int)(p - buff));
2236 send_nb(sock, (uint8_t*)srctbl, (
int)strlen(srctbl));
2240 char buff[512], tstr[64], *p = buff;
2246 p += sprintf(p,
"HTTP/1.1 200 OK\r\n");
2247 p += sprintf(p,
"Ntrip-Version: Ntrip/2.0\r\n");
2248 p += sprintf(p,
"Server: NTRIP %s/%s\r\n", MRTKLIB_SOFTNAME, MRTKLIB_VERSION_STRING);
2249 p += sprintf(p,
"Date: %s\r\n", tstr);
2250 p += sprintf(p,
"Cache-Control: no-store, no-cache, max-age=0\r\n");
2251 p += sprintf(p,
"Pragma: no-cache\r\n");
2252 p += sprintf(p,
"Transfer-Encoding: chunked\r\n");
2253 p += sprintf(p,
"Connection: close\r\n");
2254 p += sprintf(p,
"Content-Type: gnss/data\r\n\r\n");
2256 send_nb(sock, (uint8_t*)buff, (
int)(p - buff));
2260 char buff[512], tstr[64], *p = buff;
2270 p += sprintf(p,
"HTTP/1.1 %d %s\r\n", err, (err == 404) ?
"Not Found" :
"Unauthorized");
2271 p += sprintf(p,
"Ntrip-Version: Ntrip/2.0\r\n");
2272 p += sprintf(p,
"Server: NTRIP %s/%s\r\n", MRTKLIB_SOFTNAME, MRTKLIB_VERSION_STRING);
2273 p += sprintf(p,
"Date: %s\r\n", tstr);
2274 p += sprintf(p,
"Content-Type: text/html\r\n");
2275 p += sprintf(p,
"Connection: close\r\n\r\n");
2276 p += sprintf(p,
"%s\r\n", (err == 404) ?
"Mountpoint of request not found" :
"No or wrong authorization");
2278 send_nb(sock, (uint8_t*)buff, (
int)(p - buff));
2283 char url[256] =
"", mntpnt[256] =
"", proto[256] =
"", user[513], user_pwd[256], *p, *q;
2286 tracet(NULL, 3,
"rsp_ntripc=%d\n", i);
2287 con->
buff[con->
nb] =
'\0';
2288 tracet(NULL, 5,
"rsp_ntripc: n=%d,buff=\n%s\n", con->
nb, con->
buff);
2291 tracet(NULL, 2,
"rsp_ntripc: request buffer overflow\n");
2296 if (!(p = strstr((
char*)con->
buff,
"GET")) || !(q = strstr(p,
"\r\n")) || !(q = strstr(q,
"User-Agent:")) ||
2297 !strstr(q,
"\r\n")) {
2298 tracet(NULL, 2,
"rsp_ntripc: NTRIP request error\n");
2303 if (sscanf(p,
"GET %255s %255s", url, proto) < 2 || (strcmp(proto,
"HTTP/1.0") && strcmp(proto,
"HTTP/1.1"))) {
2304 tracet(NULL, 2,
"rsp_ntripc: NTRIP request error proto=%s\n", proto);
2309 if ((p = strstr((
char*)con->
buff,
"Ntrip-Version:"))) {
2310 sscanf(p + 14,
" Ntrip/%d", &ver);
2311 if (ver < 1 || ver > 2) {
2315 if ((p = strchr(url,
'/'))) {
2316 strcpy(mntpnt, p + 1);
2326 if (strcmp(mntpnt, ntripc->
mntpnt)) {
2329 tracet(NULL, 2,
"rsp_ntripc: no mountpoint %s\n", mntpnt);
2334 sprintf(user,
"%s:%s", ntripc->
user, ntripc->
passwd);
2336 q += sprintf(q,
"Authorization: Basic ");
2337 q +=
encbase64(q, (uint8_t*)user, strlen(user));
2338 if (!(p = strstr((
char*)con->
buff,
"Authorization:")) || strncmp(p, user_pwd, strlen(user_pwd))) {
2341 tracet(NULL, 2,
"rsp_ntripc: authorization error\n");
2350 strcpy(con->
mntpnt, mntpnt);
2355 int i, n, nmax, err;
2357 tracet(NULL, 4,
"wait_ntripc\n");
2365 for (i = 0; i <
MAXCLI; i++) {
2376 tracet(NULL, 2,
"wait_ntripc: recv error sock=%d err=%d\n", ntripc->
tcp->
cli[i].
sock, err);
2386 ntripc->
con[i].
nb += n;
2394 tracet(NULL, 4,
"readntripc:\n");
2398 for (i = 0; i <
MAXCLI; i++) {
2407 tracet(NULL, 2,
"readntripc: recv error i=%d sock=%d err=%d\n", i, ntripc->
tcp->
cli[i].
sock, err);
2410 }
else if (nr > 0) {
2421 tracet(NULL, 4,
"writentripc: n=%d\n", n);
2425 for (i = 0; i <
MAXCLI; i++) {
2430 if (ntripc->
con[i].
ver >= 2) {
2432 uint8_t cbuf[4096 + 20];
2433 int remaining = n, sent = 0;
2435 while (remaining > 0) {
2436 int chunk = remaining < 4096 ? remaining : 4096;
2437 int cn =
chunk_encode(cbuf,
sizeof(cbuf), buff + sent, chunk);
2443 tracet(NULL, 2,
"writentripc: send error i=%d err=%d\n", i, err);
2451 if (remaining <= 0) {
2461 tracet(NULL, 2,
"writentripc: send error i=%d sock=%d err=%d\n", i, ntripc->
tcp->
cli[i].
sock, err);
2476 int i, state = !ntripc ? 0 : ntripc->
state;
2478 p += sprintf(p,
"ntripc:\n");
2479 p += sprintf(p,
" state = %d\n", ntripc->
state);
2483 p += sprintf(p,
" type = %d\n", ntripc->
type);
2484 p += sprintf(p,
" mntpnt = %s\n", ntripc->
mntpnt);
2485 p += sprintf(p,
" user = %s\n", ntripc->
user);
2486 p += sprintf(p,
" passwd = %s\n", ntripc->
passwd);
2487 p += sprintf(p,
" srctbl = %s\n", ntripc->
srctbl);
2488 p += sprintf(p,
" svr:\n");
2490 for (i = 0; i <
MAXCLI; i++) {
2494 p += sprintf(p,
" cli#%d:\n", i);
2496 p += sprintf(p,
" mntpnt= %s\n", ntripc->
con[i].
mntpnt);
2497 p += sprintf(p,
" nb = %d\n", ntripc->
con[i].
nb);
2502static udp_t*
genudp(
int type,
int port,
const char* saddr,
char* msg) {
2507 tracet(NULL, 3,
"genudp: type=%d\n", type);
2515 strcpy(udp->
saddr, saddr);
2517 if ((udp->
sock = socket(AF_INET, SOCK_DGRAM, 0)) == (
socket_t)-1) {
2518 sprintf(msg,
"socket error (%d)",
errsock());
2521 if (setsockopt(udp->
sock, SOL_SOCKET, SO_RCVBUF, (
const char*)&bs,
sizeof(bs)) == -1 ||
2522 setsockopt(udp->
sock, SOL_SOCKET, SO_SNDBUF, (
const char*)&bs,
sizeof(bs)) == -1) {
2523 tracet(NULL, 2,
"genudp: setsockopt error sock=%d err=%d bs=%d\n", udp->
sock,
errsock(), bs);
2524 sprintf(msg,
"sockopt error: bufsiz");
2526 memset(&udp->
addr, 0,
sizeof(udp->
addr));
2527 udp->
addr.sin_family = AF_INET;
2528 udp->
addr.sin_port = htons(port);
2531 udp->
addr.sin_addr.s_addr = htonl(INADDR_ANY);
2533 setsockopt(udp->
sock, SOL_SOCKET, SO_REUSEADDR, (
const char*)&opt,
sizeof(opt));
2535 if (bind(udp->
sock, (
struct sockaddr*)&udp->
addr,
sizeof(udp->
addr)) == -1) {
2536 tracet(NULL, 2,
"genudp: bind error sock=%d port=%d err=%d\n", udp->
sock, port,
errsock());
2537 sprintf(msg,
"bind error (%d): %d",
errsock(), port);
2543 if (!strcmp(saddr,
"255.255.255.255") &&
2544 setsockopt(udp->
sock, SOL_SOCKET, SO_BROADCAST, (
const char*)&opt,
sizeof(opt)) == -1) {
2545 tracet(NULL, 2,
"genudp: setsockopt error sock=%d err=%d\n", udp->
sock,
errsock());
2546 sprintf(msg,
"sockopt error: broadcast");
2548 if (!(hp = gethostbyname(saddr))) {
2549 sprintf(msg,
"address error (%s)", saddr);
2554 memcpy(&udp->
addr.sin_addr, hp->h_addr_list[0], hp->h_length);
2560 char sport[256] =
"";
2563 tracet(NULL, 3,
"openudpsvr: path=%s\n", path);
2567 if (sscanf(sport,
"%d", &port) < 1) {
2568 sprintf(msg,
"port error: %s", sport);
2569 tracet(NULL, 2,
"openudpsvr: port error port=%s\n", port);
2572 return genudp(0, port,
"", msg);
2576 tracet(NULL, 3,
"closeudpsvr: sock=%d\n", udpsvr->
sock);
2583 struct timeval tv = {0};
2587 tracet(NULL, 4,
"readudpsvr: sock=%d n=%d\n", udpsvr->
sock, n);
2590 FD_SET(udpsvr->
sock, &rs);
2591 ret = select(udpsvr->
sock + 1, &rs, NULL, NULL, &tv);
2595 nr = recvfrom(udpsvr->
sock, (
char*)buff, n, 0, NULL, NULL);
2596 return nr <= 0 ? -1 : nr;
2603 int state = udpsvr ? udpsvr->
state : 0;
2605 p += sprintf(p,
"udpsvr:\n");
2606 p += sprintf(p,
" state = %d\n", state);
2610 p += sprintf(p,
" type = %d\n", udpsvr->
type);
2611 p += sprintf(p,
" sock = %d\n", (
int)udpsvr->
sock);
2612 p += sprintf(p,
" port = %d\n", udpsvr->
port);
2617 char sport[256] =
"", saddr[256] =
"";
2620 tracet(NULL, 3,
"openudpsvr: path=%s\n", path);
2624 if (sscanf(sport,
"%d", &port) < 1) {
2625 sprintf(msg,
"port error: %s", sport);
2626 tracet(NULL, 2,
"openudpcli: port error port=%s\n", sport);
2629 return genudp(1, port, saddr, msg);
2633 tracet(NULL, 3,
"closeudpcli: sock=%d\n", udpcli->
sock);
2640 tracet(NULL, 4,
"writeudpcli: sock=%d n=%d\n", udpcli->
sock, n);
2642 return (
int)sendto(udpcli->
sock, (
char*)buff, n, 0, (
struct sockaddr*)&udpcli->
addr,
sizeof(udpcli->
addr));
2649 int state = udpcli ? udpcli->
state : 0;
2651 p += sprintf(p,
"udpsvr:\n");
2652 p += sprintf(p,
" state = %d\n", state);
2656 p += sprintf(p,
" type = %d\n", udpcli->
type);
2657 p += sprintf(p,
" sock = %d\n", (
int)udpcli->
sock);
2658 p += sprintf(p,
" addr = %s\n", udpcli->
saddr);
2659 p += sprintf(p,
" port = %d\n", udpcli->
port);
2663static void decodeftppath(
const char* path,
char* addr,
char* file,
char* user,
char* passwd,
int* topts) {
2666 tracet(NULL, 4,
"decodeftpath: path=%s\n", path);
2682 if ((p = strchr(buff,
'/'))) {
2683 if ((q = strstr(p + 1,
"::"))) {
2686 sscanf(q + 2,
"T=%d,%d,%d,%d", topts, topts + 1, topts + 2, topts + 3);
2689 strcpy(file, p + 1);
2695 if ((p = strrchr(buff,
'@'))) {
2697 if ((q = strchr(buff,
':'))) {
2700 strcpy(passwd, q + 1);
2719 tracet(NULL, 3,
"nextdltime: topts=%d %d %d %d stat=%d\n", topts[0], topts[1], topts[2], topts[3], stat);
2726 if (stat == 0 && topts[3] > 0) {
2727 tow = (floor((tow - topts[2]) / topts[3]) + 1.0) * topts[3] + topts[2];
2731 tint = topts[1] <= 0 ? 3600 : topts[1];
2732 tow = (floor((tow - topts[2]) / tint) + 1.0) * tint + topts[2];
2742 char remote[1024], local[1024], tmpfile[1024], errfile[1024], *p;
2743 char cmd[5120], env[1024] =
"", opt[1024], *proxyopt =
"", *proto;
2746 tracet(NULL, 3,
"ftpthread:\n");
2749 tracet(NULL, 2,
"no local directory\n");
2758 if ((p = strrchr(remote,
'/'))) {
2764 sprintf(errfile,
"%.1019s.err", local);
2767 strcpy(tmpfile, local);
2768 if ((p = strrchr(tmpfile,
'.')) && (!strcmp(p,
".z") || !strcmp(p,
".gz") || !strcmp(p,
".zip") ||
2769 !strcmp(p,
".Z") || !strcmp(p,
".GZ") || !strcmp(p,
".ZIP"))) {
2772 if ((fp = fopen(tmpfile,
"rb"))) {
2774 sprintf(ftp->
local,
"%.1023s", tmpfile);
2775 tracet(NULL, 3,
"ftpthread: file exists %s\n", ftp->
local);
2781 proto = ftp->
proto ?
"http" :
"ftp";
2782 sprintf(env,
"set %.4s_proxy=http://%.998s & ", proto,
proxyaddr);
2783 proxyopt =
"--proxy=on ";
2786 if (ftp->
proto == 0) {
2788 "--ftp-user=%.32s --ftp-password=%.32s --glob=off "
2789 "--passive-ftp %.32s -t 1 -T %d -O \"%.768s\"",
2791 sprintf(cmd,
"%s%s %s \"ftp://%s/%s\" 2> \"%.768s\"\n", env,
FTP_CMD, opt, ftp->
addr, remote, errfile);
2793 sprintf(opt,
"%.32s -t 1 -T %d -O \"%.768s\"", proxyopt,
FTP_TIMEOUT, local);
2794 sprintf(cmd,
"%s%s %s \"http://%s/%s\" 2> \"%.768s\"\n", env,
FTP_CMD, opt, ftp->
addr, remote, errfile);
2799 tracet(NULL, 2,
"execcmd error: cmd=%s ret=%d\n", cmd, ret);
2807 if ((p = strrchr(local,
'.')) && (!strcmp(p,
".z") || !strcmp(p,
".gz") || !strcmp(p,
".zip") || !strcmp(p,
".Z") ||
2808 !strcmp(p,
".GZ") || !strcmp(p,
".ZIP"))) {
2811 strcpy(local, tmpfile);
2813 tracet(NULL, 2,
"file uncompact error: %s\n", local);
2819 strcpy(ftp->
local, local);
2822 tracet(NULL, 3,
"ftpthread: complete cmd=%s\n", cmd);
2829 tracet(NULL, 3,
"openftp: path=%s type=%d\n", path, type);
2841 ftp->
local[0] =
'\0';
2853 tracet(NULL, 3,
"closeftp: state=%d\n", ftp->
state);
2855 if (ftp->
state != 1) {
2864 tracet(NULL, 4,
"readftp: n=%d\n", n);
2871 if (ftp->
state <= 0) {
2873 sprintf(msg,
"%s://%s", ftp->
proto ?
"http" :
"ftp", ftp->
addr);
2876 tracet(NULL, 2,
"readftp: ftp thread create error\n");
2878 strcpy(msg,
"ftp thread error");
2882 if (ftp->
state <= 1) {
2886 if (ftp->
state == 3) {
2887 sprintf(msg,
"%s error (%d)", ftp->
proto ?
"http" :
"ftp", ftp->
error);
2896 q = (uint8_t*)ftp->
local;
2897 while (*q && (
int)(p - buff) < n) {
2900 p += sprintf((
char*)p,
"\r\n");
2908 return (
int)(p - buff);
2914 }
else if (ftp->
state == 0) {
2916 }
else if (ftp->
state <= 2) {
2926 }
else if (ftp->
state == 0) {
2928 }
else if (ftp->
state <= 2) {
2939 tracet(NULL, 3,
"openmembuf: path=%s\n", path);
2943 sscanf(path,
"%d", &bufsize);
2951 if (!(membuf->
buf = (uint8_t*)
malloc(bufsize))) {
2958 sprintf(msg,
"membuf sizebuf=%d", bufsize);
2964 tracet(NULL, 3,
"closemembufp\n");
2973 tracet(NULL, 4,
"readmembuf: n=%d\n", n);
2981 for (i = membuf->
rp; i != membuf->
wp && nr < n; i++) {
2984 if (i == membuf->
wp) {
2988 buff[nr++] = membuf->
buf[i];
2998 tracet(NULL, 3,
"writemembuf: n=%d\n", n);
3006 for (i = 0; i < n; i++) {
3007 membuf->
buf[membuf->
wp++] = buff[i];
3011 if (membuf->
wp == membuf->
rp) {
3012 strcpy(msg,
"mem-buffer overflow");
3026 int state = !membuf ? 0 : membuf->
state;
3028 p += sprintf(p,
"membuf:\n");
3029 p += sprintf(p,
" state = %d\n", state);
3033 p += sprintf(p,
" buffsize= %d\n", membuf->
bufsize);
3034 p += sprintf(p,
" wp = %d\n", membuf->
wp);
3035 p += sprintf(p,
" rp = %d\n", membuf->
rp);
3050 tracet(NULL, 3,
"strinit:\n");
3058 stream->
port = NULL;
3059 stream->
path[0] =
'\0';
3060 stream->
msg[0] =
'\0';
3174 tracet(NULL, 3,
"stropen: type=%d mode=%d path=%s\n", type, mode, path);
3176 stream->
type = type;
3177 stream->
mode = mode;
3178 strcpy(stream->
path, path);
3182 stream->
msg[0] =
'\0';
3183 stream->
port = NULL;
3226 return stream->
port != NULL;
3234 tracet(NULL, 3,
"strclose: type=%d mode=%d\n", stream->
type, stream->
mode);
3239 switch (stream->
type) {
3278 trace(NULL, 3,
"no port to close stream: type=%d\n", stream->
type);
3283 stream->
inr = stream->
outr = 0;
3284 stream->
path[0] =
'\0';
3285 stream->
msg[0] =
'\0';
3286 stream->
port = NULL;
3304 if (file1 && file2) {
3326 char* msg = stream->
msg;
3329 tracet(NULL, 4,
"strread: n=%d\n", n);
3337 switch (stream->
type) {
3375 stream->
tact = tick;
3377 tt = (int)(tick - stream->
tick_i);
3379 stream->
inr = (uint32_t)((
double)((stream->
inb - stream->
inbt) * 8) / (tt * 0.001));
3396 char* msg = stream->
msg;
3399 tracet(NULL, 4,
"strwrite: n=%d\n", n);
3407 switch (stream->
type) {
3441 stream->
tact = tick;
3443 tt = (int)(tick - stream->
tick_o);
3445 stream->
outr = (uint32_t)((
double)((stream->
outb - stream->
outbt) * 8) / (tt * 0.001));
3461 tracet(NULL, 4,
"strstat:\n");
3468 if (!stream->
port) {
3470 return stream->
state;
3472 switch (stream->
type) {
3526 tracet(NULL, 4,
"strstatx:\n");
3530 if (!stream->
port) {
3532 return stream->
state;
3534 switch (stream->
type) {
3589extern void strsum(
stream_t* stream, uint64_t* inb,
int* inr, uint64_t* outb,
int* outr) {
3590 tracet(NULL, 4,
"strsum:\n");
3600 *outb = stream->
outb;
3603 *outr = stream->
outr;
3621 tracet(NULL, 3,
"strsetopt: opt=%d %d %d %d %d %d %d %d\n", opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6],
3624 toinact = 0 < opt[0] && opt[0] < 1000 ? 1000 : opt[0];
3625 ticonnect = opt[1] < 1000 ? 1000 : opt[1];
3626 tirate = opt[2] < 100 ? 100 : opt[2];
3627 buffsize = opt[3] < 4096 ? 4096 : opt[3];
3640 tracet(NULL, 3,
"strsettimeout: toinact=%d tirecon=%d\n",
toinact, tirecon);
3659 tracet(NULL, 3,
"strsetdir: dir=%s\n", dir);
3669 tracet(NULL, 3,
"strsetproxy: addr=%s\n", addr);
3679 tracet(NULL, 3,
"strsetntripver: ver=%d\n", ver);
3681 if (ver >= 0 && ver <= 2) {
3707 tracet(NULL, 3,
"strsendnmea: rr=%.3f %.3f %.3f\n", sol->
rr[0], sol->
rr[1], sol->
rr[2]);
3713static int gen_hex(
const char* msg, uint8_t* buff) {
3715 char mbuff[1024] =
"", *args[256], *p;
3719 trace(NULL, 4,
"gen_hex: msg=%s\n", msg);
3721 strncpy(mbuff, msg, 1023);
3722 for (p = strtok(mbuff,
" "); p && narg < 256; p = strtok(NULL,
" ")) {
3725 for (i = 0; i < narg; i++) {
3726 if (sscanf(args[i],
"%x", &
byte)) {
3727 *q++ = (uint8_t)
byte;
3730 return (
int)(q - buff);
3734 char path[1024], buff[1024] =
"", *p, *q;
3735 int type = str->
type, mode = str->
mode;
3741 strcpy(path, str->
path);
3743 if (!(p = strchr(path,
':'))) {
3744 sprintf(path + strlen(path),
":%d", brate);
3746 if ((q = strchr(p + 1,
':'))) {
3749 sprintf(p,
":%d%s", brate, buff);
3752 return stropen(str, type, mode, path);
3762 const char *p = cmd, *q;
3763 char msg[1024], cmdend[] =
"\r\n";
3764 int n, m, ms, brate;
3766 tracet(NULL, 3,
"strsendcmd: cmd=%s\n", cmd);
3770 if (*q ==
'\r' || *q ==
'\n' || *q ==
'\0') {
3778 if (!*msg || *msg ==
'#') {
3780 }
else if (*msg ==
'!') {
3782 if (!strncmp(msg + 1,
"WAIT", 4)) {
3783 if (sscanf(msg + 5,
"%d", &ms) < 1) {
3790 }
else if (!strncmp(msg + 1,
"BRATE", 5)) {
3791 if (sscanf(msg + 6,
"%d", &brate) < 1) {
3796 }
else if (!strncmp(msg + 1,
"UBX", 3)) {
3797 if ((m =
gen_ubx(msg + 4, buff)) > 0) {
3800 }
else if (!strncmp(msg + 1,
"STQ", 3)) {
3801 if ((m =
gen_stq(msg + 4, buff)) > 0) {
3804 }
else if (!strncmp(msg + 1,
"NVS", 3)) {
3805 if ((m =
gen_nvs(msg + 4, buff)) > 0) {
3808 }
else if (!strncmp(msg + 1,
"HEX", 3)) {
3809 if ((m =
gen_hex(msg + 4, buff)) > 0) {
3814 strcat(msg, cmdend);
3815 strwrite(str, (uint8_t*)msg, n + 2);
int gen_nvs(const char *msg, uint8_t *buff)
int gen_stq(const char *msg, uint8_t *buff)
int gen_ubx(const char *msg, uint8_t *buff)
MRTKLIB Receiver Raw Data Module — Receiver raw data types and decoder functions for various GNSS rec...
int outnmea_gga(uint8_t *buff, const sol_t *sol)
Output NMEA GGA sentence.
MRTKLIB Solution Module — Solution data types and I/O functions.
static uint32_t tick_master
static void closemembuf(membuf_t *membuf)
static int statemembuf(membuf_t *membuf)
static int statextcpcli(tcpcli_t *tcpcli, char *msg)
static void decodeftppath(const char *path, char *addr, char *file, char *user, char *passwd, int *topts)
static int writetcpsvr(tcpsvr_t *tcpsvr, uint8_t *buff, int n, char *msg)
static file_t * openfile(const char *path, int mode, char *msg)
static int stateudpsvr(udp_t *udpsvr)
void strinit(stream_t *stream)
Initialize stream structure.
static int readntripc(ntripc_t *ntripc, uint8_t *buff, int n, char *msg)
static int readudpsvr(udp_t *udpsvr, uint8_t *buff, int n, char *msg)
static int consock(tcpcli_t *tcpcli, char *msg)
static udp_t * openudpsvr(const char *path, char *msg)
static int writefile(file_t *file, uint8_t *buff, int n, char *msg)
static void send_srctbl(ntripc_t *ntripc, int ver, int sock)
static void syncfile(file_t *file1, file_t *file2)
int strstat(stream_t *stream, char *msg)
Get stream status.
static int readntrip(ntrip_t *ntrip, uint8_t *buff, int n, char *msg)
static ntrip_t * openntrip(const char *path, int type, char *msg)
static void closeudpsvr(udp_t *udpsvr)
static void closeftp(ftp_t *ftp)
struct tcpsvr_tag tcpsvr_t
static ntripc_t * openntripc(const char *path, char *msg)
static int statentripc(ntripc_t *ntripc)
gtime_t strgettime(stream_t *stream)
Get stream time.
static void send_rsp_err(ntripc_t *ntripc, int ver, int err, int sock)
static int readserial(serial_t *serial, uint8_t *buff, int n, char *msg)
void strsettimeout(stream_t *stream, int toinact, int tirecon)
Set stream timeout.
static int statetcpsvr(tcpsvr_t *tcpsvr)
static int openfile_(file_t *file, gtime_t time, char *msg)
static int ntrip_ver_default
static int readtcpsvr(tcpsvr_t *tcpsvr, uint8_t *buff, int n, char *msg)
static int statexntripc(ntripc_t *ntripc, char *msg)
static int statexmembuf(membuf_t *membuf, char *msg)
static char proxyaddr[256]
static int statetcpcli(tcpcli_t *tcpcli)
static int readfile(file_t *file, uint8_t *buff, int nmax, char *msg)
int strstatx(stream_t *stream, char *msg)
Get stream extended status.
static int set_brate(stream_t *str, int brate)
int strread(stream_t *stream, uint8_t *buff, int n)
Read data from stream.
void strsendnmea(stream_t *stream, const sol_t *sol)
Send NMEA request to stream.
static tcpcli_t * opentcpcli(const char *path, char *msg)
static int waittcpcli(tcpcli_t *tcpcli, char *msg)
static int statexserial(serial_t *serial, char *msg)
static void closetcpsvr(tcpsvr_t *tcpsvr)
static int statexudpcli(udp_t *udpcli, char *msg)
static void closefile(file_t *file)
static void wait_ntripc(ntripc_t *ntripc, char *msg)
static int recv_nb(int sock, uint8_t *buff, int n)
static void discon_ntripc(ntripc_t *ntripc, int i)
static void urldecode(char *str)
static void closetcpcli(tcpcli_t *tcpcli)
static int statexntrip(ntrip_t *ntrip, char *msg)
static int reqntrip_s(ntrip_t *ntrip, char *msg)
static void swapfile(file_t *file, gtime_t time, char *msg)
static int statextcp(tcp_t *tcp, char *msg)
static int readmembuf(membuf_t *membuf, uint8_t *buff, int n, char *msg)
static int accept_nb(int sock, struct sockaddr *addr, socklen_t *len)
static int readftp(ftp_t *ftp, uint8_t *buff, int n, char *msg)
void strsetopt(const int *opt)
Set stream options.
static int waittcpsvr(tcpsvr_t *tcpsvr, char *msg)
static void decodetcppath(const char *path, char *addr, char *port, char *user, char *passwd, char *mntpnt, char *str)
static void closefile_(file_t *file)
static int encbase64(char *str, const uint8_t *byte, int n)
static void closeserial(serial_t *serial)
static int writentripc(ntripc_t *ntripc, uint8_t *buff, int n, char *msg)
static int statextcpsvr(tcpsvr_t *tcpsvr, char *msg)
void strlock(stream_t *stream)
Lock stream.
static void closeudpcli(udp_t *udpcli)
void strsetdir(const char *dir)
Set FTP/HTTP local directory.
void strinitcom(void)
Initialize stream communication system.
static tcpsvr_t * opentcpsvr(const char *path, char *msg)
static void swapclose(file_t *file)
static int readtcpcli(tcpcli_t *tcpcli, uint8_t *buff, int n, char *msg)
static membuf_t * openmembuf(const char *path, char *msg)
static void closentrip(ntrip_t *ntrip)
static int connect_nb(int sock, struct sockaddr *addr, socklen_t len)
static void * ftpthread(void *arg)
const char * formatstrs[32]
static void discontcp(tcp_t *tcp, int tcon)
static int statexudpsvr(udp_t *udpsvr, char *msg)
static int rspntrip_c(ntrip_t *ntrip, char *msg)
static ftp_t * openftp(const char *path, int type, char *msg)
static void closentripc(ntripc_t *ntripc)
static udp_t * openudpcli(const char *path, char *msg)
static int writetcpcli(tcpcli_t *tcpcli, uint8_t *buff, int n, char *msg)
#define BUFADD(p, rem,...)
static int stateftp(ftp_t *ftp)
static int statentrip(ntrip_t *ntrip)
static int statefile(file_t *file)
static gtime_t nextdltime(const int *topts, int stat)
static int stateserial(serial_t *serial)
static int stateudpcli(udp_t *udpcli)
static void time_str_http(char *buff)
static int waitntrip(ntrip_t *ntrip, char *msg)
static int setsock(int sock, char *msg)
static int gentcp(tcp_t *tcp, int type, char *msg)
static int reqntrip_c(ntrip_t *ntrip, char *msg)
static int accsock(tcpsvr_t *tcpsvr, char *msg)
static void send_rsp_ok(int ver, int sock)
void strclose(stream_t *stream)
Close stream.
static int gen_hex(const char *msg, uint8_t *buff)
int strwrite(stream_t *stream, uint8_t *buff, int n)
Write data to stream.
static int send_nb(int sock, uint8_t *buff, int n)
void strsetntripver(int ver)
Set default NTRIP version for new connections.
static udp_t * genudp(int type, int port, const char *saddr, char *msg)
static int parse_ntrip_query(char *mntpnt, char *host_override, int host_size)
static void rsp_ntripc(ntripc_t *ntripc, int i)
static int writeserial(serial_t *serial, uint8_t *buff, int n, char *msg)
static int statexfile(file_t *file, char *msg)
static int writentrip(ntrip_t *ntrip, uint8_t *buff, int n, char *msg)
void strsetproxy(const char *addr)
Set HTTP/NTRIP proxy address.
static int rspntrip_s(ntrip_t *ntrip, char *msg)
int stropen(stream_t *stream, int type, int mode, const char *path)
Open stream.
static int writemembuf(membuf_t *membuf, uint8_t *buff, int n, char *msg)
void strsync(stream_t *stream1, stream_t *stream2)
Sync streams.
void strunlock(stream_t *stream)
Unlock stream.
static int statexftp(ftp_t *ftp, char *msg)
static void updatetcpsvr(tcpsvr_t *tcpsvr, char *msg)
static int writeudpcli(udp_t *udpcli, uint8_t *buff, int n, char *msg)
#define DEFAULT_MEMBUF_SIZE
void strsum(stream_t *stream, uint64_t *inb, int *inr, uint64_t *outb, int *outr)
Get stream statistics summary.
static serial_t * openserial(const char *path, int mode, char *msg)
static char localdir[1024]
void strsendcmd(stream_t *str, const char *cmd)
Send receiver command to stream.
MRTKLIB Stream Module — stream I/O abstraction layer.
struct stream_tag stream_t
int rtk_uncompress(const char *file, char *uncfile)
Uncompress file (gzip/zip/tar/Hatanaka).
int execcmd(const char *cmd)
Execute command line by operating system shell.
void createdir(const char *path)
Create directory if not exists (recursively).
int reppath(const char *path, char *rpath, gtime_t time, const char *rov, const char *base)
Replace keywords in file path with date, time, rover and base station id.
MRTKLIB System Module — OS/filesystem utility functions.
void sleepms(int ms)
Sleep for specified milliseconds.
gtime_t gpst2time(int week, double sec)
Convert GPS week/tow to gtime_t.
void time2str(gtime_t t, char *s, int n)
Convert gtime_t struct to string.
gtime_t gpst2utc(gtime_t t)
Convert GPS time to UTC considering leap seconds.
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
double time2gpst(gtime_t t, int *week)
Convert gtime_t to GPS week/tow.
gtime_t timeadd(gtime_t t, double sec)
Add seconds to gtime_t.
char * time_str(gtime_t t, int n)
Get time string (not reentrant).
void timereset(void)
Reset time offset to zero.
void timeset(gtime_t t)
Set current time offset in UTC.
gtime_t utc2gpst(gtime_t t)
Convert UTC to GPS time considering leap seconds.
gtime_t timeget(void)
Get current time in UTC.
uint32_t tickget(void)
Get current tick in milliseconds.
MRTKLIB Time Module — GNSS time types and conversion functions.
void tracet(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message with elapsed time.
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
MRTKLIB Trace Module — debug trace and logging functions.
static int chunk_decode(chunk_dec_t *dec, const uint8_t **pin, int *pnin, uint8_t *out, int nout)
static int http_find_header(const uint8_t *buff, int nb, const char *name, char *val, int vmax)
static const char * stristr(const char *haystack, const char *needle)
static int http_header_end(const uint8_t *buff, int nb)
static int chunk_encode(uint8_t *out, int nout, const uint8_t *data, int ndata)
static void chunk_dec_init(chunk_dec_t *dec)
static int http_status_code(const uint8_t *buff, int nb)
char openpath[MAXSTRPATH]
GNSS time representation.