INTERNET DRAFT Dan Larner, Xerox PARC draft-larner-nginterfaces-00.txt Expires January 1, 1999 August 1, 1998 HTTP-NG Web Interfaces Status of This Document This document is an Internet-Draft. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet- Drafts as reference material or to cite them other than as "work in progress." To view the entire list of current Internet-Drafts, please check the "1id-abstracts.txt" listing contained in the Internet-Drafts Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net (Northern Europe), ftp.nis.garr.it (Southern Europe), munnari.oz.au (Pacific Rim), ftp.ietf.org (US East Coast), or ftp.isi.edu (US West Coast). This draft document describes an initial set of extensible formal object interfaces that allow some of the basic functionality of HTTP to be captured in the HTTP-NG framework. The intent is not to imply that what is presented here is complete or final, but rather to provide a starting point for developing how the Web should look in the future. Distribution of this document is unlimited. Please send comments to the HTTP-NG mailing list at www-http-ng-comments@w3.org. Discussions are archived at "http://lists.w3.org/Archives/Public/www-http-ng-comments/". Please read the "HTTP-NG Short- and Longterm Goals Document" [1] for a discussion of goals and requirements of a potential new generation of the HTTP protocol and how we intend to evaluate these goals. General information about the Project as well as new draft revisions, related discussions, and background information is linked from "http://www.w3.org/Protocols/HTTP-NG/". This work is part of the W3C HTTP/NG Activity (for current status, see "http://www.w3.org/Protocols/HTTP-NG/Activity"). Introduction Part of the charter of the Protocol Design Group of the HTTP-NG project is to identify a set of formal interfaces that will allow the current functionality of the Web to be captured, as well as support future needs. Before delving into the specific interfaces, the kinds of concepts involved need to be described. The actual interface descriptions here are cast in terms of distributed object systems, the merits of which as a foundation for the Web have been discussed in 'Migrating the Web toward Distributed Objects' (ftp://ftp.parc.xerox.com/pub/ilu/misc/webilu.html) and elsewhere. The intent is not to imply that what is presented here is complete or final, but rather to provide a starting point for how the Web should look in the future. Concepts When we think of the Web today, the idea of a 'resource' comes to mind. In general, a resource is an Object that has some methods (e.g. in HTTP, Get Head and Post) that can be invoked on it. Objects may be stateful in that they have some sort of opaque 'native data' that influences their behavior. The nature of this native data is unknown to the outside, unless the object explicitly makes it known somehow. [Any stateful object may or may not have some means by which it stores persistent state across activations, but that's not really part of our concern here.] Objects which are Renderable may be asked to produce a Rendering based on a set of Preferences. This is analogous to HTTP Get. A Rendering is a transformation of the object's native data into some other form, typically a collection of bytes with an interpretation determined by a named type relative to some typespace. Common examples are illustrated by the various MIME types, e.g. text/html Rendering for viewing in a web browser, and an application/postscript Rendering for printing. When a Renderable object is asked for a Rendering of a preferred type, the implementation of the object's method for this operation transforms or maps the native data to this Rendering type. Note that this transformation may or may not be reversible. If the Rendering format happens to be the same as the native data of the document, the transformation might be identity. Objects that have no native data themselves may be able to produce a Rendering by generating it from other sources (e.g. real world state, other objects). A Rendering may be retrieved in one of two ways. Either the Rendering is returned as a value from a synchronous call, or the Rendering is requested and then sent asynchronously, in chunks, back to some RenderingSink. The former can be thought of as a 'client-pull' technique, and the latter as a 'server-push' technique. The sink approach is to support the notion of a 'stream', to deal with Renderings that are impractically large (e.g. images), or not well bounded (e.g. live video or audio). Renderings may also be produced by an object acting as a FormProcessor . This is analogous to HTTP Post. In this case, instead of receiving information about RenderingPreferences, the object receives a set of Name/Value pairs that are interpreted in an implementation-specific manner to produce a Rendering. Some objects may be asked to accept a Rendering. This is analogous to HTTP Put. The intent here is that of updating the object's native data. When such a request is made on an object, if the supplied rendering is transformable by the implementation into the native data, and such an operation is semantically permissible, the rendering is transformed into the native form. If it's not possible to transform the rendering into native form (e.g. supplying GIF to an object whose implementation doesn't know how to OCR an image to translate it to an internal text representation), then an exception needs to be raised. Note that some objects could actually have multiple native data forms internally, but this is generally unknown outside the object. Objects may have a PropertySet. These are groups of attributes that are not normally part of the native data itself, but rather more descriptive of the object as a whole. This is often referred to as Meta-Data, and may include such information as author, version, summary, etc. Properties may be static or computed [an implementation detail]. In actual implementations, the data exchanges that take place during of method invocations may pass through one or more intermediate caches. Caches often maintain a copy of some object's Rendering to improve the speed with which a Rendering can be retrieved. What can be cached and what cannot is dependent on the operation semantics, the security policies of the parties involved, contractual obligations, and other concerns. CacheControl information must accompany each request and response where the potential for caching is of concern. Concept Composability and Extendability The previous section attempted to expose some general concepts, or 'types' that objects may be. The key word here is may. For example, not all objects need to be Renderable, not all need to be able to process forms, and some things simply have no interesting properties to expose. What's needed is the ability to describe each of these types in isolation, and be able to combine then as needed for particular circumstances. So for example, we want to define a Renderable type to be an object that has a set of operations or Methods dealing with the retrieval of a rendering. Similarly, we define a PropertySet type for those objects that need to have that sort of functionality, and so on. In object oriented systems, bits of functionality are combined through inheritance. To say that something 'C' inherits from 'A' and 'B', means that C objects are a derived type, and can be used as a method parameter wherever an A, B, or C is required. C also provides the methods defined for A and B objects, in addition to any that may be defined specifically for C objects. These properties are transitive with respect to inheritance. So then, using the inheritance capabilities of the distributed object system, we can define new kinds of objects that are a number of these types (and hence implement their Methods) through inheritance. For example, to capture the functionality of a WebDocument as we think of it today, we define WebDocument as an object that inherits Renderable (supporting the equivalent of HTTP's Get), and inherits from the PropertySet object (to primarily support independent retrieval of what is currently covered by some HTTP headers). It is also using the mechanism of inheritance that types can be extended. Note that the previous description mentioned that a type C inheriting from A and B can define its own methods in addition to the ones inherited from its parents. For example, A WebDocument can implement its own method that allows both Rendering and Properties to be retrieved in a single call. Another example could be a new object type, MicrowaveOven, that not only is Renderable (can supply an image of what's cooking), but also adds methods to turn it on and off. Printers and Scanners could be defined as children of a WebDocument, and a Copier as a child of those. The Fit with the Current Web This section attempts to basically describe how the components of the Web as we know them today could be cast using distributed objects with the kinds of interfaces described above, and illustrates some scenarios that would be difficult to implement with today's approach. In the descriptions, the word ObjRef is used to mean an object reference. This may either be something like a HTTP URL as we commonly see today, or it may be of a more general form that includes information about the object attributes (e.g. its type), in addition to the contact and instance identification information. Content Retrieval Given an ObjRef, a browser would like to contact the entity it refers to in order to receive a Rendering. If the ObjRef has the HTTP scheme, an assumption is made that the entity is a resource as we know it today and we treat it as we commonly would using HTTP1.x. [F1] If however the ObjRef has more information, (e.g. what object type it represents), the browser may take quite a different set of actions. Let's say it indicates that it's a 'WebDocument' type. The browser asks the document for a Rendering and its Properties, perhaps in a particular format. The WebDocument object receives the rendering request. It has its own implementation of the request, so how it actually processes the request may be different from other WebDocuments -- remember we're defining types here, and their intended semantics, not their actual implementations. [For example, its implementation might examine the request, and see that the requested Rendering content type is not available through local transformations of native data. It could call out to a Rendering transformation service (e.g. postscript to gif) to get the appropriate Rendering.] In the response to the browser, the WebDocument sends the Rendering, along with a set of Properties describing the document. The browser for example might notice that the document author is on the list of 'interesting people' that the browser's user has specified. The browser then decides to automatically add this ObjRef to the user's 'Favorites' folder. In a future scenario, the browser might discover that the WebDocument had been extended with Daemon interfaces. A Daemon is basically an interface that accepts condition action pairs, and performs the action when the condition is true, typically the sending of some Event containing data to a Sink. Now, since this WebDocument's author is a user favorite, the browser decides that it would like to be notified of changes in the document so that the Rendering can be updated accordingly. It adds a Daemon (through the Daemon Interface that had been 'mixed in' with the WebDocument) to the WebDocument, whose Condition is true when the Document changes. The Daemon contains an Action that accepts Condition Results and an Event Sink (that the browser implements). This Action gets the new Rendering for the Document, packages it up in an Event and sends it to the browser's Event Sink. When the browser receives the Event, it knows that the Rendering should be updated. This might even be allowed to proceed in the background so that the browser's cache can be kept up to date. When the page is left, or when the cache entry gets dumped from the cache, the browser retracts its previously posted condition action pair from the WebDocument's Daemon interface. Forms If the browser sees a form method as one might today, e.g. FORM METHOD="POST" ACTION="/cgi/wwwwais.cgi"; it treats the form just as it does today. If however, it saw a method that wasn't POST, e.g. ProcessForm, and the ACTION that wasn't the HTTP schemed URL but rather one indicating a FormProcessor object, it would invoke the named method on the specified object, passing the form parameters to the method as a property-list (a list of name-value pairs). Note here that the values in this list can be more than simple strings - any type may be passed, enabling a much richer and more compact set of inputs. HTTP-NG Interfaces This section contains brief descriptions of interfaces that embody the concepts mentioned previously. Actual interfaces described in ILU's [2] Interface Specification Language (ISL) can be found in the appendix. These interfaces are certain to evolve as missing and extraneous functionality is discovered through both review and prototype implementation. NgBasic This interface defines a number of basic types such as strings, times, intervals, etc., as well as the NgObject object type which forms a root class from which all NG classes inherit. This is useful to be able to provide all derived objects with a standard set of methods, as well as provide a type which may be used as a handle for any kind of NG-Object. A single method, GetInterfaceDefinitionSource, which provides a means for interface discovery, is declared. In addition, some exceptions are defined in NgBasic. Certain operations, typically Get or Put style, may return a WouldBlock exception when the operation would block for some reason. Similarly, Conflict exceptions may be returned when the operation is somehow in conflict with another operation (perhaps simultaneous Puts on a Rendering) or operational semantics (perhaps a Put based on an old version as determined through e-tag information for example). The value optionally contained in the ExceptionInformation's Pickle is operation specific. For a WouldBlock, it could contain locking information for example. Those knowledgeable about locking could attempt to extract and make use of the lock information contained in the pickle. Those not knowledgeable about locking could just disregard the value, but still have knowledge that something is currently going on with the target object that would cause them to block waiting for a result. There may be situations where an implementation might quickly reify an object in an object creation function and later determine that this object really doesn't exist. Since this sort of 'system exception' information isn't necessarily sent across the wire, a user exception, ObjectNotExist, is defined for this sort of event. NgStream An object having methods intended for the asynchronous receipt of data (streaming data for example) is called a DataSink. The DataSink object type is 'abstract', in that it is meant to be subtyped, never directly instantiated. Subtypes will supply methods that are specialized to the particular type of data the the sink accepts. It methods are: * RegisterSourceControl - tell the sink where control information can be sent. * Done - indicate that no more data will be sent DataSinks may have a need to exert some control over the source side. The DataSource object type may be passed to a DataSink, and the DataSink can then invoke a number of 'flow-control' related methods: * Abort - abort the streaming that is associated with this object. * Pause - pause the streaming. * Resume - resume the streaming. * Resend - cause a range of data to be resent * SuggestChunkSize : suggest the streaming change its chunk size Note that the methods on DataSink and DataSource are asynchronous. This avoids the return-trip time that synchronous call have. Since the states of these objects are influenced by the order in which methods are processed, these calls must take place over a communication channel that ensures that methods are processed in the order in which they are sent. NgDocument The object type WebDocument is primarily a combination of the Renderable and PropertySet object types, and is meant to be an NG analog to what Web documents are today. [F2] The main method is GetRenderingandProperties, which is simply intended to be a combination of the GetRendering and GetProperties methods of its parents. This method mimics what we current have with HTTP Get. SendRenderingAndProperties and SendRenderingAndPropertiesSynched is similar only it allows for the return results to be sent asynchronously back to a RenderingAndPropertiesSink. The PutableWebDocument object type inherits from WebDocument, PutableRendering, and PutablePropertySet, and provides the analog to the HTTP 1.1 Put operation. NgRendering Rendering preferences are described through use of a RenderingPreferences record. The members of this record are briefly: * allowContentTypes and disallowContentTypes: describe which Rendering content types are acceptable * allowEncodings and disallowEncodings: describe which Rendering encodings are acceptable * acceptCharsets and acceptLocales: describe which charsets and locales are acceptable * range: the interval of bytes that are desired * userAgent : a URI indicating the Agent sending this record Renderings themselves are described through use of a Rendering record. The members of this record are briefly: * contentType: Type of the rendering bytes before any encoding. * contentEncoding: Represents an ordered sequence of transformations that were applied to the original contentType to arrive at the passed renderingBytes * contentRange and rangeEncoded: If rangeEncoded is False, then contentRange is the range of the rendering bytes before any encoding (unsupplied meaning all the bytes). If rangeEncoded is True, then contentRange applies to the transformed bytes. * contentCharSet and contentLocale : charset and locale the rendering is in * renderingBytes: bytes comprising the rendering An object of type Renderable is able to produce a Rendering of the object. Examples are a text description, a graphic, an html page, an audio, etc. This first is Renderable itself. This type has a number of methods. * GetAvailableRenderings - returns what kinds of renderings are available. * GetRendering - actually returns a rendering based on caller supplied preferences. * SendRendering - Asynchronous request to send rendering data asynchronously to a RenderingSink object type. * SendRenderingSynched - Synchronous request to send rendering data asynchronously to a RenderingSink object type. The PutableRendering object type provides the analog to the HTTP 1.1 Put operation. It adds a single method: * PutRendering - The caller supplies a Rendering record describing the write operation to take place. If the supplied rendering input is unacceptable (e.g. wrong type, etc.) the callee raises the NoRenderingMatch exception which contains a RenderingPreferences describing what is acceptable. An object of type RenderingSink is able to asynchronously receive renderings. It inherits the RegisterSourceControl and Done methods from DataSink, and add several methods: * RegisterResponseCacheControl - provides the sink information about how to do caching. * RenderingProblem - called to pass exception related information * ReceiveRendering - passes Renderings into the sink. * ReceiveRenderingChunk - passes RenderingChunks (range and bytes only) into the sink. * Resynchronize - Returns the index of the next byte expected by the sink, if any, and is used to allow the source to resynchronize of needed. NgProperty An object of type PropertySet has a method GetProperties used to retrieve name/value pairs, e.g. Authors, CreationTime, etc. A subtype of PropertySet, PutablePropertySet has a method PutProperties used to write name/value pairs. NgFormProcessor An object of type FormProcessor is able to process Form based input, and produce an appropriate rendering as a response. This type has two methods: * ProcessForm - The caller supplies a FormInputElementSequence (name-value pairs) describing the form data. If the input is acceptable, the FormProcessor returns a Rendering. If the supplied formEntries input is unacceptable (e.g. wrong type, etc.) the callee raises the InvalidFormEntries exception, which contains a sequence of the names of the entries which were unacceptable. * SendFormReply - just like ProcessForm only instead of synchronously returning the Rendering, it sends it asynchronously via a call to the ReceiveFormResult method on a ProcessedFormSink. * SendFormReplySynched - Synchronous version of SendForm. NgCache Records are defined that may be sent along with requests and responses to provide caches and proxy relevant information. This mostly mimics the cache-related headers and Cache-Control header values found in HTTP 1.1. See the HTTP1.1 specification(http://www.w3.org/Protocols/rfc2068/rfc2068) for the semantics. An issue that needs further thought is the crosscutting of cache-relevant information through multiple arguments - version information is a prime example. IANA-Charsets-Registry This interface simply contains types for identifying character sets. ------------------------------------------------------ Footnotes [F1] The paper "Migrating the Web toward Distributed Objects" (ftp://ftp.parc.xerox.com/pub/ilu/misc/webilu.html), describes how in the distributed object system ILU, Get, Head and Post methods on an object can be invoked through existing HTTP through inheritance of the iluhttp.Resource object type. Through inheritance of this type, HTTP-NG style Web objects can interoperate with existing Web browser and servers, providing a migration path to the new technology. [F2] An implementer might chose to create a new type derived from both WebDocument, and from iluhttp.Resource (part of the ILU distribution), so that it can also interact with existing Web clients and servers. ------------------------------------------------------ References [1] http://www.w3.org/TR/1998/WD-HTTP-NG-goals [2] ftp://ftp.parc.xerox.com/pub/ilu/ilu.html ------------------------------------------------------ ------------------------------------------------------ Appendix - Strawmen ISL files ------------------------------------------------------ NgBasic.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** Basic Types ******************************** *) (* ************************************************************************ *) (* Defines a number of basic types used throughout HTTP-NG interfaces. *) Interface NgBasic Brand "NG" ; (* ********************** String & Type related *************************** *) Type String = Sequence Of Short Character; Type OptionalString = Optional String; Type StringSequence = Sequence Of String; Type ByteSequence = Sequence Of Byte; Type URI = String; (* see RFC1738 and RFC 1808 *) Type OptionalURI = Optional URI; Type URISequence = Sequence Of URI; Type OptionalCardinal = Optional Cardinal; (* ************************************************************************ *) (* **************************** Time Related ****************************** *) (* Represents a number of microseconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time. Note that negative values indicate number of microseconds prior to the origin. *) Type AbsoluteTime = Long Integer; Type OptionalAbsoluteTime = Optional AbsoluteTime; (* Represents an relative number of microseconds *) Type RelativeTime = Long Integer; Type OptionalRelativeTime = Optional RelativeTime; (* ************************************************************************ *) (* **************************** Version Related *************************** *) Type Version = Record major : Short Cardinal, minor : Short Cardinal End; (* ************************************************************************ *) (* ***************************** Intervals ******************************** *) (* describes an inclusive range of unsigned numbers *) Type UnsignedInclusiveInterval = Record startValue : Cardinal, endValue : Cardinal End; Type OptionalUnsignedInclusiveInterval = Optional UnsignedInclusiveInterval; (* ************************************************************************ *) (* ************************ Name Value Pairs ****************************** *) (* simply a named attribute paired with some value *) Type NameValuePair = Record name : String, value : Pickle End; Type NameValuePairSequence = Sequence Of NameValuePair; Type NameSequence = Sequence Of NgBasic.String; (* ************************************************************************ *) (* ***************************** Exceptions ******************************* *) Type OptionalPickle = Optional Pickle; Type ExceptionInformation = Record (* a human readable description of why the exception occurred *) reasonPhrase : String, (* if present, operation specific information on the details of why the operation produced an exception *) specificsData : OptionalPickle End; (* Certain operations, typically Gets or Puts, may return a WouldBlock or Conflict exception when the operation would block for some reason or is somehow in conflict with another operation (perhaps simultaneous Puts on a Rendering) or operational semantics (perhaps a Put based on an old version as determined through e-tag information for example). The value optionally contained in the ExceptionInformation's Pickle is operation specific. For a WouldBlock example, it could contain locking information. Those knowledgeable about locking could attempt to extract and make use of the lock information contained in the pickle. Those not knowledgeable about locking could just disregard the value, but still have knowledge that something is currently going on with the target object that would cause them to block waiting for a result. There may be situations where an implementation might quickly reify an object in an object creation function and later determine that this object really doesn't exist. There's a need to return an object doesn't exist exception. Since this sort of 'system exception' information isn't necessarily sent across the wire, it makes sense to create a user exception, ObjectNotExist, for this sort of event. This is also useful if this were to occur as the result of an async SendRenderingCall, where the Report returned in the ReceiveRendering can contain an ObjectNotExist exception. *) Exception WouldBlock : ExceptionInformation "Operation would have blocked" ; Exception Conflict : ExceptionInformation "Conflict with another operation or semantics" ; Exception ObjectNotExist : ExceptionInformation "Discriminator object doesn't exist" ; (* ************************************************************************ *) (* ***************************** NgObject ********************************* *) (* NgObject forms a root class from which all Ng classes inherit *) Type NgObjectSequence = Sequence Of NgObject; Type NgObject = Object Methods (* Returns a stringified object reference of an object that supports the Renderable interface. The denoted object can be asked for a Rendering (e.g. text/isl, text/idl, text/midl, etc.) interface in which (the most specific type) the object is defined. *) GetInterfaceDefinitionSource () : String End; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgStream.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailinglist, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *********************** DataSource ************************************* *) (* ************************************************************************ *) Interface NgStream Brand "NG" Imports NgBasic From ngbasic.isl End; (* This object type may be passed in invocations of operations meant for asynchronous receipt of data (such as ReceiveRendering on a RenderingSink). It allows the Sink side some control over the streaming operations. NOTE: Methods invocations are assumed to be processed at the Source in the order in which they were sent. *) Type OptionalDataSource = Optional DataSource; Type DataSource = Object Supertypes NgBasic.NgObject End Methods (* Called to abort the streaming that is associated with this object *) Asynchronous Abort (), (* Called to pause the streaming that is associated with this object *) Asynchronous Pause (), (* Called to resume the streaming that is associated with this object *) Asynchronous Resume (), (* Called to have the streaming that is associated with this object resend a range of data *) Asynchronous Resend ( repeatRange : NgBasic.UnsignedInclusiveInterval ), (* Called to suggest the streaming that is associated with this object change its chunk size *) Asynchronous SuggestChunkSize ( suggestedSize : Cardinal ) End; (* This object type is used for control over a Sink. NOTE: Methods invocations are assumed to be processed at the Sink in the order in which they were sent. *) Type DataSink = Object Supertypes NgBasic.NgObject End Methods (* Called to tell the sink where control information can be sent *) Asynchronous RegisterSourceControl (thesource : DataSource), (* Called to indicate that no more data will be sent *) Asynchronous Done () End; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgRendering.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailinglist, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** Renderings ********************************* *) (* ************************************************************************ *) (* An Object of type Renderable is able to produce a rendering. Examples renderings are a text description, a graphic, an html page, an audio, etc. An Object of type RenderingSink is able to asynchrounously receive renderings. *) Interface NgRendering Brand "NG" Imports NgBasic From ngbasic.isl, IANA-Charsets-Registry From ianacharsets.isl, NgCache From ngcache.isl, NgStream From ngstream.isl End; (* ************************************************************************ *) (* *************************** Rendering Types ***************************** *) (* Note: any URIs here which are relative paths, are by default assumed to be relative to the IANA registry - thus for example one might use "text/html". xxx Need specification here about what the URI actually denotes *) Type RenderingType = NgBasic.URI; Type RenderingTypeSequence = NgBasic.URISequence; Type RenderingEncoding = NgBasic.URI; Type RenderingEncodingSequence = NgBasic.URISequence; (* The requestor of a rendering may supply rendering preferences. The preferences describe what characteristics a rendering must have. For those members which are sequences, an empty sequence indicates no particular preference, else the sequence is treated as an ordered list of preferences. *) (* ************************************************************************ *) (* ******************** Rendering Preferences ***************************** *) Type RenderingPreferences = Record (* analogous to HTTP Accept, Accept-Charset, Accept-Encoding Range, and User-Agent headers *) (* Which content types are actually acceptable is obtained by, taking the set of all types specified by allowContentTypes (some of which may actually indicate a group of types via wildcard or other means), and subtracting from it the set of all types specified by disallowContentTypes. A zero length sequence for allowContentTypes means all types. A zero length sequence for disallowContentTypes means no types. Should the result allowContentTypes - disallowContentTypes be empty, a NoRenderingMatch exception should be raised from the receiving method. *) allowContentTypes : RenderingTypeSequence, disallowContentTypes : RenderingTypeSequence, (* Which encodings are actually acceptable is obtained by, taking the set of all types specified by allowEncodings (some of which may actually indicate a group of encodings via wildcard or other means), and subtracting from it the set of all types specified by disallowEncodings. A zero length sequence for allowEncodings means all encodings. A zero length sequence for disallowEncodings means no encodings. Should the result allowEncodings - disallowEncodings be empty, a NoRenderingMatch exception should be raised from the receiving method. *) allowEncodings : RenderingEncodingSequence, disallowEncodings : RenderingEncodingSequence, (* Acceptable Charsets of the rendering bytes before any encoding. A zero length sequence means any charset is acceptable *) acceptCharsets : IANA-Charsets-Registry.CharsetMIBEnumValueSequence, (* Acceptible Locales of the rendering bytes before any encoding. A zero length sequence means any locale is acceptable *) acceptLocales : NgBasic.StringSequence, (* If not supplied, indicates that the entire rendering is requested. If supplied and of non-zero size, it indicates the range of bytes desired from the rendering bytes before any encoding. If the interval is supplied and is of zero size, effect is similar to Http's Head method. *) range : NgBasic.OptionalUnsignedInclusiveInterval, (* xxx - Need specification here about what the URI actually denotes *) userAgent : NgBasic.OptionalURI End; (* ************************************************************************ *) (* *************************** Renderings ********************************* *) (* actual bytes of a rendering *) Type RenderingContentBytes = Sequence Of Byte; Type RenderingChunk = Record contentRange : NgBasic.OptionalUnsignedInclusiveInterval, renderingBytes : RenderingContentBytes End; Type Rendering = Record (* analogous to HTTP Content-Type, Content-Range, Content-Language, Content-Encoding and Content-MD5 headers *) (* Type of the rendering bytes before any encoding. *) contentType : RenderingType, (* Represents an ordered sequence of transformations that were applied to the original contentType to arrive at the passed renderingBytes. e.g. a,b,c means a( b( c(originalBytescontent))) A zero length sequence means no transformations were applied to the original bytes.*) contentEncoding : RenderingEncodingSequence, (* If rangeEncoded is False, then contentRange is the range of the rendering bytes before any encoding (unsupplied meaning all the bytes). If rangeEncoded is True, then contentRange applies to the transformed bytes, e.g. to a( b( c(originalBytescontent))). This is to allow for the situation where there are intervening caches that have some of the encoded bytes available, but have no ability (through design or policy) to decode the bytes down to their original content. contentRange is required with one exception: In the case where the RenderingPreferences originally received specified a range of zero size (situation treated similarly to HTTP Head), and the actual size is undeterminable (e.g. a streaming live audio for example) then contentRange may be unsupplied, and in this case, rangeEncoded should be ignored. *) contentRange : NgBasic.OptionalUnsignedInclusiveInterval, rangeEncoded : Boolean, (* charset the rendering is in - If not supplied, default is US-ASCII *) contentCharSet : IANA-Charsets-Registry.CharsetMIBEnumValue, (* locale rendering is in e.g. en-us, de, etc. If unspecified default en *) contentLocale : NgBasic.OptionalString, (* encoded bytes of the rendering *) renderingBytes : RenderingContentBytes End; Type OptionalRendering = Optional Rendering; (* ************************************************************************ *) (* ******************** Rendering Exceptions **************************** *) (* Can't supply or accept any rendering meeting the preferences or input - contains a RenderingPreferences (with the optional range and userAgent not present) describing what is acceptable *) Exception NoRenderingMatch : RenderingPreferences; (* ************************************************************************ *) (* ********************** RenderingSink Object **************************** *) (* a RenderingProblemReport is used to pass information to asynchronous callbacks that would have normally been passed back as an exception from the synchronous version of the same sort of call *) Type RenderingProblemReport = Union noMatch : RenderingPreferences, wouldBlock : NgBasic.ExceptionInformation, objectNotExist : NgBasic.ExceptionInformation End; Type RenderingSink = Object Supertypes NgStream.DataSink End Methods (* Called to tell the sink information about how to do caching. If this is never called, then the Sink may cache in any manner it wishes, so typically this will be called before any Renderings are sent. Any call to this method remains in effect until a subsequent call to this method occurs. *) Asynchronous RegisterResponseCacheControl ( responseCacheInfo : NgCache.OptionalResponseCacheControl ), (* RenderingProblem is called when an exception would have been raised from calling GetRendering (with the same args as SendRendering) on the Renderable object. This is basically to allow exceptions to be passed back as the result of an async method. report is examined for the same information as the exceptions that would have been raised from calling GetRendering on the Renderable object. The calls to the sink are considered Done if this method is called. *) Asynchronous RenderingProblem ( report : RenderingProblemReport ), (* ReceiveRendering is called as a result of a SendRendering call on a Renderable. The calls to ReceiveRendering and ReceiveRenderingChunk are considered complete when the Done method is called. *) Asynchronous ReceiveRendering ( therendering : Rendering ), (* ReceiveRenderingChunk is called to send rendering bytes that differ only in contentRange and renderingBytes from the Rendering in the last call to ReceiveRendering *) Asynchronous ReceiveRenderingChunk ( thechunk : RenderingChunk ), (* Called by the DataSource when something happens to its state such that it needs to know what was last received by the Sink. If the OptionalCardinal return value is supplied, it indicates (w.r.t rangeEncoded) the next byte expected by the sink. If it is not supplied, it indicates that the sink has not yet received any rendering chunks. *) Resynchronize ( ) : NgBasic.OptionalCardinal End; (* ************************************************************************ *) (* ************************* Renderable Object **************************** *) Type Renderable = Object Supertypes NgBasic.NgObject End Methods (* find out what types of renderings are available. The returned RenderingPreferences describes what can be supplied. *) GetAvailableRenderings () : RenderingPreferences Raises NgBasic.WouldBlock, NgBasic.ObjectNotExist End, (* GetRendering - The caller supplies a RenderingPreferences record to specify the desired characteristics of the rendering. The callee's method returns the appropriate range of bytes for the best match it has for the rendering Preferences. If no match is possible, the callee raises the NoRenderingMatch exception which contains a RenderingPreferences describing what can be supplied. *) GetRendering ( renderingPreferences : RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, out responseCacheInfo : NgCache.OptionalResponseCacheControl ) : Rendering Raises NoRenderingMatch, NgBasic.WouldBlock, NgBasic.ObjectNotExist End, (* SendRendering is just like GetRendering only instead of synchronously returning the Rendering, it sends it asynchronously via calls to the ReceiveRendering method on the supplied RenderingSink, The number of bytes in each Rendering sent is up to the caller of ReceiveRendering, but should be part of the range specified in renderingPreferences. If present, suggestedChunkSize is a suggestion on how large to make the data in the calls to ReceiveRendering. Typically, the implementation of SendRendering would arrange the following sequence of calls on the RenderingSink. (Where [] indicates optional and * indicates zero or more.) When things are successful: [RegisterSourceControl] [RegisterResponseCacheControl] ReceiveRendering ReceiveRenderingChunk* Done When there's a problem: RenderingProblem See RenderingSink's ReceiveRendering method.*) Asynchronous SendRendering( renderingPreferences : RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, renderSink : RenderingSink, suggestedChunkSize : NgBasic.OptionalCardinal ), (* A Synchronous version of SendRendering. The intent is to allow the caller to simply know that the call was received. *) SendRenderingSynched( renderingPreferences : RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, renderSink : RenderingSink, suggestedChunkSize : NgBasic.OptionalCardinal ) End; (* ************************************************************************ *) (* ***************** Renderable that you can 'Put' to ********************* *) Type PutableRenderable = Object Supertypes NgRendering.Renderable End Methods (* PutRendering - The caller supplies a Rendering record describing the write operation to take place. If the supplied rendering input is unacceptable (e.g. wrong type, etc.) the callee raises the NoRenderingMatch exception which contains a RenderingPreferences describing what is acceptable. *) PutRendering ( renderingInput : Rendering ) Raises NoRenderingMatch, NgBasic.WouldBlock, NgBasic.Conflict, NgBasic.ObjectNotExist End End; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgProperty.isl (* ************************************************************************ *) (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** Properties ********************************* *) (* ************************************************************************ *) (* A PropertySet object contains a list of name value pairs. In the Web for example, a WebDocument would inherit from PropertySet so that various attributes (e.g. last modification time, authors, etc.) could be accessed. *) Interface NgProperty Brand "NG" Imports NgBasic From ngbasic.isl End; (* ************************************************************************ *) (* ************************ Property Value Pairs ************************** *) (* a property is simply a named attribute paired with some value *) Type Property = NgBasic.NameValuePair; Type PropertySequence = Sequence Of Property; Type PropertyNames = NgBasic.NameSequence; (* ************************************************************************ *) (* ******************************** Exceptions **************************** *) (* doesn't know these properties *) Exception UnknownPropertyNames : PropertyNames ; (* ************************************************************************ *) (* *************************** Property Set Object ************************ *) Type PropertySet = Object Supertypes NgBasic.NgObject End Methods (* GetProperties returns a Set of the requested named 'Properties' and their values. Sending an empty sequence of propertiesToGet is equivalent to saying send all the properties. *) GetProperties ( propertiesToGet : PropertyNames ) : PropertySequence Raises UnknownPropertyNames, NgBasic.WouldBlock, NgBasic.ObjectNotExist End End; (* ************************************************************************ *) (* *********************** Putable Property Set Object ******************** *) (* PropertyModification Records are used when modifying property sets *) Type PropertyModificationKind = Enumeration Add, Remove, Change End; Type PropertyModification = Record propertyName : NgBasic.String, modification : PropertyModificationKind, (* present when modification is Add or Change *) value : NgBasic.OptionalPickle End; Type PropertyModificationSequence = Sequence Of PropertyModification; Type PutablePropertySet = Object Supertypes PropertySet End Methods (* PutProperties sends a Set of the requested modifications. Properties are added, removed and changed per the modification records. If an exception is raised, no modifictions will have been made to the PropertySet. *) PutProperties ( propertiesToSet : PropertyModificationSequence ) Raises UnknownPropertyNames, NgBasic.WouldBlock, NgBasic.Conflict, NgBasic.ObjectNotExist End End; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgDocument.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** Web Documents ****************************** *) (* ************************************************************************ *) (* Defines the concept of Web Documents *) (* Import iluhttp so that we can offer easy compatability with the existing web - that is, anything object inheriting from iluhttp.Resource will support Get, Head, Put and Post methods as we know them in the current web *) Interface NgDocument Brand "NG" Imports iluhttp From iluhttp.isl, NgRendering From ngrendering.isl, NgRendering From ngrendering.isl, NgCache From ngcache.isl, NgProperty From ngproperty.isl, NgStream From ngstream.isl End; (* ************************************************************************ *) (* ******************** RenderingAndPropertiesSink *********************** *) (* a RenderingProblemReport is used to pass information to asynchronous callbacks that would have normally been passed back as an exception from the synchronous version of the same sort of call *) Type PropertiesProblemReport = Union wouldBlock : NgBasic.ExceptionInformation, unknownProperties : NgProperty.PropertyNames End; Type RenderingAndPropertiesSink = Object Supertypes NgRendering.RenderingSink End Methods (* PropertyProblem is called when a property related exception would have been raised from calling GetRenderingAndProperties (with the same args as SendRenderingAndProperties) This is basically to allow exceptions to be passed back as the result of an async method. report is examined for the same information as the exceptions that would have been raised from calling GetProperties on the WebDocument object. The calls to the sink are considered Done if this method is called. *) Asynchronous PropertiesProblem( report : PropertiesProblemReport), (* ReceiveProperties is called as a result of a SendRenderingAndProperties call on a WebDocument. *) Asynchronous ReceiveProperties (theproperties : NgProperty.PropertySequence) End; (* ************************************************************************ *) (* ************************** WebDocument Interface *********************** *) (* A WebDocument is meant to be an NG version of roughly what Web documents are today *) Type WebDocument = Object Supertypes NgRendering.Renderable, NgProperty.PropertySet End (* ************ Properties which may be accessible via the property set interface include Authors - a NgBasic.StringSequence, The authors of this document CreationTime - a NgBasic.AbsoluteTime Version - a NgBasic.Version, Summary a NgBasic.String - some (human readable) summary of what the document is Note: The next two are analogous to the lastModified and expires members of the ResponseCacheControl Record LastModificationTime a NgBasic.AbsoluteTime ExpectedChange an NgBasic.AbsoluteTime - when this document is expected to change *********** *) Methods (* basically a combination of the GetRendering and GetProperties methods *) GetRenderingAndProperties ( renderingPreferences : NgRendering.RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, out responseCacheInfo : NgCache.OptionalResponseCacheControl, propertiesToGet : NgProperty.PropertyNames, Out theproperties : NgProperty.PropertySequence ) : NgRendering.Rendering Raises NgRendering.NoRenderingMatch, NgProperty.UnknownPropertyNames, NgBasic.WouldBlock, NgBasic.ObjectNotExist End, (* SendRenderingAndProperties is just like GetRenderingAndProperties only instead of synchronusly returning the results, they are sent asynchronously via calls to the ReceiveRenderingAndProperties method on the supplied RenderingAndPropertiesSink. The number of bytes in each Rendering sent is up to the caller of ReceiveRenderingAndProperties, but should be part of the range specified in renderingPreferences. If present, suggestedChunkSize is a suggestion on how large to make the data in the calls to ReceiveRenderingAndProperties. Typically, the implementation of SendRenderingAndProperties would arrange the following sequence of calls on the RenderingAndPropertiesSink. (Where [] indicates optional and * indicates zero or more.) When things are successful: [RegisterSourceControl] [RegisterResponseCacheControl] ReceiveProperties ReceiveRendering ReceiveRenderingChunk* Done When there's a problem: RenderingProblem OR PropertiesProblem See RenderingAndPropertiesSink's ReceiveRenderingAndProperties method.*) Asynchronous SendRenderingAndProperties ( renderingPreferences : NgRendering.RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, propertiesToGet : NgProperty.PropertyNames, renderPropSink : RenderingAndPropertiesSink, suggestedChunkSize : NgBasic.OptionalCardinal ), (* A Synchronous version of SendRenderingAndProperties. The intent is to allow the caller to simply know that the call was received. *) SendRenderingAndPropertiesSynched( renderingPreferences : NgRendering.RenderingPreferences, requestCacheInfo : NgCache.OptionalRequestCacheControl, propertiesToGet : NgProperty.PropertyNames, renderPropSink : RenderingAndPropertiesSink, suggestedChunkSize : NgBasic.OptionalCardinal ) End; (* ************************************************************************ *) (* *************** WebDocument that you can 'Put' to ********************** *) Type PutableWebDocument = Object Supertypes NgDocument.WebDocument, NgRendering.PutableRenderable, NgProperty.PutablePropertySet End Methods (* basically combination of the PutRendering and PutProperties methods *) PutRenderingAndProperties ( renderingInput : NgRendering.Rendering, propertiesToSet : NgProperty.PropertyModificationSequence) Raises NgRendering.NoRenderingMatch, NgProperty.UnknownPropertyNames, NgBasic.WouldBlock, NgBasic.Conflict, NgBasic.ObjectNotExist End End; (* ************************************************************************ *) (* ************** HTTPCompatibleWebDocument Interface ************ ******** *) (* A HTTPCompatibleWebDocument is a WebDocument that can also be accessed via HTTP 1.x Get, Head and Post calls. *) Type HTTPCompatibleWebDocument = Object Supertypes WebDocument, iluhttp.Resource End ; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgForm.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** FormProcessors ***************************** *) (* ************************************************************************ *) (* An Object of type FormProcessor is able to process Form based input, and produce an appropriate rendering as a response. *) Interface NgFormProcessor Brand "NG" Imports NgBasic From ngbasic.isl, IANA-Charsets-Registry From ianacharsets.isl, NgCache From ngcache.isl, NgRendering From ngrendering.isl End; (* ************************************************************************ *) (* ********************* Form entries ************************************ *) (* a Form input element is simply a named form field paired with some value *) Type FormInputElement = NgBasic.NameValuePair; Type FormInputElementSequence = Sequence Of FormInputElement; Type FormInputElementNames = NgBasic.NameSequence; (* ************************************************************************ *) (* ******************** FormProcessing Exceptions ************************* *) (* The listed form inputs has invalid values *) Exception InvalidFormEntries : FormInputElementNames; (* ************************************************************************ *) (* ********************** ProcessedFormSink ****************************** *) (* a FormProblemReport is used to pass information to asynchronous callbacks that would have normally been passed back as an exception from the synchronous version of the same sort of call *) Type FormProblemReport = Union invalidEntries : FormInputElementNames, conflict : NgBasic.ExceptionInformation, objectNotExist : NgBasic.ExceptionInformation End; Type OptionalFormProblemReport = Optional FormProblemReport; (* A ProcessedFormSink is basically a NgRendering.RenderingSink except that there are some more problems that can be reported *) Type ProcessedFormSink = Object Supertypes NgRendering.RenderingSink End Methods (* FormProblem is called when a Form related exception would have been raised from calling ProcessForm (with the same args as SendForm) on the FormProcessor object. This is basically to allow exceptions to be passed back as the result of an async method. report is examined for the same information as the exceptions that would have been raised from calling ProcessForm on the FormProcessor object. The calls to the sink are considered Done if this method is called. *) Asynchronous FormProblem ( report : FormProblemReport ) End; (* ************************************************************************ *) (* *********************** FormProcessor Object *************************** *) Type FormProcessor = Object Supertypes NgBasic.NgObject End Methods (* ProcessForm - The caller supplies a FormInputElementSequence describing the form data. If the supplied formEntries input is unacceptable (e.g. wrong type, etc.) the callee raises the InvalidFormEntries exception which contains a sequence of the names of the entries which were unacceptable, else a Rendering is returned. *) ProcessForm ( formEntries : FormInputElementSequence, out responseCacheInfo : NgCache.OptionalResponseCacheControl ) : NgRendering.Rendering Raises InvalidFormEntries, NgBasic.WouldBlock, NgBasic.Conflict, NgBasic.ObjectNotExist End, (* SendFormReply is just like ProcessForm only instead of synchronously returning the Rendering, it sends it asynchronously via a call to the ReceiveFormResult method on the supplied ProcessedFormSink *) Asynchronous SendFormReply ( formEntries : FormInputElementSequence, formSink : ProcessedFormSink ), (* A Synchronous version of SendForm. The intent is to allow the caller to simply know that the call was received. *) SendFormReplySynched( formEntries : FormInputElementSequence, formSink : ProcessedFormSink ) End; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ NgCache.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* ************************************************************************ *) (* *************************** Caching Control **************************** *) (* ************************************************************************ *) (* Caching control provides cache and proxy relevant information that may be sent along with requests and responses. This mostly mimics the cache related headers and Cache-Control header values found in HTTP 1.1. See that specification for the semantics. *) Interface NgCache Brand "NG" Imports NgBasic From ngbasic.isl End; (* ************************************************************************ *) (* *************************** Entity tags ******************************** *) Type EntityTag = NgBasic.String; Type OptionalEntityTag = Optional NgBasic.String; Type EntityTagSequence = Sequence Of EntityTag; Type EntityTagOrDate = Union etag : EntityTag, ifdate : NgBasic.AbsoluteTime End; (* ************************************************************************ *) (* ***************** Request Cache Control ******************************** *) Type RequestCacheControl = Record (* analogous to HTTP Cache-Control header values *) noCache : Boolean, noStore : Boolean, noTransform : Boolean, onlyIfCached : Boolean, (* analogous to HTTP If-ModifiedSince, If-Match, If-None-Match and If-Range headers *) ifModifiedSince : NgBasic.OptionalAbsoluteTime, ifMatch : EntityTagSequence, ifNoneMatch : EntityTagSequence, ifRange : EntityTagOrDate End; Type OptionalRequestCacheControl = Optional RequestCacheControl; (* ************************************************************************ *) (* ***************** Response Cache Control ******************************* *) Type ResponseCacheControl = Record (* analogous to HTTP Cache-Control header values*) okPublic : Boolean, isPrivate : Boolean, noCache : Boolean, noStore : Boolean, noTransform : Boolean, mustRevalidate : Boolean, proxyRevalidate : Boolean, maxAge : NgBasic.OptionalRelativeTime, sMaxAge : NgBasic.OptionalRelativeTime, (* analogous to HTTP Age, Vary, Etag, Last-Modified and Expires headers *) age : NgBasic.OptionalRelativeTime, vary : NgBasic.StringSequence, entityTag : OptionalEntityTag, lastModified : NgBasic.OptionalAbsoluteTime, expires : NgBasic.OptionalAbsoluteTime End; Type OptionalResponseCacheControl = Optional ResponseCacheControl; (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *) ------------------------------------------------------ IANACharSets.isl (* ************************************************************************ *) (* Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98 This work is very preliminary - Comments welcomed and encouraged! 'xxx' marks areas where thought is definitly needed Please send comments, suggestions, contributions, etc. to the http-ng mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com. *) (* ************************************************************************ *) (* *************************** IANA Charsets ****************************** *) (* ************************************************************************ *) (* Defines standard charsets. *) Interface IANA-Charsets-Registry Brand "NG" ; Type CharsetMIBEnumValue = Short Cardinal; Type CharsetMIBEnumValueSequence = Sequence Of CharsetMIBEnumValue; Type OptionalCharsetMIBEnumValue = Optional CharsetMIBEnumValue; Constant US-ASCII : CharsetMIBEnumValue = 3; (* XXX need to complete the list *) (* ************************************************************************ *) (* ******************************** END *********************************** *) (* ************************************************************************ *)