Developer Area

Changeset 567

Show
Ignore:
Timestamp:
11/09/09 11:07:04 (4 years ago)
Author:
jonmaycock
Message:

New lookup structure.

Location:
apps/blackberry/branches/1.5/blackberry/src/org/telnic/blackberry/lookup
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • apps/blackberry/branches/1.5/blackberry/src/org/telnic/blackberry/lookup/LookupResult.java

    r339 r567  
    3232 * 
    3333 * @author Ben Dowling, Jonathan Maycock 
    34  * @version $Id: LookupResult.java,v 1.12 2009/03/05 11:41:48 jm2 Exp $ 
     34 * @version $Id: LookupResult.java,v 1.13 2009/11/06 11:54:52 jm2 Exp $ 
    3535 */ 
    3636public class LookupResult implements Persistable 
     
    7272    private Vector locRecords; 
    7373     
    74     /** 
    75      * The nInfo records. 
    76      */ 
    77     private Vector nInfoRecords; 
    78  
    7974    // stores the time (in seconds) that this record was last updated 
    8075    /** 
     
    159154        return locRecords; 
    160155    } 
    161  
    162  
    163     /** 
    164      * Sets the nInfo records. 
    165      * 
    166      * @param nInfoRecords the nInfoRecords 
    167      */ 
    168     public synchronized void setNInfoRecords (final Vector nInfoRecords) 
    169     { 
    170         this.nInfoRecords = nInfoRecords; 
    171  
    172         updated = System.currentTimeMillis() / THOUSAND; 
    173  
    174         setMinTtl( this.nInfoRecords ); 
    175     } 
    176156     
    177     /** 
    178      * Gets the NINFO records. 
    179      * 
    180      * @return the ninfo records 
    181      */ 
    182     public synchronized Vector getNInfoRecords () 
    183     { 
    184         return nInfoRecords; 
    185     } 
    186  
    187  
    188157    /** 
    189158     * Sets the loc records. 
     
    233202    public long validFor () 
    234203    { 
    235         if (txtRecords == null && naptrRecords == null && locRecords == null && nInfoRecords == null) 
     204        if (txtRecords == null && naptrRecords == null && locRecords == null) 
    236205        { 
    237206            ttl = 0; 
    238207        } 
    239         else if (txtRecords.isEmpty() && naptrRecords.isEmpty() && locRecords.isEmpty() && nInfoRecords.isEmpty()) 
     208        else if (txtRecords.isEmpty() && naptrRecords.isEmpty() && locRecords.isEmpty()) 
    240209        { 
    241210            ttl = 0; 
  • apps/blackberry/branches/1.5/blackberry/src/org/telnic/blackberry/lookup/LookupTelname.java

    r339 r567  
    2727import org.telnic.blackberry.TelnameApp; 
    2828import org.telnic.blackberry.dns.DNS; 
     29import org.telnic.blackberry.dns.DNSTxtDDSResourceRecord; 
     30import org.telnic.blackberry.dns.DNSTxtHeaderResourceRecord; 
     31import org.telnic.blackberry.dns.DNSTxtKeywordResourceRecord; 
     32import org.telnic.blackberry.dns.DNSTxtLongLabelResourceRecord; 
     33import org.telnic.blackberry.dns.DNSTxtPDDXResourceRecord; 
    2934import org.telnic.blackberry.dns.LookupCompleteActionListener; 
    3035import org.telnic.blackberry.dns.LookupWorkerCompletedListener; 
     
    3843 * 
    3944 * @author Ben Dowling, Jonathan Maycock 
    40  * @version $Id: LookupTelname.java,v 1.21 2009/01/29 16:47:04 jm2 Exp $ 
     45 * @version $Id: LookupTelname.java,v 1.22 2009/11/06 11:55:17 jm2 Exp $ 
    4146 */ 
    4247public class LookupTelname implements LookupWorkerCompletedListener, Cancellable 
     
    7277     */ 
    7378    public static final int STATUS_TIMEOUT = 5; 
    74  
    75     /** 
    76      * The telname. 
    77      */ 
    78     private String telname; 
    79  
    80     /** 
    81      * The top level telname for LOC/TXT. 
    82      */ 
    83     private String telnameTop; 
     79     
     80    /** 
     81     * The Keyword Prefix. 
     82     */ 
     83    public static final String KEYWORD_PREFIX = "_kw"; 
     84 
     85    /** 
     86     * The private domain.. 
     87     */ 
     88    private String privateDomain; 
     89 
     90    /** 
     91     * The public domain. 
     92     */ 
     93    private String publicDomain; 
    8494 
    8595    /** 
     
    133143    private int type = 0; 
    134144     
     145    /** 
     146     * The version of the domain being looked up. 
     147     */ 
     148    private boolean isVersionOne = false; 
     149     
     150    /** 
     151     * The availability of keywords for this domain. 
     152     */ 
     153    private boolean keywordsAvailable = false; 
     154     
     155    /** 
     156     * The private availability for this domain. 
     157     */ 
     158    private boolean privateDataAvailable = false; 
    135159 
    136160    /** 
     
    144168    private int parentStatus; 
    145169     
    146     private boolean naptrDone = false; 
    147     private boolean txtDone = false; 
    148     private boolean locDone = false; 
    149     private boolean nInfoDone = false; 
     170    /** 
     171     * Boolean indicating whether this is a version lookup. 
     172     */ 
     173    private boolean versionLookup = false; 
    150174 
    151175    ConnectionManager cm; 
     
    168192        completeListener = l; 
    169193    } 
    170  
     194     
     195    /** 
     196     * Perform a lookup for a version check. 
     197     *  
     198     * @param telnameVal the version domain. 
     199     */ 
     200    public void performVersionLookup (final String telnameVal) 
     201    { 
     202        this.versionLookup = true; 
     203        performLookup( telnameVal ); 
     204    } 
     205     
     206    /** 
     207     * Perform a lookup of a public domain. 
     208     *  
     209     * @param telnameVal the public domain. 
     210     */ 
     211    public void performLookup (final String telnameVal) 
     212    { 
     213        performLookup( telnameVal, telnameVal ); 
     214    } 
    171215 
    172216    /** 
     
    174218     * 
    175219     * @param telnameVal the telnameVal 
    176      */ 
    177     public void performLookup (final String telnameVal) 
     220     * @param telnameTopVal the top level domain 
     221     */ 
     222    public void performLookup (final String telnameVal, final String telnameTopVal) 
    178223    { 
    179224        Logger.logMessage( "Performing lookup of " + telnameVal, Options.KEY_LOG_APPLICATION ); 
     
    183228            return; 
    184229        } 
    185          
    186         naptrDone = false; 
    187         txtDone = false; 
    188         locDone = false; 
    189         nInfoDone = false; 
    190  
    191         this.telname = telnameVal; 
    192         this.telnameTop = telnameVal; 
     230 
     231        this.privateDomain = telnameVal; 
     232        this.publicDomain = telnameTopVal; 
    193233 
    194234        cancelled = false; 
     
    212252            UiApplication.getUiApplication().invokeLater( new Runnable() 
    213253            { 
     254 
    214255                public void run () 
    215256                { 
     
    230271                    lookupResult = new LookupResult( telnameVal ); 
    231272                    cm = TelnameApp.getDnsConnectionManager(); 
    232                     performNaptrLookup( telnameVal );                     
    233                 } 
    234             } ); 
    235         } 
    236         // if we don't have network coverage return the 
    237         // cachedResult which could be expired or null 
    238         else if (!cancelled) 
    239         { 
    240             Logger.logMessage( "No network - returning cache", Options.KEY_LOG_NETWORK ); 
    241             // there is no cached result - but no network coverage 
    242             // either so no point trying to do a lookup 
    243  
    244             status = LookupTelname.STATUS_NO_NETWORK; 
    245  
    246             UiApplication.getUiApplication().invokeLater( new Runnable() 
    247             { 
    248                 public void run () 
    249                 {                     
    250                     completeListener.lookupTelnameComplete( cachedResult ); 
    251                 } 
    252             } ); 
    253         } 
    254     } 
    255  
    256     /** 
    257      * Perform lookup. 
    258      * 
    259      * @param telnameVal the telnameVal 
    260      * @param telnameTopVal the top level domain 
    261      */ 
    262     public void performLookup (final String telnameVal, final String telnameTopVal) 
    263     { 
    264         Logger.logMessage( "Performing lookup of " + telnameVal, Options.KEY_LOG_APPLICATION ); 
    265         if (completeListener == null) 
    266         { 
    267             // no point doing any work if nobody wants to know the result! 
    268             return; 
    269         } 
    270  
    271         this.telname = telnameVal; 
    272         this.telnameTop = telnameTopVal; 
    273  
    274         cancelled = false; 
    275  
    276         // check if we have sufficient network coverage to open a connection 
    277         final boolean hasCoverage = (RadioInfo.getState() == RadioInfo.STATE_ON) 
    278             && (RadioInfo.getSignalLevel() != RadioInfo.LEVEL_NO_COVERAGE); 
    279  
    280         // check the cache for lookup results 
    281         if (!cancelled) 
    282         { 
    283             Logger.logMessage( "Checking for cached result: " + LookupResultDataStore.numResults(), 
    284                 Options.KEY_LOG_APPLICATION ); 
    285             cachedResult = LookupResultDataStore.getLookupResult( telnameVal ); 
    286         } 
    287  
    288         // if we have a valid cache result return it 
    289         if (!cancelled && cachedResult != null && cachedResult.isValid()) 
    290         { 
    291             Logger.logMessage( "Valid cached result found", Options.KEY_LOG_APPLICATION ); 
    292             UiApplication.getUiApplication().invokeLater( new Runnable() 
    293             { 
    294  
    295                 public void run () 
    296                 { 
    297                     Logger.logMessage( "Returning Cached Result", Options.KEY_LOG_APPLICATION );                     
    298                     completeListener.lookupTelnameComplete( cachedResult ); 
    299                 } 
    300             } ); 
    301         } 
    302         // otherwise try and lookup a new result 
    303         else if (!cancelled && hasCoverage) 
    304         { 
    305             Logger.logMessage( "Trying lookup", Options.KEY_LOG_APPLICATION ); 
    306  
    307             UiApplication.getUiApplication().invokeLater( new Runnable() 
    308             { 
    309                 public void run () 
    310                 { 
    311                     lookupResult = new LookupResult( telnameVal ); 
    312                     cm = TelnameApp.getDnsConnectionManager(); 
    313                     performNaptrLookup( telname ); 
     273                     
     274                    //lookup public tst domain first, to retrieve .tsm and check version 
     275                    performTxtLookup( publicDomain ); 
    314276                } 
    315277            } ); 
     
    506468     *      java.util.Vector) 
    507469     */ 
    508     public void lookupWorkerCompleted (final int statusVal, final int type, final Vector answers) 
    509     { 
     470    public void lookupWorkerCompleted (final int statusVal, final int type, final Vector answers, String domain) 
     471    {         
    510472        Logger.logMessage( "Lookup Worker Completed: " + type, Options.KEY_LOG_NETWORK ); 
     473        if (answers != null) 
     474        { 
     475            Logger.logMessage( "Returned Answer Set: " + answers.size(), Options.KEY_LOG_NETWORK ); 
     476        } 
    511477         
    512478        switch (statusVal) 
    513479        { 
    514  
    515480            case LookupCompleteActionListener.LOOKUP_COMPLETE_OK: { 
    516481                this.status = LookupTelname.STATUS_OK; 
     
    549514 
    550515            if (statusVal == LookupCompleteActionListener.LOOKUP_COMPLETE_OK && !cancelled) 
    551             {                  
    552                 Logger.logMessage( "Txt Lookup Complete", Options.KEY_LOG_APPLICATION ); 
    553                 lookupResult.setTxtRecords( answers ); 
    554                 txtDone = true; 
    555                  
    556                 Logger.logMessage( "Checking Complete Status: NAPTR(" + naptrDone + ") TXT(" + txtDone + ") LOC(" + locDone +") NINFO(" + nInfoDone +")", Options.KEY_LOG_APPLICATION );                 
     516            {               
     517                if (!cancelled) 
    557518                { 
    558                     if (naptrDone && txtDone &&  locDone && nInfoDone) 
     519                    if (domain.equals( publicDomain )) 
    559520                    { 
    560                         //done, so finish; 
    561                         finish();  
     521                         
     522                        if (versionLookup) 
     523                        { 
     524                            //if we've done a version lookup, just fetch the txt records, removing any non plain text records 
     525                            Vector processedAnswers = new Vector(); 
     526                            for (int i = 0; i < answers.size(); i++) 
     527                            { 
     528                                if (answers.elementAt( i ) instanceof DNSTxtHeaderResourceRecord) 
     529                                { 
     530                                    processedAnswers.addElement( answers.elementAt( i ) ); 
     531                                } 
     532                            } 
     533                            lookupResult.setTxtRecords( processedAnswers ); 
     534                             
     535                            //then perform a naptr lookup of the public domain. 
     536                            performNaptrLookup( publicDomain ); 
     537                            return; 
     538                        } 
     539                         
     540                        //looked up public domain.  check version to determine following lookups. 
     541                        //text lookup done.  check for DDS. 
     542                        for (int i = 0; i < answers.size(); i++) 
     543                        { 
     544                            if (answers.elementAt( i ) instanceof DNSTxtPDDXResourceRecord) 
     545                            { 
     546                                //check the version. 
     547                                DNSTxtPDDXResourceRecord sysRecord = (DNSTxtPDDXResourceRecord) answers.elementAt( i );                            
     548                                isVersionOne = sysRecord.isVersionOne(); 
     549                                keywordsAvailable = sysRecord.isKeyWordsAvailable(); 
     550                                privateDataAvailable = sysRecord.isPrivateDataAvailable(); 
     551                                break; 
     552                            } 
     553                        } 
     554                         
     555                        if (isVersionOne) 
     556                        { 
     557                            Vector processedAnswers = new Vector(); 
     558                            for (int i = 0; i < answers.size(); i++) 
     559                            { 
     560                                //for a version 1 domain, take the txt header and keywords from the public domain 
     561                                if (answers.elementAt( i ) instanceof DNSTxtHeaderResourceRecord || answers.elementAt( i ) instanceof DNSTxtKeywordResourceRecord ) 
     562                                { 
     563                                    processedAnswers.addElement( answers.elementAt( i ) ); 
     564                                } 
     565                                 
     566                                //if its also a public lookup, take the DDS and long labels. 
     567                                if (publicDomain.equals( privateDomain )  
     568                                       && (answers.elementAt( i ) instanceof DNSTxtLongLabelResourceRecord  
     569                                       || answers.elementAt( i ) instanceof DNSTxtDDSResourceRecord)) 
     570                                { 
     571                                    processedAnswers.addElement( answers.elementAt( i ) ); 
     572                                } 
     573                            } 
     574                            lookupResult.setTxtRecords( processedAnswers ); 
     575                        } 
     576                        else 
     577                        { 
     578                            Vector processedAnswers = new Vector(); 
     579                            for (int i = 0; i < answers.size(); i++) 
     580                            { 
     581                                //for any other version, we don't want any info if it is a private lookup.  if it is a public, we copy the long labels and dds. 
     582                                if (publicDomain.equals( privateDomain )  
     583                                                && (answers.elementAt( i ) instanceof DNSTxtLongLabelResourceRecord  
     584                                                || answers.elementAt( i ) instanceof DNSTxtDDSResourceRecord)) 
     585                                { 
     586                                    processedAnswers.addElement( answers.elementAt( i ) ); 
     587                                } 
     588                            } 
     589                            lookupResult.setTxtRecords( processedAnswers ); 
     590                        } 
     591                        Logger.logMessage( "Public Txt Lookup Complete", Options.KEY_LOG_APPLICATION ); 
     592                         
     593                        if (privateDomain.equals( publicDomain )) 
     594                        { 
     595                            if (isVersionOne) 
     596                            { 
     597                                //in version one domains, when doing a public lookup, go and do NAPTRs next 
     598                                performNaptrLookup( publicDomain ); 
     599                            } 
     600                            else 
     601                            { 
     602                              //in version one+ domains, when doing a public lookup, go and do NINFO next 
     603                                performNinfoLookup( publicDomain ); 
     604                            } 
     605                        } 
     606                        else 
     607                        { 
     608                            //for private domains, lookup the private txt records next, regardless of version. 
     609                            performTxtLookup( privateDomain );                         
     610                        } 
     611                    } 
     612                    else if (domain.equals( privateDomain )) 
     613                    { 
     614                        //looked up private domain.  Obtain DDS and log labels and add to already obtained text records. 
     615                        Vector processedAnswers = lookupResult.getTxtRecords(); 
     616                        if (processedAnswers == null) 
     617                        { 
     618                            processedAnswers = new Vector(); 
     619                        } 
     620                        for (int i = 0; i < answers.size(); i++) 
     621                        { 
     622                            //for any private lookup, we get the DDS and LL from the private domain, and add to any from the public lookup. 
     623                            if ((answers.elementAt( i ) instanceof DNSTxtLongLabelResourceRecord  
     624                                            || answers.elementAt( i ) instanceof DNSTxtDDSResourceRecord)) 
     625                            { 
     626                                processedAnswers.addElement( answers.elementAt( i ) ); 
     627                            }                             
     628                        }            
     629                        lookupResult.setTxtRecords( processedAnswers ); 
     630                         
     631                        Logger.logMessage( "Private Txt Lookup Complete", Options.KEY_LOG_APPLICATION ); 
     632                                             
     633                        if (isVersionOne) 
     634                        { 
     635                            //in version one domains, when doing a public lookup, go and do NAPTRs next 
     636                            performNaptrLookup( privateDomain ); 
     637                        } 
     638                        else 
     639                        { 
     640                            //in version one+ domains, when doing a public lookup, go and do NINFO next 
     641                            performNinfoLookup( privateDomain ); 
     642                        } 
     643                    } 
     644                    else if (domain.equals( KEYWORD_PREFIX + "." + publicDomain )) 
     645                    { 
     646                        //keyword lookup complete.  get keywords, and add to text records. 
     647                        Vector processedAnswers = lookupResult.getTxtRecords(); 
     648                        if (processedAnswers == null) 
     649                        { 
     650                            processedAnswers = new Vector(); 
     651                        } 
     652                        for (int i = 0; i < answers.size(); i++) 
     653                        { 
     654                            //for any private lookup, we get the DDS and LL from the private domain, and add to any from the public lookup. 
     655                            if (answers.elementAt( i ) instanceof DNSTxtKeywordResourceRecord ) 
     656                            { 
     657                                processedAnswers.addElement( answers.elementAt( i ) ); 
     658                            }                             
     659                        }        
     660                        lookupResult.setTxtRecords( processedAnswers );                         
     661                         
     662                        Logger.logMessage( "Private Txt Lookup Complete", Options.KEY_LOG_APPLICATION ); 
     663                         
     664                        finish(); 
    562665                    } 
    563666                } 
     
    570673                } 
    571674            } 
    572         } 
     675        }         
     676         
    573677        else if (type == DNS.TYPE_LOC) 
    574678        {             
     
    578682            {              
    579683                Logger.logMessage( "Loc Lookup Complete", Options.KEY_LOG_APPLICATION ); 
    580                 lookupResult.setLocRecords( answers ); 
    581                 locDone = true; 
     684                lookupResult.setLocRecords( answers );                 
    582685                 
    583686                if (!cancelled) 
    584687                { 
    585                     performNinfoLookup( telnameTop ); 
     688                    if (isVersionOne) 
     689                    { 
     690                        //the LOC lookup is the last one, so finish. 
     691                        finish(); 
     692                    } 
     693                    else 
     694                    { 
     695                        //for v1+ domains, might need to look keywords up in _kw domains.  Check value of kwa. 
     696                        if (keywordsAvailable) 
     697                        { 
     698                            performTxtLookup( KEYWORD_PREFIX + "." + publicDomain ); 
     699                        } 
     700                        else 
     701                        { 
     702                            //no keywords available, so finish 
     703                            finish(); 
     704                        } 
     705                    } 
    586706                } 
    587707            } 
     
    599719 
    600720            if (statusVal == LookupCompleteActionListener.LOOKUP_COMPLETE_OK && !cancelled) 
    601             {              
     721            {     
    602722                Logger.logMessage( "NInfo Lookup Complete", Options.KEY_LOG_APPLICATION ); 
    603                 lookupResult.setNInfoRecords( answers ); 
    604                 nInfoDone = true; 
     723                //if returning from a NINFO lookup, add the value as a text header to the text records. 
     724                //NINFO lookups only occur on V1+ domains. 
     725                 
     726                Vector processedAnswers = lookupResult.getTxtRecords();      
     727                if (processedAnswers == null) 
     728                { 
     729                    processedAnswers = new Vector(); 
     730                } 
     731                for (int i = 0; i < answers.size(); i++) 
     732                { 
     733                    if (answers.elementAt( i ) instanceof DNSTxtHeaderResourceRecord) 
     734                    { 
     735                        processedAnswers.addElement( answers.elementAt( i ) ); 
     736                    } 
     737                } 
     738                lookupResult.setTxtRecords( processedAnswers ); 
    605739                 
    606740                if (!cancelled) 
    607741                { 
    608                     performTxtLookup( telnameTop ); 
    609                 } 
    610             } 
     742                    performNaptrLookup( privateDomain ); 
     743                } 
     744            }            
    611745            else 
    612746            { 
     
    624758            { 
    625759                Logger.logMessage( "Naptr Lookup Complete", Options.KEY_LOG_APPLICATION ); 
    626                 lookupResult.setNaptrRecords( answers ); 
    627                 naptrDone = true; 
    628  
     760                lookupResult.setNaptrRecords( answers );                
    629761                 
    630762                if (!cancelled) 
    631763                { 
    632                     performLocLookup( telnameTop ); 
     764                    if (versionLookup) 
     765                    { 
     766                        //if version lookup, finish 
     767                        finish(); 
     768                    } 
     769                    else 
     770                    { 
     771                        performLocLookup( privateDomain ); 
     772                    }                     
    633773                } 
    634774            } 
     
    638778            } 
    639779        } 
    640     } 
    641      
     780     
     781    } 
     782     
     783    public boolean isPrivateDataAvailable () 
     784    { 
     785        return privateDataAvailable; 
     786    } 
     787 
     788 
    642789    private void finish() 
    643790    { 
    644791        if (!cancelled) 
    645792        { 
    646             Logger.logMessage( "Storing result in cache + " + telname, 
     793            Logger.logMessage( "Storing result in cache + " + privateDomain, 
    647794                Options.KEY_LOG_APPLICATION ); 
    648             LookupResultDataStore.setLookupResult( telname, lookupResult ); 
     795            LookupResultDataStore.setLookupResult( privateDomain, lookupResult ); 
    649796             
    650797            Logger.logMessage( "Lookup complete", Options.KEY_LOG_APPLICATION ); 
     
    700847    public String getTelname () 
    701848    { 
    702         return telname; 
     849        return privateDomain; 
    703850    } 
    704851 
     
    730877    } 
    731878 
     879    public boolean isPrivateLookup() 
     880    { 
     881        return !(publicDomain.equals( privateDomain )); 
     882    } 
    732883 
    733884    public void setAutomated (boolean automated) 
  • apps/blackberry/branches/1.5/blackberry/src/org/telnic/blackberry/lookup/LookupWorker.java

    r339 r567  
    4242 * 
    4343 * @author John Cundall, Ben Dowling 
    44  * @version $Id: LookupWorker.java,v 1.11 2008/12/19 15:06:58 jm2 Exp $ 
     44 * @version $Id: LookupWorker.java,v 1.12 2009/11/06 11:55:31 jm2 Exp $ 
    4545 */ 
    4646 
     
    9696     */ 
    9797    private boolean automated = false; 
    98  
    9998 
    10099    /** 
     
    112111    } 
    113112 
    114  
    115113    /** 
    116114     * setLookupWorkerCompletedListener. 
     
    122120        completionListener = l; 
    123121    } 
    124  
    125122 
    126123    /** 
     
    145142            completeLookup( LookupCompleteActionListener.LOOKUP_COMPLETE_OK, queryType, answers ); 
    146143        } 
    147  
    148     } 
    149  
     144    } 
    150145 
    151146    /** 
     
    309304    } 
    310305 
    311  
    312306    /** 
    313307     * doQuery. 
     
    323317    } 
    324318 
    325  
    326319    /** 
    327320     * Complete lookup. 
     
    356349                public void run () 
    357350                { 
    358                     completionListener.lookupWorkerCompleted( status, type, answers ); 
     351                    completionListener.lookupWorkerCompleted( status, type, answers, telname ); 
    359352                } 
    360  
    361353            } ); 
    362354        } 
    363355    } 
    364356 
    365  
    366357    public boolean isAutomated () 
    367358    { 
     
    369360    } 
    370361 
    371  
    372362    public void setAutomated (boolean automated) 
    373363    { 
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us