Important: The information in this document is obsolete and should not be used for new development.
About Providers
A provider is a layered set of protocols, implemented by STREAMS modules, that provides some kind of data-oriented service. That service might be implementing a networking protocol, encrypting data, filtering data, and so on. When you configure a provider, you can layer the modules that implement the provider to create an arbitrarily complex service. For example, you can place an encryption module above the AppleTalk Data Stream Protocol (ADSP) module. This combination would provide a stream of network data that was secure from snooping on the network.Open Transport defines three main types of providers:
An endpoint provider offers a service that creates connections and moves data from one logical address to another. A mapper provider offers services that you use to associate, or "map," network entity names with network addresses. A service provider lets you perform tasks that are specific to a particular protocol, such as AppleTalk or TCP/IP. Each protocol family has the option of providing a service provider if one is needed.
- endpoint providers
- mapper providers
- service providers
In the normal course of events you do not communicate directly with the STREAMS modules that make up a provider. For example, to use an endpoint provider, you must open an endpoint and use the functions defined in the Open Transport application programming interface (API) for endpoints. The Open Transport API shields your application from the details of the provider implementation, allowing your application to run with little or no change, even when the implementation of the provider is changed, or updated.
To use a provider, you must initialize Open Transport and then call the function that opens the provider. When that function returns, it passes back to you a reference to the provider you have just created. A provider reference is like a file handle or a driver reference number. It associates a function called from your application with a specific provider that must implement the function; you pass the provider reference as a parameter to all provider functions. The data type of a provider reference depends on the type of the provider (endpoint reference, mapper reference, AppleTalk service reference, and so on).
You can open one provider or many. For example, a server application might open many providers and use them concurrently. The number of providers you can create is limited mainly by the availability of memory. The memory used to create a provider comes partly from your application heap but mostly from the system heap.
C++ note
- The C++ API for Open Transport includes a class called
TProvider
that is the superclass for all provider-related member functions. Endpoint functions are in classTEndpoint
, mapper functions are in classTMapper
, and service provider functions are in classes corresponding to specific protocol stacks. For example, the classesTAppleTalkServices
andTInternetServices
contain AppleTalk-specific and TCP/IP-specific member functions.
- In object-oriented programming parlance, endpoints, mappers, and the data structures maintained by Open Transport for service providers are all objects. An endpoint, for example, is an object instantiating the class
TEndpoint
. An endpoint contains all the data that Open Transport needs to link together software modules, drivers, and hardware for a specific endpoint provider. All of the Open Transport API functions except the functions that open providers and some utility functions are included in the class definitions of the various classes of providers.
- You can call public member functions of the
TProvider
class for provider objects of any type: these functions are the general provider functions. Public member functions defined in a subclass of theTProvider
class (for example,TEndpoint
) can be called only for providers belonging to that subclass--in this example, only from theTEndpoint
subclass. These functions are the type-specific provider functions. Note that, as with endpoints and mappers, each kind of service (for AppleTalk, TCP/IP, and so on) derives directly from theTProvider
class; there is no other class for services-type providers.Provider Functions
Functions that manipulate providers are known as provider functions. Some provider functions can manipulate providers of any type. These are called general provider functions and they are documented in detail in "Providers Reference". You use general provider functions to
In addition to the general provider functions, each type of provider has type-specific provider functions; these functions work with only that particular type of provider. For example, endpoint functions work only with endpoint providers, and mapper functions work only with mapper providers. Each type of service provider (for AppleTalk, TCP/IP, and so on) has its own type-specific provider functions.
- get or set a provider's default mode of operation, which determines whether provider functions execute synchronously or asynchronously, whether a provider can wait to send or receive data, and whether functions that send data make a copy of that data
- install and remove a notifier callback function, which the provider uses to pass information to your application
- send a module-specific command, which allows you to communicate directly with the STREAMS modules that make up your provider
- close a provider
Provider functions that accept a provider reference of type
ProviderRef
are general: they accept any other type of provider reference as well. But functions that require a type of provider reference other thanProviderRef
(for example,EndpointRef
) are type-specific: they accept only that type of provider reference.Interrupt-Time Processing
The Open Transport functions that you can call and the means by which you call them vary with the level of execution: system task time, deferred task time, and hardware interrupt time.In general you can call all Open Transport functions at system task time and most Open Transport functions, asynchronously, at deferred task time. At hardware interrupt time, you are much more limited: you cannot call any of the provider functions and you can call only a small number of Open Transport functions. Software executed at hardware interrupt level includes installable interrupt handlers for NuBus and other devices, Time Manager tasks, VBL tasks, and routines called from within a hardware interrupt handler.
Because it is possible to call many more Open Transport functions from deferred-task level than from hardware-interrupt level, if you need to call an Open Transport function from hardware-interrupt level, you can use the Open Transport function
OTScheduleDeferredTask
or the system functionDTInstall
to have those functions execute at deferred task time. Deferred tasks are scheduled to run when all other hardware interrupt processing is done but before system task processing resumes.For more information about execution levels and deferred tasks, see Inside Macintosh: Processes. For a more detailed view of processing and Open Transport, see Chapter 5, "Programming With Open Transport." For a list of those functions you can call at hardware-interrupt level and deferred-task level, see "Special Functions".
Modes of Operation
For each provider, you can use general provider functions to specify how providers execute, whether the provider can block when sending or receving data, and whether endpoint providers acknowledge sends.A provider can execute in synchronous mode or in asynchronous mode. In synchronous mode, provider functions return only when they complete execution. In asynchronous mode, they return as soon as they are queued for execution.
A provider's blocking status affects how functions that send and receive data behave when they must wait to complete an operation. If a provider is blocking, it either waits for as long as it takes to send or receive data (for a synchronous call) or it returns with a result indicating why the operation could not be done immediately (asynchronous call). If a provider is nonblocking, the provider attempts to send or receive data and, if it cannot do so immediately, it returns with a result indicating why it could not complete the operation.
A provider's mode of execution and blocking status act together to control the provider's behavior. There are four possible combinations; of these, though only three offer a practical use:
A provider's blocking status also governs what happens when you close a provider. In non-blocking mode, closing the provider flushes all outgoing commands in the stream and immediately closes the provider. In blocking mode, the stream is given up to 15 seconds per module to allow outgoing commands to be processed before the stream is closed.
- synchronous blocking
In this mode, if flow control or other conditions prevent data from being sent or received, the function returns when it is actually able to send or receive the data. Placing a provider in sychronous blocking mode can halt all operations on a Mac OS computer until the operation can complete. For information on how to manage this situation, see "Specifying How Provider Functions Execute".
- synchronous nonblocking
In this mode, if flow-control conditions prevent data from being sent or received, the function returns with the result
kOTFlowErr
or a number indicating only a partial send. Open Transport calls the provider's notifier with aT_GODATA
orT_GOEXDATA
event when flow control lifts. You must call the function again to continue to send or receive data.
- asynchronous blocking
In this mode, if flow-control conditions prevent data from being sent or received, the function returns with the result
kOTFlowErr
or a number indicating only a partial send. Open Transport calls the provider's notifier with aT_GODATA
orT_GOEXDATA
event when flow control lifts. You must call the function again to send or receive data. If the function cannot complete due to contention for STREAMS resources, it will wait until the required resources are available.
- asynchronous nonblocking
In this mode, if flow-control conditions prevent data from being sent or received, the function returns with
kOTFlowErr,
It can also returnkEAgainErr
. if the function cannot execute as a result of contention for STREAMS resources. Since the point of using asynchronous functions is to be able to continue processing undisturbed until the function returns, using asynchronous nonblocking mode is not practical, as the function might return with thekEAgainErr
result a number of times before it actually completes.
A provider's send-acknowledgment status determines whether endpoint functions that send data make an internal copy of the data before sending it. Open Transport ignores the send-acknowledgment status for mapper and service providers.
For specific recommendations about which mode to use and how to set that mode, see "Controlling a Provider's Modes of Operation".
Provider Events
Open Transport defines three kinds of events called provider events. These events are unique to the Open Transport architecture and are not events in the usual Macintosh sense: they are not processed by the Event Manager, and they have no associated Event Record. Rather, Open Transport uses provider events to inform your application that something has occurred which demands your immediate attention or to signal the fact that a function executing in asynchronous mode has completed. The first kind of provider event is called an asynchronous event, the second kind is called a completion event, and the third kind is called a miscellaneous event. In this book, the term event refers to a provider event, except where noted otherwise.A provider uses asynchronous events to notify your application that data has arrived or that a request for a connection or disconnection is pending. Most asynchronous events defined for Open Transport have equivalents in the X/Open Transport Interface (XTI), from which the Open Transport interface derives.
XTI does not define completion events. A provider uses completion events to notify your application that an asynchronous function has finished executing. Some functions are inherently synchronous and have no corresponding completion event. For example, if an endpoint provider is in asynchronous mode and you execute the
OTGetEndpointState
function, the function returns information about the state of the endpoint immediately. The description of a function indicates whether the function behaves differently in asynchronous mode.Miscellaneous events are used to notify you or warn you of a change of state in the provider: for example, the provider is about to be closed.
A provider event is identified by a provider event code. These are listed and described in the event codes enumeration .
In general, to receive notice of provider events, you must provide a notifier function and install it for the provider. A notifier function is a function that you write and that the provider will call when an event occurs. When the provider calls this function, it uses the function's parameters to pass back information about the event that occurred, and if this is a completion event, it also passes back additional information about the result of the function that completed and a pointer to any other information passed back by the function. The section "Using Notifier Functions to Handle Provider Events" provides additional information about notifier functions and the issues involved in asynchronous processing. You can also refer to "Using Notifier Functions" for a description of the notifier functions.
- Completion events have a prefix of
T_
and the suffixCOMPLETE
; for example,T_BINDCOMPLETE
.- Asyncronous events have a prefix of
T_
and no uniform suffix; for example,T_DATA
orT_MEMORYRELEASED.
- Miscellaneous events have a prefix of
kOT
and no uniform suffix; for example,kOTProviderWillClose
.
Function Results
Most Open Transport functions return a result of typeOSStatus
orOTResult
. The main difference between these is that a result of typeOSStatus
is either 0 (kOTNoError
) or a negative number indicating an error code; a result of typeOTResult
can be either a positive value whose meaning varies with the function called or a negative value indicating an error code. Appendix B lists all result codes returned by Open Transport.
The discussion of functions in the reference section of this book describes the meaning of the errors that are most likely to occur for each function. In addition, every Open Transport function might return the result codes listed in Table 3-1. For additional information, please look up the meaning of these result codes in Appendix B .
- For synchronous function calls, a result of
kOTNoError
indicates that the function succeeded. A negative value indicates an error.- For asynchronous function calls, if the result code is
kOTNoError
, the operation was successfully started. When the function completes execution, the provider will call the notification function you installed with an event code to indicate which operation completed and a result code indicating whether it succeeded. If an asynchronous function returns any immediate result other thankOTNoError
, this means that the operation failed before it was started; your notifier will not be called.
Table 3-1 Result codes that all Open Transport functions can return
Subtopics
- Provider Functions
- Interrupt-Time Processing
- Modes of Operation
- Provider Events
- Function Results