summaryrefslogtreecommitdiff
path: root/attic/historic/anode/libanode/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'attic/historic/anode/libanode/zone.c')
-rw-r--r--attic/historic/anode/libanode/zone.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/attic/historic/anode/libanode/zone.c b/attic/historic/anode/libanode/zone.c
new file mode 100644
index 00000000..a6e397ae
--- /dev/null
+++ b/attic/historic/anode/libanode/zone.c
@@ -0,0 +1,184 @@
+/* libanode: the Anode C reference implementation
+ * Copyright (C) 2009-2010 Adam Ierymenko <adam.ierymenko@gmail.com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "impl/types.h"
+#include "impl/misc.h"
+#include "impl/dictionary.h"
+#include "impl/environment.h"
+#include "impl/http_client.h"
+#include "anode.h"
+
+static const char *_MONTHS[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+static const char *_DAYS_OF_WEEK[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
+static inline unsigned long get_file_time_for_http(const char *path,char *buf,unsigned int len)
+{
+ struct stat st;
+ struct tm *gmt;
+
+ if (!stat(path,(struct stat *)&st)) {
+ gmt = gmtime(&st.st_mtime);
+ if (gmt) {
+ snprintf(buf,len,"%s, %d %s %d %d:%d:%d GMT",
+ _DAYS_OF_WEEK[gmt->tm_wday],
+ gmt->tm_mday,
+ _MONTHS[gmt->tm_mon],
+ (1900 + gmt->tm_year),
+ gmt->tm_hour,
+ gmt->tm_min,
+ gmt->tm_sec);
+ buf[len - 1] = (char)0;
+ return (unsigned long)st.st_size;
+ }
+ }
+
+ return 0;
+}
+
+struct AnodeZoneLookupJob
+{
+ char cached_zone_file[2048];
+ struct AnodeDictionary *zone_dict;
+ AnodeZone zone;
+ void *ptr;
+ void (*zone_lookup_handler)(void *,const AnodeZone *,AnodeZoneFile *);
+ int had_cached_zone;
+};
+
+static void AnodeZone_lookup_http_handler(struct AnodeHttpClient *client)
+{
+ char *data_tmp;
+ struct AnodeZoneLookupJob *job = (struct AnodeZoneLookupJob *)client->ptr[0];
+ FILE *zf;
+
+ if ((client->response.code == 200)&&(client->response.data_length > 0)) {
+ zf = fopen(job->cached_zone_file,"w");
+ if (zf) {
+ fwrite(client->response.data,1,client->response.data_length,zf);
+ fclose(zf);
+ }
+
+ data_tmp = (char *)malloc(client->response.data_length + 1);
+ Anode_memcpy((void *)data_tmp,client->response.data,client->response.data_length);
+ data_tmp[client->response.data_length] = (char)0;
+
+ AnodeDictionary_clear(job->zone_dict);
+ AnodeDictionary_read(
+ job->zone_dict,
+ data_tmp,
+ "\r\n",
+ "=",
+ ";",
+ '\\',
+ 1,1);
+
+ free((void *)data_tmp);
+
+ job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)job->zone_dict);
+ } else if (job->had_cached_zone)
+ job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)job->zone_dict);
+ else {
+ AnodeDictionary_destroy(job->zone_dict);
+ free((void *)job->zone_dict);
+ job->zone_lookup_handler(job->ptr,&job->zone,(AnodeZoneFile *)0);
+ }
+
+ free((void *)job);
+ AnodeHttpClient_free(client);
+}
+
+void AnodeZone_lookup(
+ AnodeTransportEngine *transport,
+ const AnodeZone *zone,
+ void *ptr,
+ void (*zone_lookup_handler)(void *,const AnodeZone *,AnodeZone *))
+{
+ char cached_zones_folder[2048];
+ char cached_zone_file[2048];
+ char if_modified_since[256];
+ unsigned long file_size;
+ struct AnodeZoneLookupJob *job;
+ struct AnodeHttpClient *client;
+ char *file_data;
+ FILE *zf;
+
+ if (Anode_get_cache_sub("zones",cached_zones_folder,sizeof(cached_zones_folder))) {
+ snprintf(cached_zone_file,sizeof(cached_zone_file),"%s%c%.2x%.2x%.2x%.2x.z",cached_zones_folder,ANODE_PATH_SEPARATOR,(unsigned int)zone->bits[0],(unsigned int)zone->bits[1],(unsigned int)zone->bits[2],(unsigned int)zone->bits[3]);
+ cached_zone_file[sizeof(cached_zone_file)-1] = (char)0;
+
+ job = (struct AnodeZoneLookupJob *)malloc(sizeof(struct AnodeZoneLookupJob));
+ Anode_str_copy(job->cached_zone_file,cached_zone_file,sizeof(job->cached_zone_file));
+ job->zone_dict = (struct AnodeDictionary *)malloc(sizeof(struct AnodeDictionary));
+ AnodeDictionary_init(job->zone_dict,0);
+ job->zone.bits[0] = zone->bits[0];
+ job->zone.bits[1] = zone->bits[1];
+ job->zone.bits[2] = zone->bits[2];
+ job->zone.bits[3] = zone->bits[3];
+ job->ptr = ptr;
+ job->zone_lookup_handler = zone_lookup_handler;
+ job->had_cached_zone = 0;
+
+ client = AnodeHttpClient_new(transport);
+
+ Anode_str_copy(client->uri.scheme,"http",sizeof(client->uri.scheme));
+ snprintf(client->uri.host,sizeof(client->uri.host),"a--%.2x%.2x%.2x%.2x.net",(unsigned int)zone->bits[0],(unsigned int)zone->bits[1],(unsigned int)zone->bits[2],(unsigned int)zone->bits[3]);
+ client->uri.host[sizeof(client->uri.host)-1] = (char)0;
+ Anode_str_copy(client->uri.path,"/z",sizeof(client->uri.path));
+
+ client->handler = &AnodeZone_lookup_http_handler;
+ client->ptr[0] = job;
+
+ if ((file_size = get_file_time_for_http(cached_zone_file,if_modified_since,sizeof(if_modified_since)))) {
+ zf = fopen(cached_zone_file,"r");
+ if (zf) {
+ AnodeDictionary_put(&client->headers,"If-Modified-Since",if_modified_since);
+ file_data = (char *)malloc(file_size + 1);
+ if (fread((void *)file_data,1,file_size,zf)) {
+ file_data[file_size] = (char)0;
+ AnodeDictionary_read(
+ job->zone_dict,
+ file_data,
+ "\r\n",
+ "=",
+ ";",
+ '\\',
+ 1,1);
+ job->had_cached_zone = 1;
+ }
+ free((void *)file_data);
+ fclose(zf);
+ }
+ }
+
+ AnodeHttpClient_send(client);
+ } else zone_lookup_handler(ptr,zone,(AnodeZone *)0);
+}
+
+const char *AnodeZoneFile_get(AnodeZoneFile *zone,const char *key)
+{
+ return AnodeDictionary_get((struct AnodeDictionary *)zone,key);
+}
+
+void AnodeZoneFile_free(AnodeZoneFile *zone)
+{
+ AnodeDictionary_destroy((struct AnodeDictionary *)zone);
+ free((void *)zone);
+}