125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Factor
		
	
	
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								USING: kernel sequences combinators accessors locals random
							 | 
						||
| 
								 | 
							
								       combinators.short-circuit
							 | 
						||
| 
								 | 
							
								       io.sockets
							 | 
						||
| 
								 | 
							
								       dns dns.util dns.cache.rr dns.cache.nx
							 | 
						||
| 
								 | 
							
								       dns.resolver ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								IN: dns.forwarding
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:: query->rrs ( QUERY -- rrs/f )
							 | 
						||
| 
								 | 
							
								   [let | RRS [ QUERY cache-get ] |
							 | 
						||
| 
								 | 
							
								     RRS
							 | 
						||
| 
								 | 
							
								       [ RRS ]
							 | 
						||
| 
								 | 
							
								       [
							 | 
						||
| 
								 | 
							
								         [let | NAME  [ QUERY name>>  ]
							 | 
						||
| 
								 | 
							
								                TYPE  [ QUERY type>>  ]
							 | 
						||
| 
								 | 
							
								                CLASS [ QUERY class>> ] |
							 | 
						||
| 
								 | 
							
								               
							 | 
						||
| 
								 | 
							
								           [let | RRS/CNAME [ T{ query f NAME CNAME CLASS } cache-get ] |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								             RRS/CNAME f =
							 | 
						||
| 
								 | 
							
								               [ f ]
							 | 
						||
| 
								 | 
							
								               [
							 | 
						||
| 
								 | 
							
								                 [let | RR/CNAME [ RRS/CNAME first ] |
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								                   [let | REAL-NAME [ RR/CNAME rdata>> ] |
							 | 
						||
| 
								 | 
							
								              
							 | 
						||
| 
								 | 
							
								                     [let | RRS [
							 | 
						||
| 
								 | 
							
								                                  T{ query f REAL-NAME TYPE CLASS } query->rrs
							 | 
						||
| 
								 | 
							
								                                ] |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                       RRS
							 | 
						||
| 
								 | 
							
								                         [ RRS/CNAME RRS append ]
							 | 
						||
| 
								 | 
							
								                         [ f ]
							 | 
						||
| 
								 | 
							
								                       if
							 | 
						||
| 
								 | 
							
								                     ] ] ]
							 | 
						||
| 
								 | 
							
								               ]
							 | 
						||
| 
								 | 
							
								             if
							 | 
						||
| 
								 | 
							
								           ] ]
							 | 
						||
| 
								 | 
							
								       ]
							 | 
						||
| 
								 | 
							
								     if
							 | 
						||
| 
								 | 
							
								   ] ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:: answer-from-cache ( MSG -- msg/f )
							 | 
						||
| 
								 | 
							
								   [let | QUERY [ MSG message-query ] |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     [let | NX  [ QUERY name>> non-existent-name? ]
							 | 
						||
| 
								 | 
							
								            RRS [ QUERY query->rrs                ] |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								       {
							 | 
						||
| 
								 | 
							
								         { [ NX  ] [ MSG NAME-ERROR >>rcode          ] }
							 | 
						||
| 
								 | 
							
								         { [ RRS ] [ MSG RRS        >>answer-section ] }
							 | 
						||
| 
								 | 
							
								         { [ t   ] [ f                               ] }
							 | 
						||
| 
								 | 
							
								       }
							 | 
						||
| 
								 | 
							
								       cond
							 | 
						||
| 
								 | 
							
								     ]
							 | 
						||
| 
								 | 
							
								   ] ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: message-soa ( message -- rr/soa )
							 | 
						||
| 
								 | 
							
								  authority-section>> [ type>> SOA = ] filter first ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! :: cache-message ( MSG -- msg )
							 | 
						||
| 
								 | 
							
								!    MSG rcode>> NAME-ERROR =
							 | 
						||
| 
								 | 
							
								!      [
							 | 
						||
| 
								 | 
							
								!        [let | NAME [ MSG message-query name>> ]
							 | 
						||
| 
								 | 
							
								!               TTL  [ MSG message-soa   ttl>>  ] |
							 | 
						||
| 
								 | 
							
								!          NAME TTL cache-non-existent-name
							 | 
						||
| 
								 | 
							
								!        ]
							 | 
						||
| 
								 | 
							
								!      ]
							 | 
						||
| 
								 | 
							
								!    when
							 | 
						||
| 
								 | 
							
								!    MSG answer-section>>     [ cache-add ] each
							 | 
						||
| 
								 | 
							
								!    MSG authority-section>>  [ cache-add ] each
							 | 
						||
| 
								 | 
							
								!    MSG additional-section>> [ cache-add ] each
							 | 
						||
| 
								 | 
							
								!    MSG ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:: cache-message ( MSG -- msg )
							 | 
						||
| 
								 | 
							
								   MSG rcode>> NAME-ERROR =
							 | 
						||
| 
								 | 
							
								     [
							 | 
						||
| 
								 | 
							
								       [let | RR/SOA [ MSG
							 | 
						||
| 
								 | 
							
								                         authority-section>>
							 | 
						||
| 
								 | 
							
								                         [ type>> SOA = ] filter
							 | 
						||
| 
								 | 
							
								                       dup empty? [ drop f ] [ first ] if ] |
							 | 
						||
| 
								 | 
							
								         RR/SOA
							 | 
						||
| 
								 | 
							
								           [
							 | 
						||
| 
								 | 
							
								             [let | NAME [ MSG message-query name>> ]
							 | 
						||
| 
								 | 
							
								                    TTL  [ MSG message-soa   ttl>>  ] |
							 | 
						||
| 
								 | 
							
								               NAME TTL cache-non-existent-name
							 | 
						||
| 
								 | 
							
								             ]
							 | 
						||
| 
								 | 
							
								           ]
							 | 
						||
| 
								 | 
							
								         when
							 | 
						||
| 
								 | 
							
								       ]
							 | 
						||
| 
								 | 
							
								     ]
							 | 
						||
| 
								 | 
							
								   when
							 | 
						||
| 
								 | 
							
								   MSG answer-section>>     [ cache-add ] each
							 | 
						||
| 
								 | 
							
								   MSG authority-section>>  [ cache-add ] each
							 | 
						||
| 
								 | 
							
								   MSG additional-section>> [ cache-add ] each
							 | 
						||
| 
								 | 
							
								   MSG ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! : answer-from-server ( msg servers -- msg ) random ask-server cache-message ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: answer-from-server ( msg servers -- msg ) ask-servers cache-message ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:: find-answer ( MSG SERVERS -- msg )
							 | 
						||
| 
								 | 
							
								   { [ MSG answer-from-cache ] [ MSG SERVERS answer-from-server ] } 0|| ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:: start-server ( ADDR-SPEC SERVERS -- )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  [let | SOCKET [ ADDR-SPEC <datagram> ] |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								      SOCKET receive-packet
							 | 
						||
| 
								 | 
							
								        [ parse-message SERVERS find-answer message->ba ]
							 | 
						||
| 
								 | 
							
								      change-data
							 | 
						||
| 
								 | 
							
								      respond
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								    forever
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ] ;
							 |