Oberon || Library || Module Index || Search Engine || Definition || Module
TYPE Context = POINTER TO ContextRec; TYPE ContextRec = RECORD (Disciplines.ObjectRec) END;
TYPE Name = DNSRecords.Name; TYPE Record = DNSRecords.Record; TYPE Query = POINTER TO QueryRec; TYPE QueryRec = RECORD (Objects.ObjectRec) name: Name; type: DNSRecords.RRType; class: DNSRecords.Class; END;
CONST noNameServers = 0; CONST protocolError = 1; CONST tooManyRetries = 2; CONST unexpectedResponse = 3; CONST sendFailed = 4; CONST timeout = 5; CONST formatError = 6; CONST serverFailure = 7; CONST notImplemented = 8; CONST refused = 9; CONST unexpectedResponseCode = 10; CONST errors = 11; TYPE ErrorCode = SHORTINT; (* noNameServers... *) TYPE ErrorEvent = POINTER TO ErrorEventRec; TYPE ErrorEventRec = RECORD (Events.EventRec) errorcode: ErrorCode; query: Query; dnsserver: Name; END; VAR errormsg: ARRAY errors OF Events.Message; VAR error: Events.EventType;
PROCEDURE CreateContext(VAR context: Context); PROCEDURE AddNameServer(context: Context; socket: SysSockets.Socket; name: ARRAY OF CHAR);
PROCEDURE EnableRoundRobin(context: Context); PROCEDURE SetTimeout(context: Context; seconds: INTEGER); PROCEDURE SetNumberOfRetries(context: Context; retries: INTEGER);
PROCEDURE Process(context: Context; name: ARRAY OF CHAR; type: DNSRecords.RRType; class: DNSRecords.Class; VAR header: DNSHeaders.Header; VAR answerRecs, authRecs, addRecs: Record; errors: RelatedEvents.Object) : BOOLEAN;
CreateContext creates a new context with initially no nameservers at all.
AddNameServer adds a nameserver to a context where socket is an already connected socket of type SysSockets.dgram. Note that this socket can be of any protocol family, be it SysSockets.pfINET, SysSockets.pfINET6, or SysSockets.pfUNIX. Additionally, a string name is to be given as printable representation of the nameserver which can be used in error messages. This is usually the printable representation of the socket address.
There is a transitive precedence relation defined over the set of nameservers belonging to a context. Nameservers who refuse to process our requests have a lower precedence than those from which we haven't seen any refusals yet. This being equal, nameservers have a lower precedence if they had more timeouts than others. That also being equal, nameservers are preferred if the queue of pending requests is shorter. Finally, if all other criterias show no difference, nameservers added earlier with AddNameServer take precedence. If a roundrobin mode is selected using EnableRoundRobin, however, the order of nameservers is changed by each of invocation of Process. Note that the maintained counts of refusals and timeouts are reset to 0 as soon successful replies are seen.
If no valid response comes within the given timelimit, or the nameserver responds with a refusal, requests are forwarded to the nameserver with the highest precedence excluding the last nameserver used.
For each of the nameservers added, a task is running (see Tasks). All these tasks are automatically shut down as soon as the context object terminates (see Resources).
SetTimeout sets the timeout for single request attempts. Note that the total time for requests processed by Process can be much longer as this timeout multiplies with the number of maximal retries. The default value is 1.
By default, the maximal number of retries is 2 multiplied with the number of nameservers. SetNumberOfRetries allows to change this factor. This gives usually the number of retries per nameserver but, if precedences play a role because of timeouts and refusals, it might well happen that individual nameservers are queried more often and other nameservers are left out.
Process asks for resource records for name with the given type (e.g. DNSRecords.a) in the given class (usually DNSRecords.classIN). If successful, the header is returned along with the lists of answer, authorization, and additional records. Note that name must be a fully-qualified domain name. Local domain names and search lists are not considered.
Note that permanent name errors (i.e. DNSHeaders.nameError) do not lead to error events or to a return of FALSE by Process. They are expected to be handled by the resolver who invokes Process:
IF DNSRequests.Process(context, name, rrtype, DNSRecords.classIN, header, answerRecs, authRecs, addRecs, errors) THEN rcode := DNSHeaders.GetResponseCode(header); CASE rcode OF | DNSHeaders.noError: (* handle successful response *) | DNSHeaders.nameError: (* permanent error; error event is to be generated or another attempt is to be made using search lists or other rules *) END; ELSE (* temporary error; error events have already been generated *) END;
Oberon || Library || Module Index || Search Engine || Definition || Module