Developing an Access plug-in

Access plug-in overview

Important: Every edition of the server supports Access plug-ins. However, the Access plug-in is not supported over RTMFP connections.

An Access plug‑in adds another layer of security to the server; it intercepts connection requests and lets you examine the client and the server to determine whether requests should be accepted, rejected, or redirected before the requests reach the server’s script layer. You can only use one Access plug‑in.

You can code the plug‑in to accept, reject, or redirect requests based on criteria like how many users are connected to the server and the amount of bandwidth being consumed.

You can query your organization’s database of users and passwords to determine which connection requests should be allowed. Once the plug‑in accepts the connection, you can update the database with a record of the user’s access to the server.

You can set read and write access for files and folders on the server, set permissions to access audio and video bitmap data, and inspect client properties.

Access plug-in connection flow

Once you’ve installed an Access plug‑in, it is initialized with a context pointer when the server starts. The context pointer and plug‑in pointer provide two-way communication between the Access plug‑in and the server.

When a client attempts to connect to the server, the server determines whether or not an Access plug‑in exists. If the Access plug‑in is available, it examines the connection request and either authorizes, rejects, or redirects the connection. If an Access plug‑in is not available, connection requests proceed as usual.

Note: There can only be one Access plug‑in per server installation.

Rewriting connections to the server

Both the Access and Authorization plug‑ins let you authorize connections to the server. However, the plug‑ins run at different places and are active in different stages of the connection process.

New connections arrive at the edge process (amsedge), and the data in the connection message is sent to the Access plug‑in (which runs in the edge process). At this stage, the plug‑in has information about the client such as IP address, the originating URL of the SWF file, the connection (or target) URI, user agent, and so on. Using this information, the Access plug‑in can accept, reject, or redirect the connection, or rewrite the target URI. Rewriting the target URI forces the connection to a different vhost, application, or application instance. The plug‑in can’t rewrite a connection to a different adaptor because the socket-level connection to the adaptor has already been made.

You must use the Access plug‑in to force incoming connections to a different vhost, application, or application instance; it is too late to rewrite the target URI by the time the Authorization plug‑in is notified. Also, since the Access plug‑in runs early in the connection process, it is the most efficient way to screen connections. If you want authorization to be as lightweight as possible, use the Access plug‑in, even if you don’t need to rewrite the connection URI.

The Authorization plug‑in runs in the core process (fmscore) after the connection has been forwarded to the application. The Authorization plug‑in can accept, reject, or redirect attempts by clients to connect to applications, but it cannot rewrite connections to different URIs.

Note: Redirecting a connection is different than rewriting a connection URI. Redirecting a client sends a redirection message containing a new URI back to the client and terminates the current connection. The client then attempts to connect to the new URI.

Writing the code in an Access plug-in

You can either modify the code in the sample Access plug‑in file provided by Adobe, or you can write your own plug‑in.

A client connection request triggers the onAccess() callback function in the Access plug‑in. Write the code that examines connection requests, modifies client properties, and accepts, rejects, or redirects the requests in the onAccess() callback function.

Call getValue() to query client fields. Call setValue() to modify client fields. For a list of fields, see the fms_access namespace in the Flash Media Server Plug-in API Reference. The field x-page-url, the URL of the SWF file or the server in which a connection originated, was added in Adobe Media Server 3.5.

Call getStats() to query the following server statistics: eTOTAL_CONNECTED, eBYTES_IN, and eBYTES_OUT.

After you’ve queried the fields and written your connection logic, call accept(), reject(), or redirect() to allow a client to connect to an application on the server or not.

Assigning an application to a core process

You can dynamically assign an application to a core process. Use this feature to balance a load across core processes based on real-time performance counters, for example, CPU consumption and the size of the recorded media cache. You can also use this feature to provide a higher quality of service (QoS) to certain customers.

To specify which core process handles an application, pass the field "coreIdNum" and a core number to the setValue()function. The core number can be any positive integer. The server uses the following formula to determine which core process to use: core_number % number_of_ cores. For example, the following code assigns a core number of 3:

char* coreId = "3"; 
if(!setValue("coreIdNum", coreId))    { 
    FILE * pFile = fopen ("error.log","a"); 
    fprintf(pFile, "Core id = %s", coreId); 
}

You can call getValue() to find out which core process a client connection is assigned to, as in the following:

const char* coreId =  getValue("coreIdNum"); 
FILE * pFile = fopen ("output.txt","a"); 
fprintf(pFile, "Core id = %s", coreId);

Load balancing

You can code the Access plug‑in to monitor performance metrics, such as CPU usage and the size of the recorded media cache, and balance loads accordingly. Distribution of applications across core processes is defined by numprocs and scope elements in Application.xml. For example, if numprocs is 3 and scope is set to application, each application gets three core processes to handle incoming connections. If a core process is overloaded, you can develop an Access plug‑in that ensures new incoming connections are not sent to the overloaded core process. One strategy is to write plug‑in code to do the following:

  1. Track statistics for each core process. Use the Administration APIs: getFileCacheStats(), getAppStats(), getInstanceStats().

  2. Whenever a new client connects, the plug‑in code must determine if the core process is overloaded. If it is, the plug‑in code determines the core ID of a different process (one that isn't overloaded) and sends the new connection to that process.

Quality of Service (QoS)

To provide higher QoS to certain clients, you can use certain core processes exclusively for certain clients. For example, suppose you want to provide the best possible performance to certain clients that are paying a premium subscription fee to access content. You can develop an Access plug‑in that distributes an application among six core processes and monitors the statistics for each process. Different core processes handle the connections to the application, depending on the client. Three core processes are reserved for the top clients; the remaining three are available to all other clients. The plug‑in monitors statistics for each process. If a particular process becomes overloaded, the plug‑in ensures that the overloaded process does not handle any new connections. The plug‑in can route new connections to processes that can handle them.

Configuring folder permissions on the server

The Access section of the Application.xml configuration file (located in each virtual host directory and possibly in application directories) lets you configure folder-level permissions for the Access plug‑in. If the FolderAccess element is set to true, you cannot use the readAccess and writeAccess fields in the Access plug‑in to set permissions for individual files, you can only set permissions at the folder level. The default value is false, which lets you set permissions for individual files, as in the following:

<!-- Controls libconnect.dll access configurations             --> 
<Application> 
    ... 
    <Client> 
        ... 
        <Access> 
            <FolderAccess>false</FolderAccess> 
        </Access> 
        ... 
    ... 
</Application>