.. _appendix-a: ==================== Appendix A – RLM API ==================== This appendix lists all the RLM API calls in alphabetical order. To call any of the functions in the RLM API, you need to include the RLM header file “license.h”: .. code-block:: text #include "license.h" ********** RLM_HANDLE ********** RLM_HANDLE is the main handle in RLM. Your program needs to call **rlm_init()** to get a handle; this only needs to be done once. This handle (or an RLM_LICENSE handle) is passed to all the RLM API calls. *********** RLM_LICENSE *********** RLM_LICENSE is the license handle in RLM. This handle is returned from the **rlm_checkout()** call and is passed to the **rlm_license_stat()**, **rlm_get_attr_health()** and **rlm_checkin()** calls. N.B. RLM_LICENSE is also the name of the environment variable for specifying the license file path. .. include:: ../core-api.rst .. include:: ../advanced-api.rst Namespace ========= * All RLM client library functions have names beginning with \rlm_ or \_rlm_. * All defined constants in license.h begin with \RLM_ All the RLM API functions are described (in alphabetical order) on the following pages. ------ .. _rlm-act-request: rlm_act_request() ================= Request license activation from the internet -------------------------------------------- .. note:: New code should use the *rlm_activate()* call instead of *rlm_act_request()*. *rlm_act_request()* will be supported in the future, but all new options will be added only to *rlm_activate()*. .. code-block:: text #include "license.h" RLM_HANDLE rh; int stat; const char *url; const char *isv; const char *akey; const char *hostid_list; const char *hostname; int count; const char *extra; char license[RLM_ACT_MAX_LICENSE+1]; rh = rlm_init(...); stat = rlm_act_request(rh, url, isv, akey, hostid_list, hostname, count, extra, license); *rlm_act_request()* requests a license activation from the server at *url* for ISV name *isv*. The activation key *akey* and license count *count* are sent to the server. .. note:: If the license count is <= 0, a count of 1 is used. A count of 0 requests that all remaining licenses be fulfilled for this request. In this way, your activation code does not need to supply the number of licenses ordered during fulfillment time. Note that a request of 0 will not retrieve an already-activated license - in order to re-retrieve an already-activated license, you must specify the number of licenses actually generated. If either the *akey* or *extra* parameter contains an embedded newline, *rlm_act_request()* will return RLM_EL_BADPARAM. The ISVNAME_ACT_URL environment variable will override the *url* parameter to this call. This allows you to change the URL of the activation server without rebuilding your software. For example, if your ISV name is “demo”, the environment variable would be named “DEMO_ACT_URL”, and you would set it to the URL to use for activation if the *url* parameter in this call is no longer correct. .. note:: The URL should **always** be http, never https. rlm_act_request() encrypts the request independent of the webserver. *hostid_list* is a space-separated list of RLM standard hostids. If hostid_list is NULL or empty, the hostid list from the current machine is used. Note that ethernet addresses should be exactly 12 hex characters (without the leading "0x"), and 32-bit hostids should be hex numbers without the leading "0x". RLM will select a hostid from this list for use in the license, as described in the next paragraph. Prior to v11.0, RLM would only activate licenses with rehostable, non-zero RLM_HOSTID_32BIT, RLM_HOSTID_ETHER, RLMIDn, RLM_DISKSN, or ISV-defined hostids. Any other hostid will return an RLM_ACT_BAD_HOSTID_TYPE status from *rlm_act_request()*. You can specify exactly the hostids you will accept with the *rlm_isv_cfg_actpro_allowed_hostids()* call in rlm_isv_config.c, then either re-building your license generator or creating a new generator settings file. See :ref:`customizing-rlm-isv-config` for more details. The priority is (assuming the particular hostid type is enabled): * rehostable hostid * ISV-defined hostid * ISV string hostid * rlmid hostid * Disk Serial Number * ethernet address * UUID * 32-bit hostid * IP address hostid * user-based hostid * host-based hostid * serial number hostid * string hostid * DEMO hostid * ANY hostid If none of the hostid types above are present (or enabled), the activation software will return RLM_ACT_BAD_HOSTID_TYPE. If RLM_ACT_BAD_HOSTID_TYPE is returned, the “license” parameter will contain the decimal representation of the list of valid hostids (as defined in license.h, in the RLM_ACTPRO_ALLOW_xxx definitions). This parameter is a string which represents a decimal number containing a bitwise OR of the allowed hostid types. To decode the allowed hostid types from the license string, use code similar to this: .. code-block:: text allowed = atoi(license); The *hostid_list* parameter can contain a list of hostids for use in nodelocked licenses. This is specified with the following syntax: .. code-block:: text list:list-of-hostids For example: .. code-block:: text list:user=joe host=sam ip=192.16.7.23 3f902d8b0027 If a list is supplied, note the following: * The activation software uses the hostids in the list as you specified, even if they are not "secure". * If the license to be activated is a served license (floating), only the first hostid in the list is used. * The number of available activations on the activation key is decremented by 1 regardless of the number of hostids in the license created. * The hostid list must be less than RLM_ACT_MAX_HOSTID_LIST characters long (205) including the “list:” prefix. * The hostid list can contain no more than RLM_MAX_HOSTID_LIST (25) hostids. This capability can be used to create a license which works on 2 (or more) systems, e.g., to create a license for a primary and a backup system. It can also be used to pass a hostid of a less secure type to be used, e.g., the *hostid-list* "list:ip=172.16.7.12" will cause the activation software to use the IP address as a hostid without returning RLM_ACT_BAD_HOSTID_TYPE. If *hostname* is NULL or empty, the hostname of the current machine is used. *extra* is a string containing extra "keyword=value" license attributes. These must be valid RLM license syntax, not just any keyword=value pair. .. note:: The extra string should not contain characters illegal in license files, and most particularly, it should not contain the '&' character, which is illegal in a license file and also is the cgi separator in web requests. If you put spaceseparated strings into the *extra* parameter, be sure to enclose them in quotes. For example: set *extra* to "customer=\"Your Customer Name Here\"" in order to put your customer name into the generated license, or set it to "customer=\"Your Customer Name Here\" min_timeout=100" to set your customer name and the minimum timeout. The parameter *license* must be an allocated string of length RLM_ACT_MAX_LICENSE+1. If *rlm_act_request()* succeeds, the activated license is returned in this string. For certain errors, the *license* string will contain MySQL error information, otherwise it will be an empty string. .. _rlm-act-error-returns: Error Codes ----------- Status returns >=0 indicate success, < 0 are failure status. .. list-table:: :header-rows: 1 * - Status - Meaning * - 0 - License was activated, first request, activation count consumed. * - 1 - License previously activated. Activation count is not consumed; the prior license is returned. This status indicates that a duplicate activation key/count/hostid was sent to the server. * - RLM_ACT_BADPARAM - Bad parameter to activation function. * - RLM_ACT_NO_KEY - No Activation key supplied. * - RLM_ACT_NO_PROD - No product definition (internal database error). * - RLM_ACT_CANT_WRITE_KEYS - Cannot write activation keys (admin tool). * - RLM_ACT_KEY_USED - Activation key used already (no count remaining). * - RLM_ACT_BAD_HOSTID - Missing hostid. * - RLM_ACT_BAD_HOSTID_TYPE - Invalid hostid type. * - RLM_ACT_BAD_HTTP - Bad HTTP transaction. * - RLM_ACT_CANTLOCK - Cannot lock activation database. * - RLM_ACT_CANTREAD_DB - Cannot read activation database. * - RLM_ACT_CANT_WRITE_FULFILL - Cannot write fulfillment (licf) table. * - RLM_ACT_CLIENT_TIME_BAD - Time difference too great from server → client system. * - RLM_ACT_BAD_REDIRECT - Bad HTTP Redirect. * - RLM_ACT_TOOMANY_HOSTID_CHANGES - Too many hostid changes for redirect. * - RLM_ACT_BLACLISTED - Domain on blacklist. * - RLM_ACT_NOT_WHITELISTED - Domain not on whitelist. * - RLM_ACT_KEY_EXPIRED - Activation Key expired. * - RLM_ACT_NO_PERMISSION - HTTP request denied. * - RLM_ACT_SERVER_ERROR - HTTP internal server error. * - RLM_ACT_BAD_GENERATOR - Bad or missing license generator file. * - RLM_ACT_NO_KEY_MATCH - No matching activation key found in database. * - RLM_ACT_NO_AUTH_SUPPLIED - No proxy authentication credentials supplied. * - RLM_ACT_PROXY_AUTH_FAILED - Proxy authentication failed. * - RLM_ACT_NO_BASIC_AUTH - Activation supports only BASIC proxy authentication. * - RLM_EH_CANTCONNECT_URL - Cannot connect to specified URL. * - RLM_ACT_GEN_UNLICENSED - Activation generator unlicensed. * - RLM_ACT_DB_READERR - Activtion DB read error (MySQL). * - RLM_ACT_GEN_PARAM_ERR - Generating license - bad parameter. * - RLM_ACT_UNSUPPORTED_CMD - Unsupported command to generator. **If you are using Activation Pro, you should consult the Activation Pro manual for** **troubleshooting tips and additional error returns.** .. _rlm-act-proxy-support: Proxy Server Support -------------------- RLM activation has support for proxy servers. To use a proxy server, there are 2 environment variables which must be set: **HTTP_PROXY**- set to the hostname:port of the proxy server. For example, if your proxy server is on port 8080 on host proxy_host: .. code-block:: text % setenv HTTP_PROXY proxy_host:8080 If your proxy server uses authentication, you can use the HTTP_PROXY_CREDENTIALS environment variable to pass the credentials to the proxy server: **HTTP_PROXY_CREDENTIALS** - the username and password to authenticate you to the proxy server, in the format user:password. For example, if your username is "joe" and password is "joes_password": .. code-block:: text % setenv HTTP_PROXY_CREDENTIALS joe:joes_password .. note:: RLM activation supports only the BASIC authentication type. You can either set these environment variables before running your application or use putenv() (or rlm_putenv()) to set them inside your application before calling *rlm_act_request()*. rlm_act_request() encrypts the data sent to the activation server. If RLM_ACT_NO_ENCRYPT is set in the environment, *rlm_act_request()* will not encrypt the data sent to the activation server. Back to :ref:`appendix-a`. ------ .. _rlm-activate: rlm_activate() ============== Request a license activation from the internet. ----------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; int stat; const char *akey; int count; char license[RLM_ACT_MAX_LICENSE+1]; RLM_ACT_HANDLE act_handle; rh = rlm_init(...); stat = rlm_activate(rh, url, akey, count, license, act_handle); *rlm_activate()* is the preferred call to request license activation from the internet. *url* is the location of the activation server (without the trailing /cgi-bin/ISV_mklic) The activation key *akey* and license count *count* are sent to the server. .. note:: If the license count is <= 0, a count of 1 is used. A count of 0 has a special meaning for *NORMAL* activation fulfillments of *floating* licenses – a count of 0 requests that all remaining licenses be fulfilled for this request. In this way, your activation code does not need to supply the number of licenses ordered during fulfillment time. .. note:: A request of 0 will not retrieve an already-activated license - in order to re-retrieve an already-activated license, you must specify the number of licenses generated. If the *akey* parameter contains an embedded newline, *rlm_act_request()* will return RLM_EL_BADPARAM. The ISVNAME_ACT_URL environment variable will override the *url* parameter to this call. This allows you to change the URL of the activation server without rebuilding your software. For example, if your ISV name is “demo”, the environment variable would be named “DEMO_ACT_URL”, and you would set it to the URL to use for activation if the *url* parameter in this call is no longer correct. .. note:: The URL should always be HTTP, *never* HTTPS. *rlm_activate()* encrypts the request independent of the webserver. Prior to v11.0, RLM would only activate licenses with rehostable, non-zero RLM_HOSTID_32BIT, RLM_HOSTID_ETHER, RLMIDn, RLM_DISKSN, or ISV-defined hostids. Any other hostid will return an RLM_ACT_BAD_HOSTID_TYPE status from *rlm_act_request()*. You can specify exactly the hostids you will accept with the *rlm_isv_cfg_actpro_allowed_hostids()* call in rlm_isv_config.c, then either re-building your license generator or creating a new generator settings file. See :ref:`customizing-rlm-isv-config` for more details. The priority is (assuming the particular hostid type is enabled): * rehostable hostid * ISV-defined hostid * ISV string hostid * rlmid hostid * Disk Serial Number * ethernet address * UUID * 32-bit hostid * IP address hostid * user-based hostid * host-based hostid * serial number hostid * string hostid * DEMO hostid * ANY hostid If none of the hostid types above are present (or enabled), the activation software will return RLM_ACT_BAD_HOSTID_TYPE. If RLM_ACT_BAD_HOSTID_TYPE is returned, the “license” parameter will contain the decimal representation of the list of valid hostids (as defined in license.h, in the RLM_ACTPRO_ALLOW_xxx definitions). This parameter is a string which represents a decimal number containing a bitwise OR of the allowed hostid types. To decode the alllowed hostid types from the license string, use code similar to this: .. code-block:: text allowed = atoi(license); You can override RLM's notion of the hostid by calling *rlm_act_set_handle()* with the RLM_ACT_HANDLE_HOSTID_LIST parameter. The *hostid_list* parameter can contain a list of hostids for use in nodelocked licenses. This is specified with the following syntax: .. code-block:: text list:list-of-hostids For example: .. code-block:: text list:user=joe host=sam ip=192.16.7.23 3f902d8b0027 If a list is supplied, note the following: * The activation software uses the hostids in the list as you specified, even if they are not "secure". * If the license to be activated is a served license (floating), only the first hostid in the list is used. * The number of available activations on the activation key is decremented by 1 regardless of the number of hostids in the license created. * The hostid list must be less than RLM_ACT_MAX_HOSTID_LIST characters long (205) including the “list:” prefix. * The hostid list can contain no more than RLM_MAX_HOSTID_LIST (25) hostids. This capability can be used to create a license which works on 2 (or more) systems, e.g., to create a license for a primary and a backup system. It can also be used to pass a hostid of a less secure type to be used, e.g., the *hostid-list* "list:ip=172.16.7.12" will cause the activation software to use the IP address as a hostid without returning RLM_ACT_BAD_HOSTID_TYPE. If *act_handle* is NULL, no optional parameters are specified. If *act_handle* is passed to *rlm_activate()* as a non-NULL handle, other, lesser-used parameters can be specified: * **isvname** – if different from your ISV name. * **hostid** – if you do not want to use the default hostid. * **hostname** – if you want to change the notion of your hostname * **extra** – any extra license parameters * **log** – information to log to the activation server (Activation Pro only). These other parameters are passed in by calling *rlm_act_new_handle()* and *rlm_act_set_handle()*. The parameter *license* must be an allocated string of length RLM_ACT_MAX_LICENSE+1. If *rlm_activate()* succeeds, the activated license is returned in this string. For certain errors, the *license* string will contain MySQL error information, otherwise it will be an empty string. Error Codes ----------- See :ref:`rlm-act-error-returns` above. Proxy Server Support -------------------- See :ref:`rlm-act-proxy-support` above. Back to :ref:`appendix-a`. ------ .. _rlm-act-keyinfo2: rlm_act_keyinfo2() ================== Get the most info about an activation key. ------------------------------------------ .. _rlm-act-fulfill-info: rlm_act_fulfill_info() ====================== Get info about key and latest fulfillment. ------------------------------------------ .. _rlm-act-info: rlm_act_info() ============== Get info about an activation key from the server. ------------------------------------------------- .. _rlm-act-keyinfo: rlm_act_keyinfo() ================= Get info about an activation key from the server. ------------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; const char *url = “your activation server URL here”; char *akey = “activation-key-desired”; char product[RLM_MAX_PRODUCT+1]; char version[RLM_MAX_VER+1]; char upgrade_version[RLM_MAX_VER+1]; char exp[RLM_MAX_EXP+1]; char keyexp[RLM_MAX_EXP+1]; char hostid[RLM_MAX_HOSTID_STRING+1]; int date_based; int license_type; int status; int count, fulfilled, rehosts, revoked, allowed_hostids, sub_interval, sub_window; rh = rlm_init(...); status = **rlm_act_keyinfo2(rh, url, akey, product, version, &date_based, &license_type,** **upgrade_version, &count, &fulfilled, &rehosts, &revoked, exp, hostid, keyexp,** **&allowed_hostids, &sub_interval, &sub_window);** status = **rlm_act_info(rh, url, akey, product, version, &date_based, &license_type,** **upgrade_version);** status = **rlm_act_keyinfo(rh, url, akey, product, version, &date_based, &license_type,** **upgrade_version, &count, &fulfilled, &rehosts, &revoked);** status = **rlm_act_fulfill_info(rh, url, akey, product, version, &date_based, &license_type,** **upgrade_version, &count, &fulfilled, &rehosts, &revoked, exp, hostid);** .. note:: **rlm_act_keyinfo2()** returns a superset of the information from all the other calls, and it is the preferred call. The *rlm_act_info()* call presents the activation key *akey* to the server at *url* and retrieves information about the license which would be generated by this key. The *rlm_act_keyinfo()* returns everything that *rlm_act_info()* returns, plus some fulfillment information about the activation key. The *rlm_act_fulfill_info()* returns everything that *rlm_act_keyinfo()* returns, plus the actual expiration date and hostid from the most recent fulfillment on the activation key. If no fulfillments have been made (i.e., fulfill == 0), the return values exp and hostid are undefined. .. note:: The URL should **always** be HTTP, **never** HTTPS. rlm_act_info() encrypts the request independent of the webserver. .. note:: rlm_act_info() will return RLM_ACT_KEY_DISABLED with no further information for disabled activation keys. The *rlm_act_info()* call returns 0 for success, or an RLM error code otherwise. The returned information is passed back in the last 5 parameters: * **product** – the product name in the license that would be generated from this activation key. * **version** – the version in the generated license. If date_based is non-zero, this is a string representing an integer number of months; the version is a date-based version of the form yyyy.mm for this number of months after license generation. If date_based is 0, the actual license version is returned in this parameter. * **date_based** – non-zero indicates that the version string is the number of months after license generation for a date-based version. * **license_type** – this is the type of license that will be generated. These types are defined in license.h: .. code-block:: text #define RLM_ACT_LT_FLOATING 0 /* Floating */ #define RLM_ACT_LT_F_UPGRADE 4 /* Floating UPGRADE */ #define RLM_ACT_LT_UNCOUNTED 1 /* Nodelocked, Uncounted */ #define RLM_ACT_LT_NLU_UPGRADE 5 /* Nodelocked, Uncounted UPGRADE */ #define RLM_ACT_LT_SINGLE 3 /* Single */ #define RLM_ACT_LT_S_UPGRADE 7 /* Single UPGRADE */ * **upgrade_version** – the version eligible for an upgrade for UPGRADE type licenses. This is always a fixed string (ie, it is never date-based). For non-upgrade licenses, this will be an empty string. In addition to the above information, **rlm_act_keyinfo()** returns fulfillment information: * **count** – The allowed fulfillment count (0 = unlimited). * **fulfilled** – The # already fulfilled. * **rehosts** – The number of rehost operations allowed. * **revoked** – The number of revocations already performed. .. note:: When revoked==rehosts, no additional license revocations will be allowed. In addition to the above information, **rlm_act_fulfill_info()** returns recent fulfillment information: * **exp** – The actual expiration date of the latest fulfillment. This date is returned in the ActPro sortable date format of yyyy-mm-dd, rather than the RLM standard date format of dd-mmm-yyyy. * **hostid** – The hostid from the latest fulfillment. In addition to the above, **rlm_act_keyinfo2()** also returns: * **keyexp** – The expiration date of the activation key itself. This date is returned in the ActPro sortable date format of yyyy-mm-dd, rather than the RLM standard date format of dd-mmm-yyyy. * **allowed_hostids** – The bitmap of allowed hostids for this activation key. * **sub_interval** – The subscription interval, as follows: * -1: monthly subscription * -2: quarterly subscription * -3: annual subscription * >0: # of days in subscription interval * **sub_window** – The subscription window, in days .. note:: Unless you are doing offline activation, all rlm_actXXX() calls (except rlm_act_XXX_handle()) require internet access. Back to :ref:`appendix-a`. ------ .. _rlm-act-keyvalid: rlm_act_keyvalid(), rlm_act_keyvalid_license() ============================================== Verify that an activation key still has a valid license on this hostid from the activation server. -------------------------------------------------------------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; const char *url = “your activation server URL here”; char *akey = “activation-key-desired”; char hostid[RLM_MAX_HOSTID+1]; char license[RLM_ACT_MAX_LICENSE+1]; int status; rh = rlm_init(...); status = rlm_act_keyvalid(rh, url, akey, hostid); status = rlm_act_keyvalid_license(rh, url, akey, hostid, license); The *rlm_act_keyvalid()* call presents the activation key *akey* and *hostid* to the server at *url* and retrieves status of fulfilled licenses on this hostid for this activation key. This call is intended to be used for nodelocked licenses only. If you want to invalidate a floating license, use :ref:`alternate-server-hostids`. .. note:: The URL should **always** be HTTP, **never** HTTPS. *rlm_act_keyvalid()* encrypts the request independent of the webserver. The *rlm_act_keyvalid()* call returns: * 0 for success, ie, a non-revoked license has been generated on this hostid for this activation key. * RLM_ACT_KEY_DISABLED if the activation key itself is disabled. * RLM_ACT_KEY_NO_HOSTID if there is no fulfilled license matching this hostid for this activation key, or * RLM_ACT_KEY_HOSTID_REVOKED if the only fulfilled license(s) for this hostid on this activation key have been revoked, or * RLM_EH_ACT_OLDSERVER or RLM_ACT_UNSUPPORTED_CMD if the activation server is too old to process this request. There is no other returned information. The *rlm_act_keyvalid_licenese()* call performs the same operation with the same return as rlm_act_keyvalid(), but in addition, it returns the license if the status return is 0. In the case of a floating license which has had multiple fulfillments, the license returned will be one of the licenses generated with this activation key (in general, the first license generated). If the status return is non-zero, the contents of *license* are undefined. *rlm_act_keyvalid_license()* requires an RLM Activation Pro server to return the license. .. note:: Unless you are doing offline activation, all rlm_actXXX() calls (except rlm_act_XXX_handle()) require internet access. Back to :ref:`appendix-a`. ------ .. _rlm-act-new-handle: rlm_act_new_handle(), rlm_act_destroy_handle() ============================================== Create/destroy handle to pass activation parameters. ---------------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; RLM_ACT_HANDLE act_handle; rh = rlm_init(...); act_handle = rlm_act_new_handle(rh); (void) rlm_act_destroy_handle(act_handle); *rlm_act_new_handle()* creates a blank handle to pass optional activation parameters to *rlm_activate()*. *rlm_act_new_handle()* returns a NULL handle on error. Call *rlm_act_new_handle()* before calling *rlm_act_set_handle()*. After activation is complete, call *rlm_act_destroy_handle()* to free the memory associated with the handle. .. note:: Unless you are doing offline activation, all rlm_actXXX() calls (except rlm_act_XXX_handle()) require internet access. Back to :ref:`appendix-a`. ------ .. _rlm-act-set-handle: rlm_act_set_handle() ==================== Set data in activation handle. ------------------------------ .. code-block:: text #include "license.h" RLM_ACT_HANDLE act_handle; int stat; int what; void *val; stat = rlm_act_set_handle(act_handle, what, val); *rlm_act_set_handle()* sets various options in an activation handle in order to pass these activation parameters to *rlm_activate()*. *rlm_act_new_handle()* returns 0 for success, RLM_EH_BADPARAM on error (no handle supplied, no value supplied, or bad “what” value). Call *rlm_act_set_handle()* after calling *rlm_act_new_handle()*. After activation is complete, call *rlm_act_destroy_handle()* to free the memory allocated in the handle. *what* values: -------------- All values for the “what” parameter are defined in license.h: RLM_ACT_HANDLE_DISCONN: (int val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If set to 1, rlm_activate() will create a rehostable hostid, then return data in the “license” parameter. Take this data to an internet-connected system, pass the data back into rlm_activate() in the hostid_list parameter when requesting the activation (again with RM_ACT_HANDLE_DISCONN set). See :ref:`license-rehosting` for details on how to make these calls. RLM_ACT_HANDLE_EXTRA: (const char * val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter is used to pass extra license options to the activation server. *val* is a string containing extra "keyword=value" license attributes. These must be valid RLM license syntax, not just any keyword=value pair. .. warning:: The *val* string should not contain characters illegal in license files, and most particularly, it should not contain the '&' character, which is illegal in a license file and is also the cgi separator in web requests. If you put space-separated strings into the *extra* parameter, be sure to enclose them in quotes. For example: set extra to "customer=\"Your Customer Name Here\"" in order to put your customer name into the generated license, or set it to "customer=\"Your Customer Name Here\" min_timeout=100" to set your customer name and the minimum timeout. RLM_ACT_HANDLE_HOSTID_LIST: (const char * val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter is used if you want to pass a particular hostid (other than the default) or a list of hostids to the activation server. The *hostid_list* parameter can contain a list of hostids for use in nodelocked licenses. This is specified with the following syntax: .. code-block:: text list:list-of-hostids OR .. code-block:: text list-of-hostids For example: .. code-block:: text list:user=joe host=sam ip=192.16.7.23 3f902d8b0027 OR .. code-block:: text user=joe host=sam ip=192.16.7.23 3f902d8b0027 What is the difference between using “list:” and not? * With a leading “list:”, the hostid list is used without checking whether the hostids are allowed or not. For nodelocked licenses, the whole list will be in the license, meaning the license will work on any hostid in the list. * Without the leading “list:”, each hostid in the list will be checked against the allowed hostid types, and the “most secure” one present will be used. This is the default way that RLM passes client hostids to the activation server if you do not set RLM_ACT_HANDLE_HOSTID_LIST. If a list is supplied with a leading “list:”, note the following: * The activation software uses the hostids in the list as you specified, even if they are not "secure". * If the license to be activated is a served license (floating), only the first hostid in the list is used. * The number of available activations on the activation key is decremented by 1 regardless of the number of hostids in the license created. * The list will not be accepted by the server if encryption of the request is turned off with RLM_ACT_NO_ENCRYPT This capability can be used to create a license which works on 2 (or more) systems, e.g., to create a license for a primary and a backup system. It can also be used to pass a hostid of a less secure type to be used, e.g., the hostid-list "list:ip=172.16.7.12" will cause the activation software to use the IP address as a hostid without returning RLM_ACT_BAD_HOSTID_TYPE. RLM_ACT_HANDLE_HOSTNAME: (const char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter is used for the (rare) case where you want to pass a specific hostname to the activation server. RLM_ACT_HANDLE_LOG: (const char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter is used to pass a string to be logged in the activation server database. This parameter will override any setting of the RLM_ACT_LOG environment variable. .. warning:: The use of the RLM_ACT_LOG environment variable is deprecated and is not guaranteed to work in all future versions of RLM. Setting logging using the rlm_act_set_handle() call is preferred). RLM Activation Pro allows you to log an arbitrary string to the database every time you fulfill a license. This string can be up to 80 characters in length, and it will appear in the 'log' column in the *licf* table. This string cannot contain the '>', '<', or '&' characters. RLM_ACT_HANDLE_ISV: (const char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter, which takes a (char \*) value, is used to set the ISVname, if it is different from your ISV name. This will not normally be used. It is used, for example, in the RLM web interface to request an activation from a specified ISV's activation server. RLM_ACT_HANDLE_PRODUCT: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This parameter, which takes a (char \*) value, is used to set the product name when you are preparing to do activation of a rehostable hostid on a disconnected system. This will not normally be used. RLM_ACT_HANDLE_DISCONN should also be set when the product name is set. See :ref:`the Activation Pro manual ` for more information. RLM_ACT_HANDLE_REHOST: (int val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If set to 1, rlm_activate() will create a rehostable hostid, then activate the license using that rehostable hostid. If the hostid already exists for the product associated with the activation key, rlm_activate() will return RLM_EH_REHOST_EXISTS and will not proceed with the activation. .. warning:: Once created, the contents of the rehostable hostid directory **CANNOT BE TOUCHED, MODIFIED, ** **DELETED, or RESTORED from a BACKUP without invalidating the hostid**. REHOSTable hostids can be used with nodelocked, uncounted, and SINGLE licenses only. RLM_ACT_HANDLE_CONTACT: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_COMPANY: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_EMAIL: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_STATE: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_COUNTRY: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_U1: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RLM_ACT_HANDLE_U2: (char \* val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These 7 parameters, all of which take a (char \*) value, are used to set the contact and company of the person doing the activation. If any of these parameters are set, CONTACT and COMPANY must both be set, otherwise you will receive an RLM_AT_CONTACT_BAD error from rlm_activate(). Upon activation, this information will populate the contact and company tables. Back to :ref:`appendix-a`. ------ .. _rlm-act-refresh: rlm_act_refresh() ================= Request refreshing of all refreshable licenses. ----------------------------------------------- .. warning:: rlm_act_refresh() is deprecated in RLM v9.3, in favor of the new rehostable licenses. .. code-block:: text #include "license.h" RLM_HANDLE rh; char \*isv; void (*callback)(char \*licfile, char \*license, int status); rh = rlm_init(...); error_count = rlm_act_refresh(rh, isv, callback); *rlm_act_refresh()* requests refreshing of all the refreshable licenses known to rlm through the paths supplied to rlm_init() when *rh* was created, plus licenses pointed to by the RLM_LICENSE and _LICENSE environment variables, if set. The act of refreshing the license involves a transaction with the activation server. *isv* is your ISV name. *callback* is a function supplied by the ISV that is called after each individual license refresh is attempted. *licfile* is the name of the license file containing the rehostable license, *license* is the name of the license on which a refresh was attempted, and *status* is the status of the refresh attempt. Values of *status* are as for *rlm_activate()/rlm_act_request*, except that a status of 1 means that the license was refreshed earlier the same day. *callback* may be specified as NULL. If specified, *callback* is invoked for each successful license refresh as well as unsuccessful ones. *error_count* is the number of licenses where the refresh attempt failed. Back to :ref:`appendix-a`. ------ .. _rlm-act-rehost-revoke: rlm_act_rehost_revoke() ======================= Revoke a rehostable license. ---------------------------- .. _rlm-act-revoke-disconn: rlm_act_revoke_disconn() ======================== Revoke a disconnected rehostable license. ----------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; char \*url; char \*product, *param; char retval[RLM_ACT_MAX_LICENSE+1]; int stat, flags; rh = rlm_init(...); stat = rlm_act_rehost_revoke(rh, url, product, flags); stat = rlm_act_revoke_disconn(rh, url, param, retval); *rlm_act_rehost_revoke()* causes RLM to revoke a rehostable hostid by taking the following actions: * Contacts the activation server at url and tells it to revoke all activations performed for the revokable hostid for product product. * Removes the hostid for product from the system. *flags* is one or more of the following values, ORed together: .. list-table:: * - RLM_ACT_REVOKE_REFERENCE - Revoke using the reference hostid if the hostid is not found on this system. * - RLM_ACT_REVOKE_NOFULFILL - Removes the rehostable hostid even if the activation server does not think there is a fulfillment. * - RLM_ACT_REVOKE_NODEL - Tells the server to revoke the fulfillment even if the rehostable hostid cannot be deleted. If *rlm_act_rehost_revoke()* cannot contact the activation server, or no fulfillments have been made using rehostable hostids for *product*, or the rehostable hostid for product does not exist, and none of the 3 possible conditions specified in *flags* corrects this, *rlm_act_rehost_revoke()* will return a non-zero error status. Otherwise, *rlm_act_rehost_revoke()* returns a 0 status to indicate success. .. note:: The URL should **always** be HTTP, **never** HTTPS. rlm_act_revoke() encrypts the request independent of the webserver. If you set a reference hostid with rlm_set_attr_reference_hostid() prior to activating this license, be sure to set the same reference hostid before attempting to revoke the license. Once a license is revoked with *rlm_act_rehost_revoke()*, it will no longer work on the system, and activation count associated with the fulfillment to this system will be returned to the activation server so that your customer can re-activate the license on another system. See the notes below for considerations when setting the various flags bits. *rlm_act_revoke_disconn()* is used to perform a rehostable hostid revocation on a system which is not connected to the internet. For the usage of this function, see :ref:`license-rehosting`. Note/risks when setting the *flags* bits to *rlm_act_rehost_revoke()*: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * **RLM_ACT_REVOKE_REFERENCE** – this should always be a safe option to set, unless you are worried that your customer has the same native hostid for multiple systems. In that case, the license could be revoked on a different system, and the original system would still have a valid rehostable hostid. If you already call *rlm_revoke_reference()* after *rlm_revoke()* fails, you should set this option and not worry about it. * **RLM_ACT_REVOKE_NOFULFILL** – in this case, the server did not find the fulfillment, but with this option set, the rehostable will be deleted. This prevents a new activation from receiving a “rehostable hostid exists” error and is a good option to set. * **RLM_ACT_REVOKE_NODEL** – this option tells the server to remove the fulfillment even if the rehostable cannot be deleted. This would allow a dishonest customer to cheat the system by first write-protecting the rehostable directory hierarchy, then revoking the license. With this option set, even if the hostid can't be deleted, *rlm_act_rehost_revoke()* would still tell the activation server that it was deleted, and the server would put activation count back into the key. .. note:: Reprise Software recommends always setting RLM_ACT_REVOKE_REFERENCE and RLM_ACT_REVOKE_NOFULFILL, and adding RLM_ACT_REVOKE_NODEL depending on your tolerance for some customers being able to cheat the system. Notes on the deprecated calls ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * **rlm_act_revoke()** - the pre-14.1 revoking API call, is still available, and it is 100% equivalent to calling *rlm_act_rehost_revoke(rh, url, product, 0)*. New applications should call *rlm_act_rehost_revoke()* with the appropriate flags. There is no longer any reason to call *rlm_act_revoke_reference()* after a failure of *rlm_act_revoke()*. *rlm_act_rehost_revoke(rh, url, product, RLM_ACT_REVOKE_REFERENCE)* is equivalent to *rlm_act_revoke()* followed by *rlm_act_revoke_reference()*. * **rlm_act_revoke_reference()** performs the same operation as *rlm_act_revoke()*, but it will work even when the rehostable hostid is bad or missing on the system. You must decide if you are willing to revoke the license in this case, and you should only call rlm_act_revoke_reference() after rlm_act_revoke() fails with an RLM_EH_CANT_GET_REHOST or RLM_EL_NOTTHISHOST status. .. note:: That rlm_act_rehost_revoke() and rlm_act_revoke() will return RLM_ACT_REVOKE_TOOLATE (-1029) if the license associated with the rehostable hostid has expired, and you have not enabled “Revocation of expired rehostable hostids” in the Database section of the Admin tab in RLM License Center. This error means that no count was returned to the activation key, however, the rehostable hostid was deleted in this case. If there is sufficient count in the activation key, or if a different activation key is used, a new rehostable activation will succeed. The most likely scenario where you would see this is as follows: 1. User attempts to check out license, gets RLM_EL_EXPIRED status. 2. User then attempts to re-activate the license, gets RLM_EH_REHOST_EXISTS 3. User then attempts to revoke the activation, gets RLM_ACT_REVOKE_TOOLATE At this point, the rehostable hostid is gone, and the user can re-activate successfully. Back to :ref:`appendix-a`. ------ .. _rlm-add-meter-count: rlm_add_meter_count() ===================== Add count to a specified meter. ------------------------------- .. code-block:: text #include "license.h" int status; RLM_HANDLE rh; RLM_PRODUCTS product; int counter, count; status = rlm_add_meter_count(rh, product, counter, count); *rlm_add_meter_count()* is used by an application to add *count* to a server's meter *counter*. The *rlm_add_meter_count()* call requires a connection to a license server which was created with rlm_init() (NOT rlm_init_disconn()). The license server connection is specified in one of 2 ways: * If a product is specified via the product and rh parameters, this connection is used. * If no product is specified, the connection from the supplied RLM_HANDLE is used. This connection must have been established prior to the call to rlm_add_meter_count() via an rlm_checkout() call. If no server connection is specified: * If neither a product nor an RLM_HANDLE is specified, RLM_EH_NOHANDLE is returned to the caller. * If the specified product or RLM_HANDLE does not have a server associated, RLM_EH_NOSERVER is returned to the caller. Given a server as specified above, this call will add *count* to the specified meter *counter*. Example (add 100 to counter for “your-product-name”): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: text int status, counter, count_to_add; RLM_PRODUCTS products; products = rlm_products(rh, "your-product-name", ""); if (products && rlm_product_ismetered(products)) { counter = rlm_product_meter_counter(products); count_to_add = 100; status = rlm_add_meter_count(rh, products, counter, count_to_add); } **alternately:** .. code-block:: text int status, counter, count_to_add; RLM_LICENSE lic; lic = rlm_checkout(rh, “your-product-name”, “1.0”, 1); if (!rlm_license_stat(lic) && rlm_license_ismetered(lic)) { counter = rlm_license_meter_counter(lic); count_to_add = 100; status = rlm_add_meter_count(rh, (RLM_PRODUCTS) NULL, counter, count_to_add); } Back to :ref:`appendix-a`. ------ .. _rlm-auth-check: rlm_auth_check() ================ Ask the server to verify a license. ----------------------------------- .. code-block:: text #include "license.h" int status; RLM_LICENSE license; char \*license_to_check; status = rlm_auth_check(license, license_to_check); *rlm_auth_check()* is used by an application to verify the integrity of the license server. This call is not required by RLM and is used only as an additional check that the license server has not been modified. The *rlm_auth_check()* call asks the license server to verify a signed license (license_to_check) after you have checked out some other license. You pass a node-locked uncounted license to this call as the *license_to_check* parameter. This license can be either a good or a bad license, and you should pass both types at different times to make spoofing this call harder. .. warning:: Do not include HOST or ISV lines in this license, only the LICENSE line. Also note that these licenses must be node-locked, uncounted (or SINGLE) licenses, and do not enclose the license in angle brackets - “<” and “>”. You must pass a valid RLM_LICENSE handle in, and this handle should represent a checked-out license from a license server. *license_to_check* is a signed license, either valid or not. This function will return either: * 0 - the server authenticated the license, and it is correct. * RLM_EL_SYNTAX (-26) – the license to be checked has a syntax error, or the received message is incorrect. * RLM_EL_BADKEY (-5) - the license did not authenticate in the server. * RLM_EH_NOSERVER (-112) - the RLM_LICENSE handle passed in does not have a license checked-out on a license server. See the Securing Your Application FAQ for more information on how to secure your application and license server. Back to :ref:`appendix-a`. ------ .. _rlm-auto-hb: rlm_auto_hb(), rlm_set_auto_hb_isvdata() ======================================== Enable Automatic Heartbeats. ---------------------------- .. code-block:: #include "license.h" RLM_HANDLE rh; int period; int auto_reconnect; void (*notify(RLM_HANDLE, RLM_LICENSE, int, void *)); const void *isv_data; status = rlm_auto_hb(rh, period, auto_reconnect, notify); rlm_set_auth_hb_isvdata(rh, isv_data); With RLM, you must either manually send heartbeats to the license server by calling *rlm_get_attr_health()* periodically in your code, or tell RLM to do this for you. *rlm_auto_hb()* is the function that sets up automatic heartbeats. You should call either *rlm_get_attr_health()* or *rlm_auto_hb()*, but not both. Also note that while this is not strictly a requirement, you need to send heartbeats to the server if you want to detect license loss. On the other hand, if your application runs for less than a minute or so, there is no real need to send heartbeats to the license server and you can safely ignore heartbeats. You can call *rlm_auto_hb()* any time after calling *rlm_init()*. If *rlm_auto_hb()* returns a 0 status, the handler was installed without error, otherwise, status contains the RLM error code. The first parameter is the handle on which to perform automatic heartbeats. RLM will perform heartbeats on all checked-out licenses on this handle. You can call *rlm_auto_hb()* any time after the *rlm_init()* and before the *rlm_close()* call. In practice, you should call *rlm_auto_hb()* within 30 seconds or so of your first license checkout, but it can be called before any checkouts if you wish. The second parameter, *period*, is the period at which the heartbeat thread runs. *period* must be at least 2 seconds (and is set to 2 if specified as a lower value). RLM will not send heartbeats any more often than once every 30 seconds even if you set *period* to a value less than 30, however, when the license is lost, rlm_auto_hb() will attempt to re-acquire it every *period* seconds. Also note that there is an interaction between the *period* you pick and the minimum heartbeat interval. For example, if you set *period* to 25 seconds, the heartbeat will not be sent the first time requested (since it is less than 30 seconds), but it will be sent the 2\ :sup:`nd` time – in other words, after 50 seconds. So setting *period* to a value <30 seconds may cause the heartbeat interval to be longer than 30 seconds. .. note:: The *period* parameter is set to a minimum of 2 seconds internally. The third parameter, *auto_reconnect*, is set to 0 if you do not want RLM to attempt to re-acquire lost licenses. If you would like RLM to re-acquire licenses that have been lost, set *auto_reconnect* to one. If RLM does an automatic re-acquisition of the license, your original RLM_LICENSE handle will reflect the new status of the license. .. note:: If you have modified the ISV data via a call to rlm_set_environ() between the time you made your original checkout and the time of the reconnection, the ISV data sent on the new checkout request will be the new version of the ISV data, NOT the ISV data that was transmitted originally. The fourth parameter is a function pointer which is called when a license is lost, **after** re-acquisition is attempted. If you supply a NULL pointer in this argument, no callback is done to your code. This function is called independent of the setting of *auto_reconnect*. The *notify* handler will be called as long as the license is lost, and, if you have a reconnection handler set, one time when license re-acquisition is successful (i.e., when status==0). Note that the last call will not happen if you do not have a reconnection handler installed. The function is called as follows: .. code-block:: text (*notify)(rh, license, lic_status, isv_data); The *license* parameter is the license which was lost. Note that the status may be 0 when this routine is called if you have set *auto_reconnect* to one and the license has already been re-acquired. This function is called in the context of the thread in which heartbeats are performed. The only RLM functions you can call in this routine are all the *rlm_license_xxxx()* functions **with the exception of rlm_license_stat()**. The third parameter, *lic_status*, is the status of the license (updated after the reconnection attempt). The fourth parameter is a void * that you specified in the latest call to *rlm_set_auto_hb_isvdata()* on this handle, or NULL if rlm_set_auto_hb_isvdata() was not called on this handle. This argument can be used to pass any data from the application to the reconnection handle. *rlm_set_auth_hb_isvdata()* specifies the data item to be passed to the automatic heartbeat reconnection function, above. If you call *rlm_auto_hb()*, heartbeats will be sent to the server whenever your application is running, whether you are actively processing or not. This means that an application which is simply waiting for user input will continue to send heartbeats and will not appear to be inactive to RLM. If you would like your customers to be able to time-out the licenses from applications which are in such an idle state, use the rlm_set_active() call to inform RLM when your application is active or inactive. .. note:: rlm_auto_hb() uses pthreads on Unix, and Windows threads on Windows. If you call *rlm_auto_hb()* on Unix, you must include -lpthreads in your link command for your application. In addition to this, on Solaris, you must include -lrt in your link command. On Unix systems, *rlm_auto_hb()* sets the handler for SIGPIPE to SIG_IGN in both the main thread and in the thread that generates the heartbeat. .. note:: If a license expires, the license server does not invalidate or remove any instances of that license which are checked out at the time of license expiration. Heartbeats on such a license will continue to succeed. Some additional notes on heartbeats and server status checking ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *rlm_get_attr_health()* will re-attempt to verify the connection to the server each time it is called. This means a few things: * The client will be able to “re-acquire” a license that is lost due to a temporary network interruption. During the time of the interruption, *rlm_get_attr_health()* will return RLM_EL_NO_HEARTBEAT. If you are using *rlm_auto_hb()*, this is attempted 5 times, then the connection is deemed bad and it is shut down. If you are doing manual heartbeats, you control how many times you look for a heartbeat before giving up (although Reprise Software recommends that you keep this number relatively low, say 4-6 attempts). * In *rlm_auto_hb()*, your application will not attempt to re-acquire a lost license until it has tried to verify a heartbeat 5 times. Previously, it attempted a reconnection on the initial detection of the lost heartbeat. * In any case, if the network was interrupted and then restored, it may take more calls to *rlm_get_attr_health()* to detect a loss of heartbeat in a subsequent interruption. This is because several heartbeat responses may have been queued up for the application to read. Back to :ref:`appendix-a`. ------ .. _rlm-checkin: rlm_checkin() ============= Release a license. ------------------ .. code-block:: text #include "license.h" RLM_LICENSE license; rlm_checkin(license); *rlm_checkin()* releases license and frees all data associated with it. After calling *rlm_checkin()*, the RLM_LICENSE *license* is no longer valid, and you should make no further calls using this handle. Do not call *rlm_checkin()* more than once on a license. .. note:: You cannot call *rlm_license_stat()* on a license handle after that handle has been checked in, or if the RLM_HANDLE used to check it out has been closed. In fact, you cannot use this handle in any way. Use of the handle after an *rlm_checkin()* or *rlm_close()* will result in unpredictable behavior (including possible application crashes), since the handle you are using has been freed by RLM. .. note:: If you plan to check any licenses in then close the handle (ie, if you are not going to use the handle after checking a license in), then you should omit the *rlm_checkin()* call, and simply call *rlm_close()* on the handle. *rlm_close()* always checks-in any licenses which are checked out on the handle, and if you are using a disconnected handle, RLM will only reconnect to the server one time for all your license check-ins as well as to tell the server that you’re are done with the handle. Back to :ref:`appendix-a`. ------ .. _rlm-checkout: rlm_checkout() ============== Request a license from RLM. --------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; RLM_LICENSE license; const char \*product; const char \*version; int count; license = rlm_checkout(handle, product, version, count); *rlm_checkout* requests *count* licenses of product *product* at version *version*. *count* must be a positive integer. If there are node-locked, uncounted licenses available in a license file that is specified in The License Environment, then these node-locked licenses are used. Otherwise, a request is made to each server specified by The License Environment, until either the licenses are granted, or all servers have been tried without success. *rlm_checkout()* creates *license* and returns it to its caller. The *version* string should be of the form *major* or *major.minor* where *major* and *minor* are integers. The *count* parameter must be a positive integer. The order of license checkout attempts is as follows: * If RLM_ROAM is set to a positive value, roamed licenses on the local node will be checked first. * All node-locked, uncounted licenses in local license files (from all license files in the license file path) will be checked next. * All licenses served by servers that RLM has already connected to are checked next. * All licenses served by servers which RLM has not previously connected to are checked next. * Finally, if RLM_ROAM is not set, a check will be made for local roamed licenses. .. note:: If RLM_ROAM is set, the setting of RLM_QUEUE is ignored, ie, you cannot queue for the license. To get the status of the rlm_checkout call, use rlm_license_stat(license). For a list of status returns, see :ref:`appendix-b`. There are generally 3 "success" status returns from a license checkout request: .. list-table:: * - 0 - License checked out normally. * - RLM_EL_OVERSOFT - License checkout results in usage over the soft_limit specified, or a token-based license is misconfigured and the server is in an overdraft condition (see note in :ref:`token-based-restrictions`). * - RLM_EL_INQUEUE - License request is in the queue. If you have specified a minimum server version/revision/build via the rlm_isv_cfg_set_oldest_server() call in rlm_isv_config.c, and the server is older than your specification, you will get an RLM_EL_COMM_ERROR error from the server and the handle will have the error status RLM_EH_SERVER_REJECT. .. note:: You should always call *rlm_checkin()* when you are done with the license, even if the checkout call returns an error. Calling *rlm_checkin()* on the license frees any associated memory with the license. You can call *rlm_checkin()* even if *rlm_checkout()* returns a NULL license handle, however, you should only call *rlm_checkin()* on a non-NULL license handle once. Back to :ref:`appendix-a`. ------ .. _rlm-checkout-product: rlm_checkout_product() ====================== Request an exact license from RLM. ---------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; RLM_LICENSE license; RLM_PRODUCTS product; const char \*version; int count; license = rlm_checkout_product(handle, product, version, count); In most cases, applications use *rlm_checkout()* to check out licenses, as any license that meets the product name and version requirements is sufficient. In some other cases, an application may want to choose from multiple instances of licenses for the same product. For example, if there are several licenses present for a product, but they contain different options attributes, the application may want to check out a specific instance based on the options content determined with *rlm_products()*. In that case the application would use *rlm_checkout_product()* to check out the license. *rlm_checkout_product()* requests count licenses of version version of the product specified by the RLM_PRODUCTS handle *product*. *count* must be a positive integer. *rlm_checkout_product()* creates *license* and returns it to its caller. The *version* string should be of the form *major* or *major.minor* where *major* and *minor* are integers. The *count* parameter must be a positive integer. *rlm_checkout_product()* operates on the RLM_PRODUCTS handle returned from *rlm_products()*. Once you have found the product you want to check out via the *rlm_product_first()* and *rlm_product_next()* calls, a call to *rlm_checkout_product()* will check out the product that is described by the current state of the RLM_PRODUCTS handle *product*. To get the status of the *rlm_checkout_product()* call, use *rlm_license_stat(license)*. For a list of status returns, see :ref:`appendix-b`. There are generally 3 "success" status returns from a license checkout request: .. list-table:: * - 0 - License checked out normally. * - RLM_EL_OVERSOFT - License checkout results in usage over the soft_limit specified, or a token-based license is misconfigured and the server is in an overdraft condition (see note in :ref:`token-based-restrictions`). * - RLM_EL_INQUEUE - License request is in the queue. If you have specified a minimum server version/revision/build via the rlm_isv_cfg_set_oldest_server() call in rlm_isv_config.c, and the server is older than your specification, you will get an RLM_EL_COMM_ERROR error from the server and the handle will have the error status RLM_EH_SERVER_REJECT. .. note:: You should always call *rlm_checkin()* when you are done with the license, even if the checkout call returns an error. Calling *rlm_checkin()* on the license frees any associated memory with the license. You can call *rlm_checkin()* even if *rlm_checkout()* returns a NULL license handle, however, you should only call *rlm_checkin()* on a non-NULL license handle once. Back to :ref:`appendix-a`. ------ .. _rlm-close: rlm_close() =========== Terminate licensing operations with RLM. ---------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; rlm_close(handle); When you are finished with all licenses and do not intend to make any more calls to RLM, call *rlm_close()* to clean up the handle created with rlm_init() and free all the data associated with it. *rlm_close()* does the following: * If you have automatic heartbeats - syncs with the other thread and destroys that thread. * Checks in any licenses that are still checked out - which will disconnect from all servers and shut down the connections (and on windows, calls WSACleanup() to close down Winsock). * Frees all data structures used in that handle. * Frees the handle. .. note:: If you are using a DLL on Windows, you **cannot** call *rlm_close()* in the DLL unloading routine. .. note:: You cannot use any license handles that were created using this RLM_HANDLE after the call to *rlm_close()*. Use of the RLM_HANDLE or any associated license handles after an *rlm_close()* will result in unpredictable behavior (including possible application crashes), since the handle you are using has been freed by RLM. .. note:: If you plan to check any licenses in then close the handle (i.e., if you are not going to use the handle after checking a license in), then you should omit the *rlm_checkin()* call, and simply call *rlm_close()* on the handle. *rlm_close()* always checks-in any licenses which are checked out on the handle, and if you are using a disconnected handle, RLM will only reconnect to the server one time for all your license checkins as well as to tell the server that you’re are done with the handle. You are not strictly required to call *rlm_close() unless the handle is a disconnected handle*. Specifically, if your program is about to exit, *rlm_close()* is unnecessary for a connected handle, but for a disconnected handle, *rlm_close()* informs the server that you are done and allows the server to clean up data associated with your process. Of course, you can omit the rlm_close() call even for a disconnected handle, in which case the server will time out the licenses after your *promise* interval. If you do not call *rlm_close()*, memory leak detectors will report leaked memory. .. important:: Prior to v16.1 it was necessary to call rlmssl_ERR_remove_state(0); before exiting your program to avoid memory leaks caused by OpenSSL. Starting in 16.1 this is no longer necessary and the call was removed, so you must remove this call from your program. Back to :ref:`appendix-a`. ------ .. _rlm-temp-xxx: rlm_create_temp_license(), rlm_return_temp_license(), rlm_temp_new_handle(), rlm_temp_destroy_handle(), rlm_temp_set_handle() ============================================================================================================================= Temporary license functions --------------------------- .. code-block:: #include "license.h" RLM_HANDLE rh; RLM_TEMP_HANDLE temp_handle; const void *val; int status, what; (void) rlm_temp_destroy_handle(temp_handle); temp_handle = rlm_temp_new_handle(rh); status = rlm_temp_set_handle(temp_handle, what, val); status = rlm_create_temp_license(rh, temp_handle); status = rlm_return_temp_license(rlm_license); *rlm_create_temp_license()* will create a new temporary license specified by the information in *temp_handle*. *rlm_return_temp_license()* removes the temporary license and returns it to the source. *rlm_temp_new_handle()* creates a new temporary license handle, *rlm_temp_set_handle()* sets the parameters in the handle, and *rlm_temp_destroy_handle()* removes the handle. *rlm_temp_new_handle()* creates a blank handle to pass temporary license parameters to *rlm_create_temp_license()*. *rlm_temp_new_handle()* returns a NULL handle error. Call *rlm_temp_new_handle()* before calling *rlm_temp_set_handle()*. After the temporary license has been created, call *rlm_temp_destroy_handle()* to free the memory associated with the handle. To create a temporary license, first create a handle using *rlm_temp_new_handle()*. *rlm_temp_new_handle()* sets the following defaults: * RLM_TEMP_SOURCE is set to RLM_TEMP_RLMCLOUD * RLM_TEMP_TYPE is set to RLM_TEMP_UNCOUNTED Next, set the parameters using *rlm_temp_set_handle()* as follows: .. list-table:: * - RLM_TEMP_HANDLE_DURATION (int) - # of minutes until license expires. * - RLM_TEMP_HANDLE_NEW_DURATION (int) - New duration at refresh (see below) * - RLM_TEMP_HANDLE_SOURCE (integer) - The license comes from the source specified, which is either RLM_TEMP_RLMCLOUD or RLM_TEMP_ACTPRO. Currently only RLM_TEMP_RLMCLOUD is supported; this is the default. * - RLM_TEMP_HANDLE_LICENSE (RLM_LICENSE) - A checked-out license. Used for RLM_TEMP_RLMCLOUD only. The RLM_LICENSE must come from an RLM Cloud server, not a local server. * - RLM_TEMP_HANDLE_TYPE (int) - Either RLM_TEMP_UNCOUNTED or RLM_TEMP_HANDLE_SINGLE to create an uncounted or single license, respectively. RLM_TEMP_HANDLE_UNCOUNTED is the default. * - RLM_TEMP_WINDOW (int) - Refresh window, in seconds, if ==0, no automatic refresh (see below). * - RLM_TEMP_AKEY (const char \*) - Activation key for activation pro. Unused. * - RLM_TEMP_COUNT - # of licenses requested. Unused. * - RLM_TEMP_URL (const char \*) - URL of the ActPro server. Unused. Once the license is created, on each subsequent checkout, if the license expires within *window*, minutes, then the license will be renewed for *new_duration* minutes (RLM will do this using this same call, with *new_duration* substituted for *duration*). When RLM performs this automatic renewal, it uses the same call, and if the renewal fails, it returns the original license. If the renewal succeeds, the new license is returned. .. note:: The new expiration is computed from the time of the renewal, NOT from the time of the initial expiration. Also note that if *window* is specified as 0, no automatic renewal will be done. For example, the following code will create an uncounted license for “prod” which lasts for 3 days, and which auto-renews when you check out the license 12 hours before the end time for an additional 2 days: .. code-block:: text #define HOURS 60 #define DAYS (24 * HOURS) RLM_LICENSE lic; RLM_HANDLE rh; rh = rlm_init(....); lic = rlm_checkout(rh, …..); if (!rlm_license_single(lic) && !rlm_license_uncounted(lic)) { temp_handle = rlm_temp_new_handle(rh); if (!temp_handle) /* whatever error code you want */ rlm_temp_set_handle(temp_handle, RLM_TEMP_DURATION, (void *) 3*DAYS); rlm_temp_set_handle(temp_handle, RLM_TEMP_WINDOW, (void *) 12*HOURS); rlm_temp_set_handle(temp_handle, RLM_TEMP_NEW_DURATION, (void *) 2*DAYS); rlm_temp_set_handle(temp_handle, RLM_TEMP_LICENSE, (void *) lic); status = rlm_create_temp_license(rh, temp_handle); } If *rlm_create_temp_license()* returns 0 status, the license was written and is ready for checkout. Otherwise status contains the RLM error status. *rlm_return_temp_license()* can only be called on a license that is checked out. To return this license, call *rlm_return_temp_license()* with the RLM_LICENSE handle returned by *rlm_checkout()*. If *rlm_return_temp_license()* returns good status (0), the license is checked in, and the handle should not be used again. For example, to return the license created above: .. code-block:: text lic = rlm_checkout(rh, “prod”, “1.0”, 1); if (lic) { status = rlm_return_temp_license(lic); if (status) rlm_checkin(lic); } .. note:: If *rlm_create_temp_license()* returns RLM_EH_NOTEMPFROMLOCAL status, this means there was already a temporary license present on the system. In this case, the temporary license might have been refreshed as part of the operation. Back to :ref:`appendix-a`. ------ .. _rlm-detached-demo: rlm_detached_demo() =================== Install RLM Detached Demo\ :sup:`TM` license. --------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; int stat; int days; const char license[RLM_MAX_LINE+1]; rh = rlm_init(...); stat = rlm_detached_demo(rh, days, license); *rlm_detached_demo()* requests RLM to install a Detached Demo\ :sup:`TM` valid for *days*. The parameters of the demo license installed are contained in the *license* string. *days* - the number of days the demo license should be valid. *license* - an RLM license string. When installing the demo license, the *license* string is parsed into its components, and these are used for the license. The license should not be signed, but must have valid syntax, otherwise an RLM_EL_BADPARAM error will result. If *rlm_detached_demo()* returns a non-zero status, the status is contained in the RLM_HANDLE parameter (rh) after the call. The *count*, *hostid*, and *expiration date* fields of this input *license* are unused. The resulting installed demo license will be a node-locked, uncounted license, valid on the machine which made the call to *rlm_detached_demo()*, **and valid for the version specified in the license** **only**. The expiration date will be days days in the future. Note that licenses are valid until midnight, local time, so a 0-day license will be valid until midnight on the day it is installed. A Detached Demo\ :sup:`TM` license can only be installed once on a particular system for any given combination of *product* and *version*. Detached Demo\ :sup:`TM` licenses cannot be modified or re-installed. They do not require any kind of internet connectivity; however, they are not as secure as licenses created with RLM Activation Pro, which is always the preferred way to install a license which expires in a fixed number of days. For a Detached Demo\ :sup:`TM` license to be usable, you must be able to check out an rlm_demo license. This allows you to add the code to create demo licenses into your product but enable it only in certain situations. If you call *rlm_detached_demo()* without an rlm_demo license available, the operation will fail with an RLM_EH_NO_DEMO_LIC status. Note that the rlm_demo license must be valid, in other words, you must sign this license and it must be present **and valid** on the system where the demo is going to be installed. The rlm_demo license should be placed in the directory with your product binary, and it should be a nodelocked, uncounted license, perhaps locked to hostid *demo* or *any*, e.g.: .. code-block:: text LICENSE demo rlm_demo 1.0 permanent uncounted hostid=demo The following example is a call to *rlm_detached_demo()* to set up a 30-day license for v1.0 of *myproduct*: .. code-block:: text RLM_HANDLE rh; int stat; char license[RLM_MAX_LINE+1]; rh = rlm_init(...); sprintf(license, "LICENSE demo mylicense 1.0 permanent uncounted hostid=any _customer=%s", customer); stat = rlm_detached_demo(rh, 30, license); To determine if a license which is checked out is a Detached Demo\ :sup:`TM` license, call *rlm_license_detached_demo()* on the license handle. If it is a Detached Demo\ :sup:`TM` license, *rlm_license_detached_demo()* will return 1. .. note:: Detached Demo\ :sup:`TM` licenses are not as secure as licenses created with RLM Activation Pro. Using internet activation to install demo licenses is always preferred, and Detached Demo\ :sup:`TM` licenses should only be used when absolutely required. Also note that Detached Demo\ :sup:`TM` licenses are not reported by the *rlm_products()* call. Back to :ref:`appendix-a`. ------ .. _rlm-detached-demox: rlm_detached_demox() ==================== Remove RLM Detached Demo\ :sup:`TM` license. -------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; int stat; const char product[RLM_MAX_PRODUCT+1]; const char version[RLM_MAX_VER+1]; rh = rlm_init(...); stat = rlm_detached_demox(rh, product, version); *rlm_detached_demox()* requests RLM to remove an installed Detached Demo\ :sup:`TM` license. The license is specified by the product name and version. *product* - the name of the product license to be removed. *version* – the version of product to be removed. Since a Detached Demo\ :sup:`TM` license can only be installed once on a particular system for any given combination of *product* and *version*, *rlm_detached_demox()* gives you a way to test this functionality during development. .. note:: Reprise Software STRONGLY recommends that you use this function only during development, and that you do not ship products that include rlm_detached_demox() calls to your customer. **rlm_detached_demox() will only remove a Detached Demo**\ :sup:`TM` **license created by the same** **version of RLM.** Back to :ref:`appendix-a`. ------ .. _rlm-diagnostics: rlm_diagnostics() ================= Print client-side diagnostics ----------------------------- .. code-block:: text RLM HANDLE rh; char \*filename; (void) rlm_diagnostics(rh, filename); *rlm_diagnostics()* will print client-side diagnostics to the filename specified. *rlm_diagnostics()* can be called any time after a call to *rlm_init()* or *rlm_init_disconn()*. The values for the 3 *rlm_init()* parameters will be the values used in the most recent call to *rlm_init()*. Back to :ref:`appendix-a`. ------ .. _rlm-errstring: rlm_errstring() =============== Format RLM status into a string ------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; RLM_LICENSE lic; char string[RLM_ERRSTRING_MAX]; int stat; (char \*) rlm_errstring(lic, handle, string); *rlm_errstring()* will take the latest status returns from any call-in *handle* and from the latest rlm_checkout() call in *lic*, and format the resulting status into *string*. It is the caller's responsibility to manage the memory used by *string*. *string* should be at least RLM_ERRSTRING_MAX bytes in length. You can pass either a NULL *lic* or a NULL *handle* to *rlm_errstring()*, and only the status from the other will be returned. .. note:: Prior to RLM v9.1, rlm_act_errstring() was used to return a printable string corresponding to the error returned by rlm_activate()/rlm_act_request(). Beginning in RLM v9.1, rlm_errstring() prints all RLM errors, including activation errors. Thus, rlm_act_errstring() is no longer required and should not be used. *rlm_errstring()* returns its 3rd argument, so that it can be placed directly in an output (e.g., printf()) call. If RLM_EXTENDED_ERROR_MESSAGES is set in the user's environment, rlm_errstring() will output additional information (for certain errors) with suggestions for solving the problem. The returned string consists of multiple lines of information, in the following format. If any of these errors are not present, the corresponding line will not appear in the output (e.g., if there is no RLM_HANDLE error, the 2nd line will not appear): .. code-block:: text license (RLM_LICENSE) error string (error number) handle (RLM_HANDLE) error string (error number) communications error (comm: error number) system error string (errno: error number) Optional extended error messages For example, if a connection attempt is made to an ISV server that is not running, the following error string might be returned. Note that this example does not contain an RLM_LICENSE error line: .. code-block:: text Networking error (in msg_init()) (-103) Cannot connect to server (comm: -4) Transport endpoint is not connected (errno: 146) If RLM_EXTENDED_ERROR_MESSAGES is set, the following lines would be added to this message: .. code-block:: text This error usually means that: (1) The license server (rlm) is not running, or (2) The hostname or port # in a port@host or license file is incorrect, or (3) The ISV server isn't running, or (4) The license server machine is down. .. note:: For certain activation errors (rlm_act_request() or rlm_activate()) additional status will be contained in the returned license string. See rlm_activate() for more information. Back to :ref:`appendix-a`. ------ .. _rlm-errstring-num: rlm_errstring_num() =================== Translate RLM status value into a string. ----------------------------------------- .. code-block:: text int error; char string[RLM_ERRSTRING_MAX]; (char \*) rlm_errstring_num(error, string); *rlm_errstring_num()* will take any RLM status return and turn it into an error string. The *error* parameter can be the return from any RLM call which returns status (primarily rlm_stat() and rlm_license_stat()) It is the caller's responsibility to manage the memory used by *string*. *string* should be at least RLM_ERRSTRING_MAX bytes in length. *rlm_errstring()* returns its 3rd argument, so that it can be placed directly in an output (e.g., printf()) call. RLM_EXTENDED_ERROR_MESSAGES has no effect on the *rlm_errstring_num()* call. The returned string consists of a single line of error information. Example: ^^^^^^^^ .. code-block:: text char string[RLM_ERRSTRING_MAX]; rlm_errstring_max(-24 /* RLM_EL_TIMEDOUT */, string) printf(“RLM Error is: %s\n”, string); The output will be: .. code-block:: text RLM Error is: License timed out by server Back to :ref:`appendix-a`. ------ .. _rlm-get-attr-health: rlm_get_attr_health() ===================== Check license status by testing server connection. -------------------------------------------------- .. code-block:: text #include "license.h" RLM_LICENSE license; int status; status = rlm_get_attr_health(license); Once you have checked out a license, you need to periodically check the health of the connection to the license server by calling *rlm_get_attr_health()* on a license-by-license basis. You can make this call as often as you like; RLM ensures that communications with the license server is done at most once every 30 seconds. This communication is called a *heartbeat*. In general, it is sufficient to call *rlm_get_attr_health()* every couple of minutes. If your product runs for less than a few minutes, you can skip this call entirely. The main function of *rlm_get_attr_health()* is to protect against a malicious user killing and restarting the license server in order to make all licenses available again. If this is not a concern, you can simply never call *rlm_get_attr_health()* in your application. Status of 0 indicates that everything is OK, non-zero status returns are defined in license.h If, after successfully checking out a license, *rlm_get_attr_health()* returns a non-zero status, you should call *rlm_checkin()* on the license to free any associated memory, and then check out the license again. If you receive a return of RLM_EL_INQUEUE from your checkout call, you would call *rlm_get_attr_health()* until you receive a 0 status, at which point the license is checked out. In this case, if *rlm_get_attr_health()* returns anything other than 0 or RLM_EL_INQUEUE, this is an error and you should call *rlm_checkin()* on that license. If you would like RLM to provide this checking automatically (in a separate thread), see :ref:`rlm-auto-hb` for a description of the rlm_auto_hb() function. Note that you should call **either** *rlm_get_attr_health()* or *rlm_auto_hb()*, but not both. Some notes on heartbeats and server status checking ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *rlm_get_attr_health()* will re-attempt to verify the connection to the server each time it is called. This means a few things: * The client will be able to “re-acquire” a license that is lost due to a temporary network interruption. During the time of the interruption, *rlm_get_attr_health()* will return RLM_EL_NO_HEARTBEAT. If you are using *rlm_auto_hb()*, this is attempted 5 times, then the connection is deemed bad, and it is shut down. If you are doing manual heartbeats, you control how many times you look for a heartbeat before giving up (although Reprise Software recommends that you keep this number relatively low, say 4-6 attempts). * In *rlm_auto_hb()*, your application will not attempt to re-acquire a lost license until it has tried to verify a heartbeat 5 times. Previously, it attempted a reconnection on the initial detection of the lost heartbeat. * In any case, if the network was interrupted and then restored, it may take more calls to *rlm_get_attr_health()* to detect a loss of heartbeat in a subsequent interruption. This is because several heartbeat responses may have been queued up for the application to read. Back to :ref:`appendix-a`. ------ .. _rlm-get-attr-lfpath: rlm_get_attr_lfpath() ===================== Get license path in use by RLM. ------------------------------- .. code-block:: text #include "license.h" RLM_LICENSE license; char \*path; path = rlm_get_attr_lfpath(license); Once you have attempted a license checkout, you can determine the license path in use by RLM by calling *rlm_get_attr_lfpath()* on the license handle (the checkout does not need to be successful for *rlm_get_attr_lfpath()* to work). This call will retrieve the same path for any license handle passed in. You should **NOT** free the returned string. .. note:: On Windows, the path components are separated by the ';' character. On all other RLM platforms, the path components are separated by the ':' character. Back to :ref:`appendix-a`. ------ .. _rlm-get-attr-lic-check: rlm_get_attr_lic_check() ======================== Get license check information ----------------------------- .. code-block:: text #include "license.h" RLM_LICENSE lic; char \*license; char \*hostid; int status; status = rlm_get_attr_lic_check(lic, &license, &hostid); If you have enabled server license checking with *rlm_isv_cfg_enable_check_license()* AND you have disabled failures from this license check with *rlm_isv_cfg_no_server_license_fail()*, you can check the status of the returned license from the server with this call after you have attempted a checkout. This data will be valid after the checkout and before any other call that attempts to connect to the server. The call will return pointers to the license and server hostid returned by the license server in the *license* and *hostid* parameters, if they are supplied as non-NULL pointers. You should **NOT** free or otherwise modify either the license or hostid strings returned from this call. The return from the call will be one of the following values: .. list-table:: * - 0 - License from server verified correctly. * - RLM_EH_BADPARAM - Either lic is NULL or the RLM_HANDLE associated with *lic* is NULL. * - RLM_NO_SERVER_LIC - The server did not return a license. * - RLM_LIC_BAD - The returned license did not verify correctly. * - RLM_EH_LIC_WITH_NEW_KEYWORDS - The returned license has unknown keywords. Back to :ref:`appendix-a`. ------ .. _rlm-get-rehost: rlm_get_rehost() ================ Retrieve the hostid of a rehostable license. -------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; char \*product; char \*hostid[RLM_MAX_HOSTID_STRING+1]; int status; status = rlm_get_rehost(handle, product, hostid); **rlm_get_rehost()** will return the hostid for the specified *product* if there is a rehostable hostid on this system. If status==0, *hostid* will contain the hostid string for this *product*. This call can be used to retrieve a rehostable hostid when the license file is lost, and then transmit this hostid to the activation server to retrieve the hostid. .. note:: Prior to RLM v12.4, rlm_get_rehost() changed the working directory during the time of the call. This caused problems with multi-threaded applications, specifically plugins to Adobe products. In RLM v12.4, the working directory is not changed during this call. There are no changes to the API or the file layout of rehostable hostids, so no changes to your product are needed. Back to :ref:`appendix-a`. ------ .. _rlm-hostid: rlm_hostid(), rlm_all_hostids(), rlm_all_hostids_free() ======================================================= Retrieve the hostid of this machine. ------------------------------------ rlm_hostid() ------------ .. code-block:: text #include "license.h" RLM_HANDLE handle; int type; char hostid[RLM_MAX_HOSTID_STRING]; const char \*description; description = rlm_hostid(handle, type, hostid); Call rlm_hostid() on any open RLM_HANDLE to retrieve the hostid of type *type*. The hostid will be returned in the string *hostid*. The value of the hostid can be the string “invalid” in certain circumstances. The value of *type* should be one of: * RLM_HOSTID_32BIT * RLM_HOSTID_DISKSN (Windows only) * RLM_HOSTID_ETHER * RLM_HOSTID_UUID (Windows only) * RLM_HOSTID_USER * RLM_HOSTID_HOST * RLM_HOSTID_IP * RLM_HOSTID_RLMID1 * One of your ISV-defined hostid types. .. note:: *type* could also be one of RLM_HOSTID_ANY, RLM_HOSTID_DEMO, or RLM_HOSTID_STRING, but these will always return "ANY", "DEMO", or "". The description return value will be NULL for an error, otherwise it is a static string - do not free it. Currently it is always an empty string, but may be used in the future. .. note:: You cannot retrieve a rehostable hostid with *rlm_hostid()* or *rlm_all_hostids()*. Call *rlm_get_rehost()* to retrieve a rehostable hostid for a product. rlm_all_hostids() ----------------- The *rlm_all_hostids()* call returns a list of hostids for hostid types which allow for multiple instances on a given machine. .. code-block:: text RLM_HANDLE handle; int type; char \**list; list = rlm_all_hostids(handle, type); *rlm_all_hostids()* returns a pointer to an array of (char \*) pointers. Each pointer points to a string which is one instance of the specified hostid type. The list is terminated with a NULL pointer. rlm_all_hostids_free() ---------------------- Free all memory allocated for the list with the rlm_all_hostids_free() call. .. code-block:: text char \**list; (void) rlm_all_hostids_free(list); Example: ^^^^^^^^ .. code-block:: text char \**list, **list_save; list_save = list = rlm_all_hostids(handle, RLM_HOSTID_ETHER); while (list && *list) { printf("Hostid: %s\n", *list); list++; } rlm_all_hostids_free(list_save); Back to :ref:`appendix-a`. ------ .. _rlm-init: rlm_init(), rlm_init_disconn() ============================== Initialize licensing operations with RLM. ----------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; const char \*license; const char \*argv0; const char \*license_strings; int promise; handle = rlm_init(license, argv0, license_strings); handle = rlm_init_disconn(license, argv0, license_strings, promise); Before any RLM operations can be done, you must call either *rlm_init* or *rlm_init_disconn* to obtain an RLM_HANDLE. This handle is then passed to the *rlm_checkout()*, *rlm_stat()*, *rlm_errstring()*, and *rlm_close()* calls. If you plan to call *rlm_init_disconn()*, please read the section on :ref:`disconnected-operation` first. **The first parameter** is the license file (or directory) you would like to use. If you allow the license administrator to specify the license file, put the path to this license file here. If you do not allow specification of the license file, Reprise Software recommends searching the current directory - you do this by passing a string with a single dot (".") as the first parameter. This first parameter can be a list. List elements are separated by a semicolon on Windows and a colon on all other platforms. This parameter can also be a port\@host specification. This string must have a length <= RLM_MAX_PATH bytes (1024 on Unix, 2048 on Windows), otherwise an RLM_EH_BADPARAM error will be returned by rlm_init(). **If this string is dynamically allocated, it must remain** **valid for the lifetime of the RLM_HANDLE created by the rlm_init() call.** For example: .. code-block:: text 5053@myhost .. admonition:: RLM Cloud This can also be done for RLM Cloud access. In this case, set RLM_LICENSE to “port@host@customer-name\@password” (customer name MUST be all lowercase, even if it is mixed case on the RLM Cloud server). .. code-block:: text 5053@ls1.rlmcloud.com@demo1@abc123 For more information see :ref:`customer-license-file` in the RLM Cloud manual. **The second parameter** should be your argv[0] invocation argument. This will cause RLM to look in the directory where your binary resides to find license files. If you do not have access to argv[0], pass a NULL or empty string as the second parameter. Using anything other than an empty/NULL string or argv[0] will result in unpredictable behavior. This string must have a length <=RLM_MAX_PATH bytes (1024 on Unix, 2048 on windows), otherwise an RLM_EH_BADPARAM error will be returned by *rlm_init()*. **The third parameter** is used to pass licenses into RLM directly. This can be one license, or a list of licenses separated by the path separator (':' on Unix, ';' on Windows). Each license must be enclosed within angle brackets ('<' and '>'). This would be used, for example, when you are licensing a library and you want to give your customer a license to use the library, yet you do not want to require that they use a separate license file. In this case, they would compile the license into the code and you would pass it into rlm_init() in this parameter. **Do not include HOST or** **ISV lines in this license, only the LICENSE line. These licenses must be node-locked, uncounted** **(or SINGLE) licenses. Also, if this string is dynamically allocated, it must remain valid for** **the lifetime of the RLM_HANDLE created by the rlm_init() call.** .. note:: On Windows platforms, if the paths your application would pass to rlm_init() in the first and second parameters are Unicode wide characters (wchar_t or WCHAR), you must first convert them to UTF-8. The Win32 function WideCharToMultiByte() can be used for this conversion. For example, to pass 2 licenses into RLM using the *rlm_init()* call, pass a string similar to the following as the third parameter to rlm_init() (you must include the entire signed license within the angle brackets): .. code-block:: text : If you are calling *rlm_init_disconn()*, **the fourth parameter** is how often you promise to contact the server. Specify *promise* in minutes. If you do not contact the server every *promise* minutes (by calling *rlm_get_attr_health()*), your licenses will be automatically checked back in by the license server, and the server will forget about you; subsequent calls to rlm_get_attr_health() will return RLM_EL_REMOVED (or alternately RLM_EL_NO_HEARTBEAT, RLM_EL_SERVER_DOWN, or RLM_EH_NOCLIENT). .. note:: RLM uses environment variables for a number of user-selectable options, such as queuing (RLM_QUEUE), license roaming (RLM_ROAM), project identification (RLM_PROJECT), etc. It is possible for you as an ISV to set these environment variables within your application, but if you wish to do this, you should do it before you call *rlm_init()*, because the environment is read and initialized at the time *rlm_init()* is called. Retrieve the status of the *rlm_init()* call by calling *rlm_stat(handle)* and providing the *handle* returned by *rlm_init()*: For a list of status returns, see :ref:`appendix-b`. .. code-block:: text int status; status = rlm_stat(handle); *rlm_init()* will set up a list of licenses, port\@host specifications and license files in the RLM handle. This order will determine the order in which license checkouts will be attempted. The order will be randomized if the user has set the RLM_PATH_RANDOMIZE environment variable to any value. The default order is: * The contents of the ISV_LICENSE (if present) or RLM_LICENSE environment. * The license specifications in the first parameter (*license*) in the *rlm_init()* call. * The license files contained in the directory (*argv0*) in the second parameter in the *rlm_init()* call. * Any licenses passed as strings in the third parameter (*license_strings*) in the *rlm_init()* call. Client timeouts connecting to the license server ------------------------------------------------ There are 2 different timeouts that clients can experience when talking to license servers: CONNECT timeouts and READ/WRITE communication timeouts. By default, the CONNECT timeout is set to 10 seconds. To change this, set the environment variable RLM_CONNECT_TIMEOUT to a positive integer, e.g.: .. code-block:: text % setenv RLM_CONNECT_TIMEOUT 5 to set the connect timeout to 5 seconds. The read/write timeout is set to 5 seconds by default. To change this, set the environment variable RLM_COMM_TIMEOUT to 1000 times the timeout desired, e.g.: .. code-block:: text % setenv RLM_COMM_TIMEOUT 10000 to set the comm timeout to 10 seconds. Special note about MacOS ------------------------ The RLM temporary directory on mac changed from /var/tmp to /Library/Application Support/Reprise in RLM v14.1. The main implication for this is that rehostable hostids should be revoked before upgrading to v14.1 and re-activated after. See :ref:`appendix-j` for more information. One additional implication is that while this directory was writable in older macOS versions, it is no longer writable (at least on Catalina, and possibly on some earlier versions). So you will need to add a step to your installation procedures on macOS, to create /Library/Application Support/Reprise and set it to mode 777. If you do not do this, and the directory doesn't exist or is unwritable, you will get the new RLM_EH_NOTEMPDIR error from rlm_init(), and when RLM is started, it will log this message and exit: .. code-block:: text % rlm The RLM temporary directory: /Library/Application Support/Reprise could not be created. Please create this directory with the following 2 commands: sudo mkdir "/Library/Application Support/Reprise" and sudo chmod 777 "/Library/Application Support/Reprise" Also, in RLM v14.1 (and v14.1 only) the rlmsign utility will fail with some type of “unauthorized” error. This last error is corrected (i.e., a better error message) in later versions of RLM. Back to :ref:`appendix-a`. ------ .. _rlm-license-xxxx: rlm_license_XXXX() ================== Get checked-out license information. ------------------------------------ This is a family of functions that operate on a valid license handle. These functions return status and attributes of a checked-out license. Note that in the case of token-based licenses, these data will be attributes of the license which actually satisfied the request, rather than attributes of the token-based license itself. These functions are divided into *policy* functions, which you should use to affect license policy, and *display* functions, which you should use only to display license data to your user. .. warning:: Other than the *policy* functions, be very careful using these functions. The *display* functions are intended for the application to use to determine the details of the license checked out, for the purposes of display to the user. Use of these functions to affect the behavior of the application based on the contents of the optional fields in the license is annoying and frustrating to license administrators. This is because doing so makes application behavior mysterious to them, and non-standard across all their licensed applications. For example, using rlm_license_customer() to display the name of the customer is reasonable. Making runtime decisions about application behavior or capability based on the data returned from rlm_license_customer() makes the application behavior different from other licensed applications and risks customer dissatisfaction. This violates the RLM design philosophy of "policy in the license" and is historically a sore point with license administrators of license management systems. Reprise Software urges you to take heed. All functions operate on an RLM_LICENSE. Definitions for all functions are: .. code-block:: text #include "license.h" RLM_LICENSE license; .. note:: On all of the following functions that return strings, if there is no valid checked-out license or the license handle is invalid, the function returns a NULL pointer. For functions that return int, a return value of RLM_EL_NOHANDLE indicates that a null or invalid handle was passed to the function. The functions are: Policy Functions ---------------- rlm_license_akey() ^^^^^^^^^^^^^^^^^^ Retrieve activation key used to create license. .. code-block:: text char \*akey = rlm_license_akey(license); .. note:: The akey field is only used by RLM to control license pooling in the server. rlm_license_count() ^^^^^^^^^^^^^^^^^^^ Retrieve requested license count. .. code-block:: text int count = rlm_license_count(license); .. note:: The *count* is the count you requested in checkout. The sum of the counts across all processes might be larger than the total available count due to sharing. .. _rlm-license-stat: rlm_license_stat() ^^^^^^^^^^^^^^^^^^ Retrieve license status. .. code-block:: text int status; status = rlm_license_stat(license); You can retrieve the status of an *rlm_checkout()* call by calling *rlm_license_stat(license)*. *license* is the license handle returned by *rlm_checkout()*. This call does not query the license server for the status, it merely returns the status stored the last time the server was contacted. You can call this as often as you like. For a list of status returns, see :ref:`appendix-b`. This call, and *rlm_license_goodonce()* are the only calls in the family of *rlm_license_xxxx()* functions which you should use to affect application behavior. .. note:: You cannot call *rlm_license_stat()* on a license handle after that handle has been checked in, or if the RLM_HANDLE used to check it out has been closed. This will result in unpredictable behavior (including possible application crashes), since the handle you are using has been freed by RLM. rlm_license_goodonce() ^^^^^^^^^^^^^^^^^^^^^^ Was checkout ever successful on this handle. .. code-block:: text int status; status = rlm_license_goodonce(license); You can determine whether a checkout was ever successful on a particular license handle by calling *rlm_license_goodonce(license)*. If *status* is 0, the checkout was never successful. If non-zero, the checkout succeeded at one time (although the license may no longer be valid). Note that a license status of RLM_EL_OVERSOFT will be considered to be a good checkout, but RLM_EL_INQUEUE is not. RLM_EL_OVERSOFT is an error if you have a misconfigured token-based license (see the note in :ref:`token-based-restrictions`). rlm_license_options() ^^^^^^^^^^^^^^^^^^^^^ Retrieve license options. .. code-block:: text char \*options = rlm_license_options(license); The meaning of the options string is completely determined by an individual ISV. This string is intended to encode product options for this license. Display Functions ----------------- rlm_license_cached() ^^^^^^^^^^^^^^^^^^^^ Is the license cached on client node? .. code-block:: text int cached = rlm_license_cached(license); If this is a cached license, the return is 1, otherwise 0. rlm_license_client_cache() ^^^^^^^^^^^^^^^^^^^^^^^^^^ Returns the value of client_cache. .. code-block:: text int cache_time = rlm_license_client_cache(license); Returns the cache time for the license, in seconds. rlm_license_contract() ^^^^^^^^^^^^^^^^^^^^^^ Retrieve license contract string. .. code-block:: text char \*contract = rlm_license_contract(license); .. note:: This license field is unused by RLM. rlm_license_customer() ^^^^^^^^^^^^^^^^^^^^^^ Retrieve license customer string. .. code-block:: text char \*customer = rlm_license_customer(license); .. note:: This license field is unused by RLM. rlm_license_detached_demo() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve “detached demo” status of license. .. code-block:: text int detached = rlm_license_detached_demo(license); If this is a Detached Demo\ :sup:`TM` license, the return is 1, otherwise 0. rlm_license_exp() ^^^^^^^^^^^^^^^^^ Retrieve license expiration date. .. code-block:: text char \*exp = rlm_license_exp(license); .. note:: For licenses checked-out from a license server, the expiration date returned by the server is the first (earliest) expiration date from all the licenses which make up the license pool used to satisfy this request. In other words, there may be other licenses for this same product which expire later than this date. rlm_license_exp_days() ^^^^^^^^^^^^^^^^^^^^^^ Retrieve the # of days until license expiration. .. code-block:: text int days = rlm_license_exp_days(license); .. note:: **For licenses checked-out from a license server, the number of days to** **expiration is based on the first (earliest) expiration date** from all the licenses which make up the license pool used to satisfy this request. In other words, there may be other licenses for this same product which expire later than this date. .. note:: **rlm_license_exp_days() counts today as a day.** So, for example, a license which expires tomorrow at midnight will be reported as expiring in 2 days. A license which expires today at midnight will be reported as expiring in 1 day. If days == 0, this is a permanent license. If days is < 0, there was an error. rlm_license_hold() ^^^^^^^^^^^^^^^^^^ Retrieve license hold time. .. code-block: text int secs = rlm_license_hold(license); rlm_license_host_based() ^^^^^^^^^^^^^^^^^^^^^^^^ Is license host-based? .. code-block:: text int host_based = rlm_license_host_based(license); rlm_license_hostid() ^^^^^^^^^^^^^^^^^^^^ Retrieve license hostid. .. code-block:: text char \*hostid = rlm_license_hostid(license); License servers can serve nodelocked licenses as well as floating licenses. If you want to know if the license was checked out from a license server, call *rlm_license_server()*. If you want to know if the license is nodelocked, call *rlm_license_hostid()* - if the license is floating instead of nodelocked, this will return NULL. This call, however, returns the hostid from the LICENSE line, never the server's hostid. So for floating licenses, the return will be empty. rlm_license_ismetered() ^^^^^^^^^^^^^^^^^^^^^^^ Is this license metered? .. code-block:: text int ismetered = rlm_license_ismetered(license); *rlm_license_ismetered()* returns non-zero for a metered license, - 0 otherwise. Note that 0 is returned if the handle passed in is invalid. rlm_license_issued() ^^^^^^^^^^^^^^^^^^^^ Retrieve license issued date. .. code-block:: text char \*issued = rlm_license_issued(license); .. note:: This value is only correct for licenses which aren't served. Any license coming from a license server has an undefined rlm_license_issued() value.) rlm_license_issuer() ^^^^^^^^^^^^^^^^^^^^ Retrieve license issuer string. .. code-block:: text char \*issuer = rlm_license_issuer(license); .. note:: This license field is unused by RLM. rlm_license_line_item() ^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license line_item string. .. code-block:: text char \*line_item = rlm_license_line_item(license); .. note:: This license field is unused by RLM. rlm_license_max_roam() ^^^^^^^^^^^^^^^^^^^^^^ Retrieve maximum roam time. .. code-block:: text int days = rlm_license_max_roam(license); rlm_license_max_roam_count() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve maximum roam count. .. code-block:: text int max_roam_count = rlm_license_max_roam_count(license); rlm_license_max_share() ^^^^^^^^^^^^^^^^^^^^^^^ Retrieve maximum # of licenses that can be shared. .. code-block:: text int max_share = rlm_license_max_share(license); rlm_license_meter_counter() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve the meter counter for this license (if metered). .. code-block:: text int counter = rlm_license_meter_counter(license); rlm_license_min_checkout() ^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license minimum checkout time. .. code-block:: text int secs = rlm_license_min_checkout(license); rlm_license_min_remove() ^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license minimum remove time. .. code-block:: text int secs = rlm_license_min_remove(license); rlm_license_min_timeout() ^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license minimum timeout. .. code-block:: text int secs = rlm_license_min_timeout(license); rlm_license_named_user_count() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license Named User Count. .. code-block:: text int count = rlm_license_named_user_count(license); If count == 0, this is not a named user license. rlm_license_named_user_min_hours() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license Named User Minimum # of hours on the list. .. code-block:: text int minimum_hours = rlm_license_named_user_min_hours(license); The return from this call is only valid for licenses with named_user_count > 0. rlm_license_platforms() ^^^^^^^^^^^^^^^^^^^^^^^ Retrieve licensed platforms. .. code-block:: text char \*platforms= rlm_license_platforms(license); rlm_license_product() ^^^^^^^^^^^^^^^^^^^^^ Retrieve licensed product. .. code-block:: text char \*product = rlm_license_product(license); .. note:: rlm_license_product() retrieves the product name which satisfied the request. This may be different than the product requested. In the case of token-based licenses, the license requested is not the product that satisfies the license request. The actual product which satisfied the request is returned by rlm_license_product(). Also note that only the attributes of the **first** license (in the case of a compound token-based license) is returned by these calls. The first license is the first license listed in the token definition. rlm_license_roaming() ^^^^^^^^^^^^^^^^^^^^^ Retrieve "roaming" status of license. .. code-block:: text int roaming = rlm_license_roaming(license); If this is a roaming license, the return is 1, otherwise 0. Note that when you check the license out from the server requesting the roam, this is **not** a roaming license. The license is only roaming when the system is using the local roamed license without using the license server. rlm_license_server() ^^^^^^^^^^^^^^^^^^^^ Retrieve license server hostname. .. code-block:: text char \*server = rlm_license_server(license); If *license* is a license handle which has a valid checkout of a license which was granted from a license server, then the *rlm_license_server()* call will retrieve the hostname of the license server, otherwise an empty or NULL string will be returned. License servers can serve nodelocked licenses as well as floating licenses. If you want to know if the license is nodelocked, call *rlm_license_hostid()* - if the license is floating instead of nodelocked, this will return NULL. rlm_license_share() ^^^^^^^^^^^^^^^^^^^ Retrieve license sharing spec. .. code-block:: text int share = rlm_license_share(license); *share* is a bitmap, with the bits defined in *license.h*: * RLM_LA_SHARE_USER - Share if username matches. * RLM_LA_SHARE_HOST - Share if hostname matches. * RLM_LA_SHARE_ISV - Share if the isv-defined data matches. All fields specified in the bitmap must match in order for the license to be shared. rlm_license_single() ^^^^^^^^^^^^^^^^^^^^ Is license a “single” type. .. code-block:: text int single = rlm_license_single(license); Returns 1 if the license is “single”, 0 otherwise. rlm_license_soft_limit() ^^^^^^^^^^^^^^^^^^^^^^^^ Retrieve license soft limit. .. code-block:: text int soft_limit= rlm_license_soft_limit(license); .. note:: If licenses are pooled by the license server, the soft limit returned by this call is the sum of the soft limits of all pooled licenses. If some licenses do not have soft limits, the license count is used as the soft limit, thus this number could be equal to the license count. rlm_license_start() ^^^^^^^^^^^^^^^^^^^ Retrieve license start date. .. code-block:: text char \*start= rlm_license_start(license); rlm_license_teams() - Retrieve RLM Teams URL .. code-block:: text char \*url = rlm_license_teams(license); If *license* is a license handle which has a valid checkout of a license which was granted by RLM Teams, then the *rlm_license_teams()* call will retrieve the URL of the RLM Teams server, otherwise an empty or NULL string will be returned. rlm_license_type() ^^^^^^^^^^^^^^^^^^ Retrieve license type. .. code-block:: text int type = rlm_license_type(license); The type variable has bits set for the specified license types, as defined in *license.h*: * RLM_LA_BETA_TYPE - "beta" specified in license type keyword * RLM_LA_EVAL_TYPE - "eval" specified in license type keyword * RLM_LA_DEMO_TYPE - “demo” specified in license type keyword * RLM_LA_SUBSCRIPTION_TYPE - "subscription" specified in license type keyword .. note:: This license field is unused by RLM. rlm_license_tz() ^^^^^^^^^^^^^^^^ Retrieve license timezone spec. .. code-block:: text int tz = rlm_license_tz(license); rlm_license_uncounted() ^^^^^^^^^^^^^^^^^^^^^^^ Is license uncounted. .. code-block:: text int uncounted = rlm_license_uncounted(license); Returns 1 if the license is uncounted, 0 otherwise. rlm_license_user_based() ^^^^^^^^^^^^^^^^^^^^^^^^ Is license user-based? .. code-block:: text int user_based = rlm_license_user_based(license); rlm_license_ver() ^^^^^^^^^^^^^^^^^ Retrieve license version. .. code-block:: text char \*ver= rlm_license_ver(license); *rlm_license_ver()* returns the actual version of the license that was used to satisfy the request. This may be different than the version requested. Also note that if the request was satisfied by a TOKEN license on the server side, the version returned will be the greater of the requested version and the version of the first primary license which the TOKEN license utilizes. Back to :ref:`appendix-a`. ------ .. _rlm-log: rlm_log(), rlm_dlog() ===================== Log ISV-specific data. ---------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; const char data[]; **Log to report log:** .. code-block:: text (int) status = rlm_log(handle, data); Any time after calling *rlm_init*, the *rlm_log()* function can be called to log data to the ISV server's report log (if it exists). The *rlm_log()* function will establish a connection to a license server if one does not already exist, then all subsequent *rlm_log()* and *rlm_dlog()* calls will operate with this server (until *rlm_close()* is called on the handle). The data logged is a character string, which should not contain a newline character. The format of the data logged to the reportlog is: .. code-block:: text log hh:mm:ss data from rlm_log call **Log to debug log:** .. code-block:: text (int) status = rlm_dlog(handle, (const char \*) data); Any time after calling *rlm_init*, the *rlm_dlog()* function can be called to log data to the debug log. The rlm_dlog() function will establish a connection to a license server if one does not already exist, then all subsequent *rlm_log()* and *rlm_dlog()* calls will operate with this server (until *rlm_close()* is called on the handle). The data logged is a character string, which should not contain a newline character. The format of the data logged to the debug log is: .. code-block:: text mm/dd hh:mm (ISV name) ISV: data from rlm_log call **Return value:** *rlm_log()* and *rlm_dlog()* return 0 for success, and on failures: * RLM_EH_NOHANDLE - Called without a valid RLM_HANDLE. * RLM_EH_NO_REPORTLOG - rlm_log() called but the server does not have a reportlog. .. note:: The maximum length of a logged string is RLM_MAX_LOG (currently 256). However, logging strings much longer than 60 bytes will generally create wrapped lines in the debug and report log files. Back to :ref:`appendix-a`. ------ .. _rlm-products: rlm_products() ============== Generate list of products that can be checked out. -------------------------------------------------- .. code-block:: text #include "license.h" RLM_PRODUCTS products; RLM_HANDLE handle; char \*product; char \*ver; int status; products = rlm_products(handle, product, ver); (void) rlm_product_first(products); status = rlm_product_next(products); .. note:: *rlm_products()* is an expensive call. If you don't absolutely need it, don't call it. If you do call it, specify a product name if you can. You should avoid calling it more than once inside an application. Why is it expensive? If called with empty product/version strings, it has to validate the license keys for all node-locked uncounted/single-use licenses in local license files, and it also goes to every server in the list and retrieves from each server a list of available licenses. *rlm_products* generates a list of products of the specified version that can be checked out. If *product* is an empty or NULL string, all products are checked. If *ver* is empty or NULL, any version will be listed. If *rlm_products()* returns a non-null pointer, then there are products in the list. The **status** return from *rlm_product_next()* is 0 if there is another product in the list, or -1 if the list is exhausted. *rlm_products()* does not report on Detached Demo\ :sup:`TM` licenses. To examine the list of products, first call *rlm_products()* to retrieve the products pointer. Next, use *rlm_product_first()* and *rlm_product_next()* to walk the list of products returned. At any point after calling *rlm_product_first()*, you can call the appropriate function below. .. note:: You should **not** free any data returned by any of these calls. *rlm_products()* returns the licenses in the same order that rlm_checkout() will attempt checkouts. This order is: * If **RLM_ROAM** is set to a positive value, roamed licenses on the local node first. * All node-locked, uncounted licenses in local license files (from all license files in the license file path) will be next. * All licenses served by servers are next. * Finally, if **RLM_ROAM** is not set, the local roamed licenses will be last. .. note:: *rlm_products()* returns the list of valid roamed products on the local node, **whether** **or not it can check out an rlm_roam license**. *rlm_checkout()* first processes licenses from connected servers, then it attempts checkouts from servers that are not connected. However, rlm_products() will connect to all servers and get the lists from each of them. It will then close connections to all servers that have no active licenses checked out. If your software depends on the order of the licenses on license servers as returned from rlm_products() (not recommended), then you **should** call *rlm_set_attr_keep_conn(handle, 1)* before calling rlm_products(), so that rlm_products() will not close any connections that it makes. .. list-table:: :header-rows: 1 :widths: 50 50 * - Function - Description * - char **\*rlm_product_name(products)** - Returns the product name. * - char **\*rlm_product_ver(products)** - Returns the product version. * - char **\*rlm_product_exp(products)** - Returns the expiration date. If this product represents a pool in a license server, the expiration date will be the *earliest* expiration of any of the licenses which were combined to create the pool. * - int **rlm_product_exp_days(products)** - Returns the number of days until expiration. Note that “0” indicates a permanent license; a license which expires today has a value of 1. If this product represents a pool in a license server, the expiration date will be the *earliest* expiration of any of the licenses which were combined to create the pool. * - char **\*rlm_product_akey(products)** - Returns the akey= attribute. * - int **rlm_product_client_cache()** - Returns the value of the client_cache parameter. * - char **\*rlm_product_customer(products)** - Returns the customer attribute. * - char **\*rlm_product_contract(products)** - Returns the contract attribute. * - int **rlm_product_count(products)** - Returns the license count. * - int **rlm_product_current_inuse(products)** - Returns the license count in use. * - int **rlm_product_current_resuse(products)** - Returns the # of reservations in use. * - int **rlm_product_hbased(products)** - Returns the HOST-BASED count. * - int **rlm_product_hold(products)** - Returns the license hold time. * - char **\*rlm_product_hostid(products)** - Returns the license nodelock hostid, if it exists. * - int **rlm_product_isalias(products)** - Returns non-zero for an alias license, 0 otherwise. * - int **rlm_product_isfloating(products)** - Returns non-zero for a floating license, 0 otherwise. * - int **rlm_product_ismetered(products)** - Returns non-zero for a metered license, 0 otherwise. * - int **rlm_product_isnodelocked(products)** - Returns non-zero for a nodelocked license. * - int **rlm_product_issingle(products)** - Returns non-zero for a single license, 0 otherwise. * - char **\*rlm_product_issuer(products)** - Returns the issuer attribute. * - int **rlm_product_max_roam(products)** - Returns the maximum roam time. * - int **rlm_product_max_roam_count(products)** - Returns the max # of these licenses which can be roamed. * - int **rlm_product_max_share(products)** - Returns the max number of processes that can share this license. * - int **rlm_product_meter_counter(products)** - Returns the meter counter for this product (0 if not metered). * - int **rlm_product_meter_cur_count(products)** - Returns the meter count for this product (0 if not metered). * - int **rlm_product_min_remove(products)** - Returns the minimum rlmremove time. * - int **rlm_product_min_checkout(products)** - Returns the license minimum checkout time. * - int **rlm_product_min_timeout(products)** - Returns the minimum timeout time. * - int **rlm_product_named_user_count(products)** - Returns the named user count. * - int **rlm_product_nres(products)** - Returns the # of license reservations. * - int **rlm_product_num_roam_allowed(products)** - Returns the # of roaming licenses allowed. * - char **\*rlm_product_options(products)** - Returns the product options. * - int **rlm_product_personal(products)** - Returns the personal license reservation count. * - int **rlm_product_roaming(products)** - Returns the # of licenses currently roaming (for roaming licenses). * - char **\*rlm_product_server(products)** - Returns the license server's hostname (from the server's license file). * - char **\*rlm_product_start(products)** - Returns the product's start date, if present. * - int **rlm_product_share(products)** - Returns the license share flags. (Share flags (RLM_LA_SHARE_xxx) are defined in *license.h*) * - int **rlm_product_soft_limit(products)** - Returns the license soft limit. * - int **rlm_product_thisroam(products)** - Returns 1 if this license is a roaming license. * - int **rlm_product_timeout(products)** - Returns the current license timeout. * - int **rlm_product_tz(products)** - Returns the license timezone specification. * - int **rlm_product_tokens(products)** - If 0, this is a normal license. If non-zero, this is a token-based license. * - int **rlm_product_type(products)** - Returns the license type (TYPE= parameter). (License type flags (RLM_LA__xxx_TYPE) are defined in *license.h*) * - int **rlm_product_ubased(products)** - Returns the USER_BASED count. .. note:: All functions with char \* returns can return NULL for cases where the data does not exist, so you must check for a NULL return. For example, rlm_product_server() called on an unserved license will return NULL. .. note:: client-cached licenses on the client side will never be returned by *rlm_products()*. The rlm_product_client_cache() call returns the value of the cache time (in seconds) from the server's license. Certain of these items will always be 0 for node-locked, uncounted licenses. These are: * current_inuse * current_resuse * min_remove * nres * num_roam_allowed * timeout .. note:: The list of products may contain products that cannot be checked out at any given time, if all the licenses are in use, the maximum # of roaming licenses has been reached, etc. It is possible (at some time) to check out every product in the list, however. In other words, the list contains only licenses for which the license key is good, the time is past the start date and before the expiration date, the timezone is correct, and we are on the correct host if a hostid is specified. **Also note that the following licenses will never be returned by rlm_products():** * Detached Demo\ :sup:`TM` licenses * reserved license names (e.g., *rlm_server*, *rlm_server_enable_vm*, *rlm_no_server_lock*) * licenses passed in the 3rd parameter to rlm_init() * Client cached licenses The data returned by the *rlm_products()* call is dynamically allocated. Call *rlm_products_free(products)* to free this memory when you are finished with it, in order to avoid memory leaks in your program. You should only call *rlm_products_free()* once on the data returned by *rlm_products()*, and only when you are finished accessing this data. Back to :ref:`appendix-a`. ------ .. _rlm-putenv: rlm_putenv() ============ Set environment variable within the application. ------------------------------------------------ .. code-block:: text #include "license.h" RLM_HANDLE rh; int status; const char \*nvp; status = rlm_putenv(const char \*nvp); *rlm_putenv()* sets the specified name into the specified value in the process's environment. The return of *rlm_putenv()* is the return of the system *putenv()* call. Example: .. code-block:: text const char \*nvp = “RLM_ROAM=10”; rlm_putenv(nvp); In this example, the environment value of RLM_ROAM is set to 10. Back to :ref:`appendix-a`. ------ .. _rlm-set-active: rlm_set_active() ================ Inform RLM of activity status of application. --------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; int active; (void) rlm_set_active(rh, active); *rlm_set_active()* informs RLM that the application is *active* (active=1), or inactive (active=0). This is used with *rlm_auto_hb()* in order to allow your application's license to be timed-out with the license administration TIMEOUT option. The activity state applies to all checked-out licenses on the handle. If you call *rlm_auto_hb()*, heartbeats will be sent to the server whenever your application is running, whether you are actively processing or not. This means that an application which is simply waiting for user input will continue to send heartbeats, and will appear active to RLM. If you would like your license administrators to be able to time-out the licenses from applications which are in such an idle state, use the *rlm_set_active()* call to inform RLM when your application is active or inactive. .. note:: If you use manual heartbeats the rlm_set_active() call is not necessary, since you would only send heartbeat requests by calling rlm_get_attr_health() calls when the application is active. A call to *rlm_checkout()* will set the active flag to 1 (ie, the application is active) whether the checkout succeeds or not. Back to :ref:`appendix-a`. ------- .. _rlm-set-attr-keep-conn: rlm_set_attr_keep_conn() ======================== Set “keep connection” status for RLM. ------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; int conn_status; rlm_set_attr_keep_conn(handle, conn_status); When multiple checkouts are performed in a single application, RLM automatically create a new connection to a license server if the current license server cannot provide the license required. This operation is transparent to the application, and the RLM software maintains a list of connected servers which can be queried (in the order connected) for any new license request. When a checkout request fails, RLM can either close down the connection to the license server or keep it open. If your product checks out multiple licenses, an optimization is to keep these connections open (at the expense of the TCP/IP overhead for the connection). The default is to close the connection, which will be correct for the vast majority of applications. However, if you would like to keep the connection open, you can call: .. code-block:: text rlm_set_attr_keep_conn(handle, 1); Please note that making this call will not affect the functioning of RLM in your application - it is an optimization only. Back to :ref:`appendix-a`. ------ .. _rlm-set-attr-logging: rlm_set_attr_logging() ====================== Turn server logging on or off. ------------------------------ .. code-block:: text #include "license.h" RLM_HANDLE rh; int log; rlm_set_attr_logging(handle, log); By default, RLM servers log all license checkout and checkin activity. You can call *rlm_set_attr_logging()* any time before a checkout or checkin request, and if the value of *log* is non-zero, the server will log the the checkout/checkin status in both the debug and report log files. If the value of *log* is zero, the server will not log anything about the checkout/checkin. This is useful, for example, if you want to check out a product which should never succeed, in order to see if your license server has been compromised. The resulting checkout activity will not appear in any server log and will not confuse your customers. You should remember to turn logging back on after doing this, otherwise your license server logs will contain no checkout/checkin activity. Back to :ref:`appendix-a`. ------ .. _rlm-set-attr-password: rlm_set_attr_password() ======================= Set license password-string for future operations. -------------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; char \*password_string; rlm_set_attr_password(handle, password_string); Each license can contain a password. If the license contains a password, only processes which specify the matching password-string, will be able to use (either check out, or view) the license. You can call *rlm_set_attr_password()* any time before a checkout or status request, and the value of the password-string can be changed for subsequent requests. .. note:: The setting of the environment variable RLM_LICENSE_PASSWORD will be the default, but this call will override the value set in RLM_LICENSE_PASSWORD. The intended use of this capability is to allow a single license server to serve licenses for several independent customers. Each customer would be given a password-string, which would enable access to all their licenses, but not the licenses of other customers. If a license does not specify a password, calling *rlm_set_attr_password()* (or setting RLM_LICENSE_PASSWORD) will have no effect. Back to :ref:`appendix-a`. ------ .. _rlm-set-attr-reference-hostid: rlm_set_attr_reference_hostid() =============================== Set reference hostid for ActPro. -------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; char \*reference_hostid; (void) rlm_set_attr_reference_hostid(handle, reference_hostid); You can set the hostid which RLM uses as a reference hostid when creating a rehostable hostid. It is important that the hostid you set is a valid RLM hostid which is valid on the current host, otherwise your rehostable hostid will not work and will always return RLM_EL_NOTTHISHOST. You can call *rlm_set_attr_reference_hostid()* any time before an *rlm_act_request()*, *rlm_activate()* or *rlm_act_revoke_reference()* call. If you set the reference hostid when creating a rehostable hostid, you must set the same hostid before calling *rlm_act_revoke_reference()*, otherwise the rehostable hostid will not be revoked. The hostid string you pass to this function must be <= RLM_MAX_HOSTID_STRING characters long, **and must be a valid hostid on the current host**. .. note:: RLM selects a reference hostid automatically, and you should never need to make this call. Back to :ref:`appendix-a`. ------ .. _rlm-set-attr-req-opt: rlm_set_attr_req_opt() ====================== Set required substring in license options. ------------------------------------------ .. code-block:: text #include "license.h" RLM_HANDLE rh; char \*opts; rlm_set_attr_req_opt(handle, opts); You can request that any license must contain a certain substring in the “options=” field. You can call *rlm_set_attr_req_opt()* any time before an *rlm_checkout()* or *rlm_products()* call, and the value of the option substring can be changed for subsequent requests. If you set **opts** to an empty string (“”), no checking of the license options will be done by *rlm_checkout()* or *rlm_products()*. The opts parameter must be a substring in the license options, and the comparison is **CASE** **SENSITIVE**. .. note:: Once you call *rlm_set_attr_req_opt()*, you will only see licenses with the specified substring in the options field in either the *rlm_checkout()* or *rlm_products()* calls. If you want to see other licenses, call *rlm_set_attr_req_opt()* with an empty string. Back to :ref:`appendix-a`. ------ .. _rlm-set-environ: rlm_set_environ() ================= Set user/host/ISV-defined values for RLM. ----------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; char user[RLM_MAX_USERNAME+1]; char host[RLM_MAX_HOSTNAME+1]; char isv[RLM_MAX_ISVDEF+1]; rlm_set_environ(handle, user, host, isv); License sharing operates by comparing user, host, and ISV fields for matches. *rlm_set_environ()* allows the ISV to override the system's notion of user and/or host, and also provides a way to set the ISV-defined data. If any of user/host/isv are passed in as NULL, the corresponding field remains unchanged. The ISV field should be a printable string which does not contain the double-quote character ("). Note that *rlm_set_environ()* should be called after *rlm_init()* and before any *rlm_checkout()* call to which it should apply. Once *rlm_checkout()* is called, these values will persist for the life of the RLM_HANDLE in which you call *rlm_set_environ()*. You can call *rlm_set_environ()* any time (even after the first *rlm_checkout()* call), and the new user, host, and ISV-defined parameters will apply to all subsequent checkouts, until you call *rlm_set_environ()* again. The original settings will continue to apply to *rlm_products()* calls, however. .. note:: RLM always treats usernames and hostnames as case-insensitive. Back to :ref:`appendix-a`. ------ .. _rlm-skip-isv-down: rlm_skip_isv_down() =================== Enable "skip" of license servers where your ISV server isn't running. --------------------------------------------------------------------- .. code-block:: text #include "license.h" RLM_HANDLE rh; (void) rlm_skip_isv_down(rh); RLM keeps track of which license servers in the list have your ISV server running on them. If either: * The client cannot connect to the server, or * An attempt is made to check out a license from a server and the rlm server returns a status indicating that this ISV is not present, then the server is flagged as not having your ISV server. If you call *rlm_skip_isv_down()*, then future *rlm_checkout()* and *rlm_products()* calls will not attempt to use this license server. .. note:: By default, RLM will attempt all operations on all servers. You can call *rlm_skip_isv_down()* any time after calling *rlm_init()*. If you would like to give your user the opportunity to attempt to use these servers again, call: .. code-block:: text (void) rlm_forget_isv_down((RLM_HANDLE) rh) *rlm_forget_isv_down()* will cause RLM to attempt to use all license servers again, until it determines that your ISV server is not running. .. note:: RLM will attempt a connection one time to servers that don't have your ISV line in them. If the server is not up or if your ISV server isn't present, then that server won't be checked again. Back to :ref:`appendix-a`. ------ .. _rlm-stat: rlm_stat() ========== Retrieve RLM_HANDLE status. --------------------------- .. code-block:: text #include "license.h" RLM_HANDLE handle; int status; status = rlm_stat(handle); *rlm_stat()* retrieves the status of the handle created with the rlm_init() call. The status returned by *rlm_stat()* is only meaningful if called after *rlm_init()* or *rlm_init_disconn()* and **before any other RLM function**. **Calls to rlm_stat() after other RLM function calls return undefined results.** For a list of status returns, see :ref:`appendix-b`.