/* Serval Distributed Numbering Architecture (DNA) Copyright (C) 2012 Paul Gardner-Stephen 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. */ #include "serval.h" /* The challenge with making an interface for calling an external program to resolve a DID into a URI is that it really should be asynchronous, so that servald can't pause due to delays in looking up DIDs by helper applications. This can be partially mitigated by having a cache, so that at least for repeated requests the helper doesn't need to be called each time. This is very important because the DNA protocol relies on pre-emptive retries to ensure reception of a request over a lossy network. The second part of the solution is to create an asynchronous queue for requests, by passing them via file descriptor to a single persistent instance of the DNA helper application, and polling the output of that application for results, and then passing them out to their destinations. This ensures that the process is asynchronous and non-blocking, regardless of how much time the helper application requires. Then the helper will just be another file descriptor to poll in the main loop. */ static int dna_helper_stdin = -1; static int dna_helper_stdout = -1; int parseDnaReply(unsigned char *bytes, int count, char *did, char *name, char *uri) { bzero(did, SID_SIZE); bzero(name,64); bzero(uri,512); int i,l; l=0; for(i=0;i<511&&i=count||i>=511) return WHY("DNA response does not contain name field"); l=0; i++; for(;i<511&&i=count||i>=511) return WHY("DNA response does not contain URI field"); l=0; i++; for(;i<511&&i sizeof(buffer) - 1) return WHY("Command to helper is too long"); sigPipeFlag = 0; WRITE_STR(dna_helper_stdin, buffer); if (sigPipeFlag) { /* Assume broken pipe due to dead helper. Next request will cause it to be restarted. (Losing the current request is not a big problem, because DNA preemptively retries, anyway. XXX In fact, we should probably have a limit to the number of restarts in quick succession so that we don't waste lots of time with a buggy or suicidal helper. */ close(dna_helper_stdin); close(dna_helper_stdout); dna_helper_stdin = -1; dna_helper_stdout = -1; return -1; } return 0; } int dna_return_resolution(overlay_mdp_frame *mdp, unsigned char *fromSid, const char *did,const char *name, const char *uri) { /* copy SID out into source address of frame */ bcopy(fromSid,&mdp->out.src.sid[0],SID_SIZE); /* and build reply as did\nname\nURI */ snprintf((char *)&mdp->out.payload[0],512,"%s\n%s\n%s", did,name,uri); mdp->out.payload_length=strlen((char *)mdp->out.payload)+1; /* Dispatch response */ mdp->packetTypeAndFlags&=MDP_FLAG_MASK; mdp->packetTypeAndFlags|=MDP_TX; overlay_mdp_dispatch(mdp,0 /* system generated */, NULL,0); return 0; }