2013-11-21 02:12:59 +00:00
|
|
|
/*
|
|
|
|
Serval DNA directory service
|
2013-12-04 06:26:55 +00:00
|
|
|
Copyright (C) 2013 Serval Project Inc.
|
2013-11-21 02:12:59 +00:00
|
|
|
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
2012-09-14 02:20:45 +00:00
|
|
|
|
2013-10-18 00:04:43 +00:00
|
|
|
#ifdef HAVE_POLL_H
|
2012-09-14 02:20:45 +00:00
|
|
|
#include <poll.h>
|
2013-10-18 00:04:43 +00:00
|
|
|
#endif
|
2012-09-14 02:20:45 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
2013-12-09 07:15:47 +00:00
|
|
|
#include <inttypes.h>
|
2013-10-18 00:04:43 +00:00
|
|
|
#include "constants.h"
|
2013-11-28 06:23:12 +00:00
|
|
|
#include "serval.h"
|
2013-10-18 00:04:43 +00:00
|
|
|
#include "mdp_client.h"
|
2012-11-12 00:11:16 +00:00
|
|
|
#include "str.h"
|
2012-09-14 02:20:45 +00:00
|
|
|
|
2012-09-17 06:12:30 +00:00
|
|
|
struct item{
|
|
|
|
// simple tree structure
|
|
|
|
struct item *_left;
|
|
|
|
struct item *_right;
|
|
|
|
char key[32];
|
|
|
|
char value[128];
|
|
|
|
time_ms_t expires;
|
|
|
|
};
|
2012-09-14 02:20:45 +00:00
|
|
|
|
2012-11-12 00:08:24 +00:00
|
|
|
struct item *root=NULL;
|
2012-09-17 06:12:30 +00:00
|
|
|
|
|
|
|
static struct item *create_item(const char *key){
|
|
|
|
struct item *ret=calloc(1,sizeof(struct item));
|
|
|
|
strncpy(ret->key,key,sizeof(ret->key));
|
|
|
|
ret->key[sizeof(ret->key) -1]=0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-20 06:51:18 +00:00
|
|
|
static struct item *find_item(const char *key){
|
2012-09-17 06:12:30 +00:00
|
|
|
struct item *item = root;
|
|
|
|
|
|
|
|
while(item){
|
|
|
|
int c=strcmp(item->key, key);
|
|
|
|
if (c==0)
|
|
|
|
return item;
|
|
|
|
if (c<0){
|
|
|
|
item = item->_left;
|
|
|
|
}else{
|
|
|
|
item = item->_right;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-20 06:51:18 +00:00
|
|
|
static void add_item(char *key, char *value){
|
|
|
|
struct item *item = root, **last_ptr=&root;
|
|
|
|
while(item){
|
|
|
|
int c=strcmp(item->key, key);
|
|
|
|
if (c==0){
|
|
|
|
c=strcmp(item->value, value);
|
2012-11-12 00:38:08 +00:00
|
|
|
if (c==0){
|
|
|
|
item->expires = gettime_ms()+1200000;
|
2012-09-20 06:51:18 +00:00
|
|
|
return;
|
2012-11-12 00:38:08 +00:00
|
|
|
}
|
2012-09-20 06:51:18 +00:00
|
|
|
}
|
|
|
|
if (c<0){
|
|
|
|
last_ptr = &item->_left;
|
|
|
|
}else{
|
|
|
|
last_ptr = &item->_right;
|
|
|
|
}
|
|
|
|
item = *last_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*last_ptr = item = create_item(key);
|
|
|
|
|
2012-09-17 06:12:30 +00:00
|
|
|
strncpy(item->value,value,sizeof(item->value));
|
|
|
|
item->value[sizeof(item->value) -1]=0;
|
2012-09-18 02:56:30 +00:00
|
|
|
// expire after 20 minutes
|
|
|
|
item->expires = gettime_ms()+1200000;
|
|
|
|
// used by tests
|
|
|
|
fprintf(stderr, "PUBLISHED \"%s\" = \"%s\"\n", key, value);
|
2012-09-14 02:20:45 +00:00
|
|
|
}
|
|
|
|
|
2012-11-06 19:48:54 +00:00
|
|
|
static void add_record(int mdp_sockfd){
|
2012-09-14 02:20:45 +00:00
|
|
|
int ttl;
|
|
|
|
overlay_mdp_frame mdp;
|
|
|
|
|
2012-11-06 19:48:54 +00:00
|
|
|
if (overlay_mdp_recv(mdp_sockfd, &mdp, MDP_PORT_DIRECTORY, &ttl))
|
2012-09-14 02:20:45 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-18 02:56:30 +00:00
|
|
|
if (mdp.packetTypeAndFlags&MDP_NOCRYPT){
|
|
|
|
fprintf(stderr, "Only encrypted packets will be considered for publishing\n");
|
2012-09-17 06:12:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-09-14 05:12:15 +00:00
|
|
|
|
2012-09-14 02:20:45 +00:00
|
|
|
// make sure the payload is a NULL terminated string
|
2014-02-05 04:56:56 +00:00
|
|
|
mdp.out.payload[mdp.out.payload_length]=0;
|
2012-09-14 02:20:45 +00:00
|
|
|
|
2014-02-05 04:56:56 +00:00
|
|
|
char *did=(char *)mdp.out.payload;
|
2012-09-14 02:20:45 +00:00
|
|
|
int i=0;
|
2014-02-05 04:56:56 +00:00
|
|
|
while(i<mdp.out.payload_length && mdp.out.payload[i] && mdp.out.payload[i]!='|')
|
2012-09-14 02:20:45 +00:00
|
|
|
i++;
|
2014-02-05 04:56:56 +00:00
|
|
|
mdp.out.payload[i]=0;
|
|
|
|
char *name = (char *)mdp.out.payload+i+1;
|
|
|
|
char *sid = alloca_tohex_sid_t(mdp.out.src.sid);
|
2012-09-14 02:20:45 +00:00
|
|
|
|
|
|
|
// TODO check that did is a valid phone number
|
|
|
|
|
|
|
|
char url[256];
|
2012-09-21 05:47:56 +00:00
|
|
|
snprintf(url, sizeof(url), "sid://%s/local/%s|%s|%s", sid, did, did, name);
|
2012-09-20 06:51:18 +00:00
|
|
|
add_item(did, url);
|
|
|
|
}
|
|
|
|
|
2012-11-16 05:09:33 +00:00
|
|
|
static void respond(char *token, struct item *item, char *key){
|
2012-09-20 06:51:18 +00:00
|
|
|
if (!item)
|
|
|
|
return;
|
2012-11-16 05:09:33 +00:00
|
|
|
|
|
|
|
int c = strcmp(item->key, key);
|
|
|
|
if (c<=0)
|
|
|
|
respond(token, item->_left, key);
|
|
|
|
if (c==0 && item->expires > gettime_ms())
|
2012-09-20 06:51:18 +00:00
|
|
|
printf("%s|%s|\n",token,item->value);
|
2012-11-16 05:09:33 +00:00
|
|
|
if (c>=0)
|
|
|
|
respond(token, item->_right, key);
|
2012-09-14 02:20:45 +00:00
|
|
|
}
|
|
|
|
|
2012-09-17 06:12:30 +00:00
|
|
|
static void process_line(char *line){
|
2012-09-14 02:20:45 +00:00
|
|
|
char *token=line;
|
|
|
|
char *p=line;
|
|
|
|
while(*p && *p!='|') p++;
|
|
|
|
*p++=0;
|
|
|
|
char *did = p;
|
|
|
|
while(*p && *p!='|') p++;
|
|
|
|
*p++=0;
|
|
|
|
|
2012-11-16 05:09:33 +00:00
|
|
|
respond(token, find_item(did), did);
|
2012-09-18 02:56:30 +00:00
|
|
|
printf("DONE\n");
|
|
|
|
fflush(stdout);
|
2012-09-14 02:20:45 +00:00
|
|
|
}
|
|
|
|
|
2012-09-17 06:12:30 +00:00
|
|
|
static void resolve_request(){
|
2012-09-14 02:20:45 +00:00
|
|
|
static char line_buff[1024];
|
|
|
|
static int line_pos=0;
|
|
|
|
|
2012-09-27 06:57:37 +00:00
|
|
|
set_nonblock(STDIN_FILENO);
|
|
|
|
|
2012-09-14 02:20:45 +00:00
|
|
|
int bytes = read(STDIN_FILENO, line_buff + line_pos, sizeof(line_buff) - line_pos);
|
2012-09-27 06:57:37 +00:00
|
|
|
|
|
|
|
set_block(STDIN_FILENO);
|
|
|
|
|
2012-09-14 02:20:45 +00:00
|
|
|
int i = line_pos;
|
|
|
|
int processed=0;
|
|
|
|
line_pos+=bytes;
|
|
|
|
char *line_start=line_buff;
|
|
|
|
|
|
|
|
for (;i<line_pos;i++){
|
|
|
|
if (line_buff[i]=='\n'){
|
|
|
|
line_buff[i]=0;
|
|
|
|
if (*line_start)
|
|
|
|
process_line(line_start);
|
|
|
|
processed=i+1;
|
|
|
|
line_start = line_buff + processed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processed){
|
|
|
|
// squash unprocessed data back to the start of the buffer
|
|
|
|
line_pos -= processed;
|
|
|
|
bcopy(line_buff, line_start, line_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 02:06:00 +00:00
|
|
|
int main(void){
|
2012-09-14 02:20:45 +00:00
|
|
|
struct pollfd fds[2];
|
2012-11-06 19:48:54 +00:00
|
|
|
int mdp_sockfd;
|
|
|
|
|
|
|
|
if ((mdp_sockfd = overlay_mdp_client_socket()) < 0)
|
|
|
|
return WHY("Cannot create MDP socket");
|
2012-09-14 02:20:45 +00:00
|
|
|
|
|
|
|
// bind for incoming directory updates
|
2013-02-15 09:04:24 +00:00
|
|
|
sid_t srcsid;
|
2012-11-06 19:48:54 +00:00
|
|
|
|
|
|
|
if (overlay_mdp_getmyaddr(mdp_sockfd, 0, &srcsid)) {
|
|
|
|
overlay_mdp_client_close(mdp_sockfd);
|
2012-09-18 02:56:30 +00:00
|
|
|
return WHY("Could not get local address");
|
2012-11-06 19:48:54 +00:00
|
|
|
}
|
|
|
|
if (overlay_mdp_bind(mdp_sockfd, &srcsid, MDP_PORT_DIRECTORY)) {
|
|
|
|
overlay_mdp_client_close(mdp_sockfd);
|
2012-09-18 02:56:30 +00:00
|
|
|
return WHY("Could not bind to MDP socket");
|
2012-11-06 19:48:54 +00:00
|
|
|
}
|
2012-09-14 02:20:45 +00:00
|
|
|
|
|
|
|
fds[0].fd = STDIN_FILENO;
|
|
|
|
fds[0].events = POLLIN;
|
2012-11-06 19:48:54 +00:00
|
|
|
fds[1].fd = mdp_sockfd;
|
2012-09-14 02:20:45 +00:00
|
|
|
fds[1].events = POLLIN;
|
|
|
|
|
2012-09-18 02:56:30 +00:00
|
|
|
printf("STARTED\n");
|
|
|
|
fflush(stdout);
|
|
|
|
|
2012-09-14 02:20:45 +00:00
|
|
|
while(1){
|
2012-09-18 02:56:30 +00:00
|
|
|
int r = poll(fds, 2, 100);
|
2012-09-14 02:20:45 +00:00
|
|
|
if (r>0){
|
|
|
|
if (fds[0].revents & POLLIN)
|
2012-11-06 19:48:54 +00:00
|
|
|
resolve_request();
|
2012-09-14 02:20:45 +00:00
|
|
|
if (fds[1].revents & POLLIN)
|
2012-11-06 19:48:54 +00:00
|
|
|
add_record(mdp_sockfd);
|
2012-09-14 02:20:45 +00:00
|
|
|
|
|
|
|
if (fds[0].revents & (POLLHUP | POLLERR))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-06 19:48:54 +00:00
|
|
|
overlay_mdp_client_close(mdp_sockfd);
|
2012-09-14 02:20:45 +00:00
|
|
|
return 0;
|
2013-02-15 09:04:24 +00:00
|
|
|
}
|