/*************************************************************************** * map_webload.c * * Thu Jul 19 19:00:10 2010 * Copyright 2007 Steffen Pohle * steffen@gulpe.de ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "map.h" #include "memoryleak.h" #include "system.h" #include "osmroute.h" #ifndef NET_HOSTLEN #define NET_HOSTLEN 128 #endif #ifndef NET_PORTLEN #define NET_PORTLEN 5 #endif #include #include #include #include #include #include #include #if defined(_WINDOWS_) || defined(_WINDOWSCE_) #include #else #if !defined(ANDROID) #include #endif #include #include #include #include #endif #if defined(_WINDOWS_) || defined(_WINDOWSCE_) #define _sockaddr sockaddr #else #define _sockaddr sockaddr_in6 #endif #include "system.h" // dns.c char *dns_net_getip (char *host); int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, struct _sockaddr *sAddr); // tcp.c void tcp_close (int sock); int tcp_send (int sock, char *data, int len); int tcp_connect (char *host, char *port); int tcp_get (int tcpsocket, int len, char *data); void unblock_socket (int sock); /********************************************* * tcp ip stuff */ char dnsip[NET_HOSTLEN]; int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, struct _sockaddr *sAddr) { #if defined(_WINDOWS_) || defined(_WINDOWSCE_) struct hostent *he; char txt[255]; if (host[0] == 0 || port[0] == 0) { /* we have to complete server and port from the sAddr */ strncpy (host, inet_ntoa (((struct sockaddr_in *) sAddr)->sin_addr), hostlen); sprintf (txt, "%d", ntohs (((struct sockaddr_in *) sAddr)->sin_port)); strncpy (port, txt, portlen); } else { /* we have to complete the sAddr struct */ if ((he = gethostbyname (host)) == NULL) { // get the host info d_printf ("dns_filladdr (gethostbyname) %s", strerror (errno)); return -1; } ((struct sockaddr_in *) sAddr)->sin_family = ai_family; // host byte order ((struct sockaddr_in *) sAddr)->sin_port = htons (atoi (port)); // short, network byte order ((struct sockaddr_in *) sAddr)->sin_addr = *((struct in_addr *) he->h_addr); memset (&(((struct sockaddr_in *) sAddr)->sin_zero), '\0', 8); // zero the rest of the struct } #else struct addrinfo hints, *res; int err, i, addrlen; if (host[0] == 0 || port[0] == 0) { /* we have to complete server and port from the sAddr */ if (ai_family == PF_INET) addrlen = sizeof (struct sockaddr_in); else addrlen = sizeof (struct sockaddr_in6); bzero (host, hostlen); bzero (port, portlen); if ((err = getnameinfo ((struct sockaddr *) sAddr, addrlen, host, hostlen, port, portlen, NI_NUMERICHOST | NI_NUMERICSERV)) < 0) { printf ("dns_filladdr (getnameinfo): %s\n", gai_strerror (err)); return -1; } if (strstr (host, "::ffff:") != NULL) { for (i = 0; host[i + 7] != 0; i++) host[i] = host[i+7]; host[i] = 0; } } else { /* we have to complete the sAddr struct */ bzero (&hints, sizeof (struct addrinfo)); hints.ai_family = ai_family; hints.ai_socktype = SOCK_DGRAM; if ((err = getaddrinfo (host, port, &hints, &res)) < 0) { d_printf ("dns_filladdr (getaddrinfo):%s\n", gai_strerror (err)); return -1; } // i hope it's enough to copy only sizeof (struct sockaddr) ? memcpy (sAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo (res); } #endif return 0; }; char * dns_net_getip (char *host) { struct hostent *hAddr; hAddr = gethostbyname (host); if (hAddr == NULL) return NULL; strncpy (dnsip, inet_ntoa (*((struct in_addr *) hAddr->h_addr)), NET_HOSTLEN); return dnsip; }; void unblock_socket (int sock) { #if defined(_WINDOWS_) || defined(_WINDOWSCE_) /* Windows Code of the tcp part is not needed, we will work over select */ #else int flags; /* Linux Code of the tcp part * get current socket flags */ if ((flags = fcntl (sock, F_GETFL)) == -1) { perror ("GETFL"); } /* set socket to non-blocking */ flags |= O_NDELAY; if (fcntl (sock, F_SETFL, flags) == -1) { perror ("SETFL"); } #endif }; /* close TCP Socket */ void tcp_close (int sock) { close (sock); #if defined (_WINDOWS_) || defined (_WINDOWSCE_) WSACleanup (); #endif }; /* send date to an TCP socket*/ int tcp_send (int sock, char *data, int len) { return send (sock, data, len, 0); }; /* connect to an server */ int tcp_connect (char *host, char *port) { int err, sock = -1; #if defined(_WINDOWS_) || defined(_WINDOWSCE_) /* Windows Code of the tcp part */ struct hostent *he; struct sockaddr_in adresse; WSADATA wsaData; if ((err = WSAStartup (MAKEWORD (1, 1), &wsaData)) != 0) { d_printf ("WSAStartup failed.\n"); exit (1); } he = gethostbyname (host); if (he == NULL) { d_printf ("Error: Could not get hostname (%s)\n", host); return -1; } /* adressen vorbereiten */ adresse.sin_family = AF_INET; adresse.sin_port = htons (atoi (port)); memcpy (&adresse.sin_addr, he->h_addr_list[0], sizeof (adresse.sin_addr)); /* Socket an Filediscriptor binden, aufbaun der verbindung */ if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0) { d_printf ("ERROR: could not get socket.\n"); return -1; } if (connect (sock, (struct sockaddr *) &adresse, sizeof (adresse))) { d_printf ("ERROR: could not connect.\n"); return -1; } #else /* Linux Code of the tcp part */ struct addrinfo hints, *res, *sres; bzero (&hints, sizeof (struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo (host, port, &hints, &res)) == 0) { sres = res; if ((sock = socket (sres->ai_family, sres->ai_socktype, 0)) < 0) { d_printf ("%d=socket(PF_INET, SOCK_STREAM, 0)\n", sock); sock = -1; freeaddrinfo (res); return -1; } if (connect (sock, res->ai_addr, res->ai_addrlen) < 0) { d_printf ("connect error\n"); close (sock); freeaddrinfo (res); return -1; } unblock_socket (sock); freeaddrinfo (res); } else { d_printf ("getaddrinfo:%s\n", gai_strerror (err)); } #endif return sock; }; /* gets some data from socket, if there are any data aviable */ int tcp_get (int tcpsocket, int len, char *data) { int len_ = len; #if defined(_WINDOWS_) || defined(_WINDOWSCE_) /* Windows Code of the tcp part */ fd_set rfds; struct timeval tval; FD_ZERO (&rfds); FD_SET (tcpsocket, &rfds); tval.tv_sec = 0; tval.tv_usec = 100; if (select (tcpsocket + 1, &rfds, NULL, NULL, &tval)) { len_ = recv (tcpsocket, data, len, 0); if (len_ == 0) { return -1; } else if (len_ < 0) { d_printf ("%s:%d tcp_get returned something different than the expected. len_:%d", __FILE__, __LINE__, len_); return -2; } data[len_] = 0; } else return 0; #else /* Linux Code of the tcp part */ len_ = read (tcpsocket, data, len_); if (len_ < 0 && errno == EAGAIN) len_ = 0; else if (len_ < 0 && errno != EAGAIN) { d_printf ("tcp_get:%s", strerror (errno)); len_ = -2; } else if (len_ == 0) len_ = -1; #endif return len_; } #define HOST "sposmroute.gulpe.de" #define PORT "80" #define URLPREFIX "/map/" #define BUFFERSIZE 4096 int map_webload (char *remotefn, char *localfn, char *statustext) { char outdata[BUFFERSIZE]; char indata[BUFFERSIZE]; char host[NET_HOSTLEN]; char port[NET_PORTLEN]; char tmpfn[LEN_FILENAME]; char text[255]; int len, sock, i = 0, data = 0, fd = 0, filelen = 0, filesize = -1; int breakup; char _statustext[255]; time_t to = time(NULL); if (statustext == NULL) _statustext[0] = 0; else strncpy (_statustext, statustext, 255); d_printf ("map_webload started"); app.status = APPSTATUS_loadfromweb; strncpy (host, HOST, NET_HOSTLEN); strncpy (port, PORT, NET_PORTLEN); sock = tcp_connect (host, port); if (sock <= 0) { d_printf ("map_webload: could not load file '%s' from web", remotefn); } else { snprintf (outdata, BUFFERSIZE, "GET %s%s HTTP/1.0\nUser-Agent: sposmroute map-dl \nHost: %s\n\n", URLPREFIX, remotefn, HOST); tcp_send (sock, outdata, strlen (outdata)); map_save_all (); map_clear (); i = data = fd = filelen = breakup = 0; while (!breakup && (len = tcp_get (sock, BUFFERSIZE-1, indata)) >= 0) { if (fd && data && len > 0) filelen += write (fd, indata, len); else { indata[len] = 0; while (i < len -4 && data == 0) { if (fd && indata[i] == 0x0d && indata [i+1] == 0x0a && indata [i+2] == 0x0d && indata [i+3] == 0x0a) { data = 1; i = i + 4; d_printf ("download of file http://%s:%s%s%s started.", host, port, URLPREFIX, remotefn); filelen += write (fd, indata+i, len-i); } else if (strncmp (indata+i, "Content-Length:", 15) == 0) { filesize = atoi (indata+i+16); i = i + 16; } else if (strncmp (indata+i, "403 ", 4) == 0) break; else if (strncmp (indata+i, "200 ", 4) == 0) { sprintf (tmpfn, "%s.tmp", localfn); #if defined(_WINDOWS_) || defined (_WINDOWSCE_) fd = open (tmpfn, O_CREAT|O_RDWR | _O_BINARY, 0644); #else fd = open (tmpfn, O_CREAT|O_RDWR, 0644); #endif if (fd <= 0) { d_printf ("%s could not save file. [%s]", __FUNCTION__, tmpfn); breakup = 1; } i++; } else i++; } } if (to != time(NULL)) { to = time(NULL); if (filesize > 0) sprintf (text, _("%s%d/%dkb loaded"), _statustext, filelen/1024, filesize/1024); else sprintf (text, _("%s%dkb loaded"), _statustext, filelen/1024); main_wnd_update (); } } close (fd); tcp_close (sock); /* check if we had a valid file and rename the tmp to the real file */ if (len == -1) { if (file_exist (localfn)) unlink (localfn); rename (tmpfn, localfn); d_printf ("map_webload finished to %s", localfn); } else { d_printf ("map_webload error"); } /* delete tempory file */ if (file_exist (tmpfn)) unlink (tmpfn); } app.status = APPSTATUS_nothing; app_status(NULL, -1); map_clear (); map_init (); draw_redrawmap (); draw (); return 0; };