Page tree
Skip to end of metadata
Go to start of metadata

In this article we are going to add a sample code project to your own application using the language C. NSL can easily be added to new or existing software as it is a shared library and can be accessed as such. The example below is a basic set of rules to using our C libraries.

 

Before following this documentation, please be sure to first read sections Introduction which provide important details relating to integration. You may also want to review section Avoiding Potential Pitfalls - NSL. You should also create and download your custom Licensing/Analytics DLL - see section Download the required Nalpeiron library for how to do this.

 

Download the Example Application

You can download the required files at the Customer Center below:

 

The C Code kit (above download) provides some basic instruction and guidance for using Nalpeiron's Licensing tool (NSL) and Nalpeiron's Analytics too (NSA). 

The C Code kit consists of three pieces:

  1. A licensing example (nslExample.c)
  2. An analytics example (nsaExample.c)
  3. And a combined example (shafer.c)

Release Notes  (Please always check the release notes for the latest updates)

Getting Started

The NSL library can be installed anywhere that is convenient. All information and files used by NSL are stored in the WordDir location specified at library initialization (see NalpLibOpen below).
In our downloadable project you should note the following files:

 

nslExample.c

The main example file which make use of the library functions.

NSLCalls.c

Wrapper functions which relate specifically to Nalpeiron Licensing (NSL) functionality, e.g. shim_NSLValidateLibrary

SHACalls.c Wrapper functions which relate to general functionality required by both NSL and NSA, e.g. opening and closing the library.
shaUnix.c UNIX specific implementations of SetUpLib, getSymbol and ShutdownLib
shaWin.c 

Windows specific implementations of SetUpLib, getSymbol and ShutdownLib

 

You will usually only include shaUnix.c or shaWin.c depending on the OS you are using. 

Using the Nalpeiron Library with your Application

The basic steps for accessing and using the Nalpeiron library are:

  1. Open the Library
  2. Initializing and Verifying the Library
  3. Access the Desired Function(s)
  4. Close the Library

1. Opening the Library

You will have setup a product and downloaded the Nalpeiron support library (.dll, .so or .dylib) for your OS(es) in an earlier step (see setting up your products here). For convenience, let's assume that you library is call shaferfilecheck.so and is located in /tmp. Take special note of your customer ID, product ID and the authentication values you stampe into your library. You will need them in this example.

 

In our download example project you will find two files called shaUnix.c and shaWin.c. If you are using UNIX you should include the former file otherwise the latter. Both files include different (OS specific) implementations for various calls. For example, to open the NSL library we call a wrapper function called SetupLib (NSLExample.c):

C Example - Opening the library
int
main(
int		argc,
char	*argv[]
)
{


	...
 
	//Prepare the library for access via dlsym.
	if ((comArgs->libPath == NULL) ||
	(SetupLib(comArgs->libPath, &(comArgs->libHandle)) < 0))
	{
		fprintf(stderr, "Could not find the lib\n");
		usage();
	}	
 
	...
}


...where SetUpLib found in shaWin.c looks like this:

C Example (WINDOWS) - An implementation of SetupLib
int
SetupLib(
	char *libPath,
	void **libHandle
	)
	{
		int retVal;
		struct stat stbuf;

		//NOTE - Windows C library calls (like stat) only with with
		// ANSI paths. If you wish to use unicode characters in
		// your libPath you'll will have to convert to UTF-16 and
		// call _wstat
		retVal = stat(libPath, &stbuf);
		if (retVal != 0)
		{
			fprintf(stderr, "The library %s does not exist "
				"or has incorrect permissions.\n", libPath);
			return -1;
		}
		//NOTE - This too must be converted to UTF-16 and use
		// LoadLibraryW.
		*libHandle = (void *)LoadLibraryA(libPath);
		if (*libHandle == NULL)
		{
			fprintf(stderr, "libFileMgmt is corrupt: %d\n", GetLastError());
			return -1;
		}
		return 0;
	}
Be very careful when dealing with Unicode in Windows.
Windows uses UTF 16 internally which is not compatible with standard C functions. If the above snippet, the A at the end of LoadLibrary stands for Ascii as the library path "/tmp/shaferfilechecks.so" is an ascii string. You are free to use any encoding you wish but ALL STRINGS PASSED INTO THE NALPEIRON LIBRARY MUST BE UTF-8 encoded

Remember C considers the / characters to be escapes for the following character (i.e. if you want to include the double quotes inside a string it would be something like mystr=strdup(“\”");. To get a Windows type path that includes slashes you need to double up on them i.e. comArgs→libPath = strdup(“c://NSL_Example//CCodeKitSource//NalpeironCodeKit//Debug//ShaferFilechk.DLL”); You’ll have to do the same for the comArgs→workDir strdup. 

 

...and in shaUnix.c look like this:

C EXample (UNIX) - An implementation of SetupLib
int
    SetupLib(
        char *libPath,
        void **libHandle
    )
    {
    	int retVal;
		struct stat stbuf;

		retVal = stat(libPath, &stbuf);
		if (retVal != 0)
		{
			fprintf(stderr, "The library %s does not exist "
				"or has incorrect permissions.\n", libPath);
			fprintf(stdout, "The library %s does not exist "
				"or has incorrect permissions.\n", libPath);
			fflush(stdout);
			return -1;
		}
		fprintf(stdout, "Library exists\n");
		fflush(stdout);
		*libHandle = dlopen(libPath, RTLD_LOCAL | RTLD_LAZY);
		fprintf(stdout, "finished dlopen\n");
		fflush(stdout);
		if (*libHandle == NULL)
		{
			fprintf(stderr, "libFileMgmt is corrupt\n");
			fprintf(stderr, "%s\n", dlerror());
			fprintf(stdout, "libFileMgmt is corrupt\n");
			fprintf(stdout, "%s\n", dlerror());
			fflush(stdout);
			return -1;
		}
return 0;
}
NOTE: RTLD_LOCAL ensure the symbols are only made available when we ask for them.

RTLD_LAZY causes the symbols to be resolved only when they are needed. If you are planning to use multiple nalpeiron libraries in the same process, you must use the RTLD_LOCAL parameter when calling dlopen. Otherwise, a -1074 error (library already initialized) will most likely occur on opening the second and subsequent libraries.

 

2. Initializing the library

Initializing the library entails setting up and calling the NalpLibOpen function (returns 0 on success or a negative number on failure) which takes an XML string as its parameter (see below for the XML schema).

To improve security, a security constant can be passed into the NalpLibOpen call via its XML parameter and element <SecurityValue>. This allows each function to return a semi-random value which is easily decoded to the true return. This feature ensures that the library's return values can't be sniffed and used to create a spoofed version.

The following shows how you might write your code to create the security value and construct your XML string before making the call to open the library:

Example C - Initializing the library
int
main(
int		argc,
char	*argv[]
)
{
	...
    //These are the security values stamped into your library.
    // They should be changed to match your vaues.
    unsigned int xauth = 10;
    unsigned int yauth = 20;
    unsigned int zauth = 30;
 
    //These values should be set to your customer ID and
    // product ID. They are used to verify that the library
    // being accessed corresponds to your product.
    char custID[] = "3183";
    char prodID[] = "100";
	...
 
	//Random number between 1 and 500. The security value is used
	// along with the authentication values stamped into the library
	// to create a unique offset that is added to all returns. Using
	// a random number for security ensures that the offset is
	// different for every run of your software. This feature is
	// enabled by setting the <SecurityValue> when contructing
	// the XML passed into NalpLibOpen.
	srand((unsigned)time(NULL));
	security = 1 + (unsigned int)(500.0 * rand() / (RAND_MAX + 1.0));
	offset = xauth + ((security * yauth) % zauth);

	//You must always call NalpLibOpen before using the NSL library. 
	// NalpLibOpen initializes necessary structures and kicks off the
	// threads. To guard against future changes, NalpLibOpen takes
	// a xml string as its parameter. Construct that xml
	// parameter string.
	retVal = constNSLParams(&xmlParams, security, comArgs);
	if (retVal < 0)
	{
		return -1;
	}

	retVal = shim_NalpLibOpen(xmlParams, comArgs->libHandle);
 
	...
}

...where an implementation of constNSLParams can be found in NSLExample.cs:

C Example - Constructing the XML string
int
constNSLParams(
	char **xmlParams,
	int security,
	struct command_arg *comArgs
	)
{
	int xmlLen;
	char secVal[25];
	//Start with enough room for
	// <?xml version=\"1.0\" encoding=\"UTF-8\"?> 42
	// <SHAFERXMLParams> 17
	//+ 1 (NULL Terminator)
	xmlLen = 60;
	*xmlParams = (char *)malloc(xmlLen);
	strcpy(*xmlParams, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	strcat(*xmlParams, "<SHAFERXMLParams>");
	addXMLParam(xmlParams, "NSLEnabled", "1");
	addXMLParam(xmlParams, "WorkDir", comArgs->workDir);
	addXMLParam(xmlParams, "LogLevel", comArgs->logLevel);
	addXMLParam(xmlParams, "WorkGroup", comArgs->workGroup);
	//Enable the security offset feature. That is, all returns from
	// the library will have a security offset added to them.
	sprintf(secVal, "%i", security);
	addXMLParam(xmlParams, "SecurityValue", secVal);
	*xmlParams = (char *)
	realloc(*xmlParams, strlen(*xmlParams) + 18 + 1); 
	strcat(*xmlParams, "</SHAFERXMLParams>");
	return 0; 
}

 

Validating the library ensures that the library currently being accessed is a valid Nalpeiron library stamped with your customer ID and product ID and should be called immediately following opening the library. An implementation of shim_NSLValidateLibrary can be found in file NSLCalls.c

C EXample - Validating the library
retVal = shim_NSLValidateLibrary(custID,
prodID, comArgs->libHandle);
retVal = retVal - offset;
if (retVal != 0)
{
    fprintf(stderr, "Library failed security\n");
    NSLHandleError(retVal, comArgs->libHandle);
}
else
{
    fprintf(stdout, "Library validated\n");
}

XML Schema for NalpLibOpen 

 

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<SHAFERXMLParams>
<WorkDir>/tmp/</WorkDir>
<WorkGroup>groupName</WorkGroup>
<LogLevel>4</LogLevel>
<LogQLen>300</LogQLen>
<CacheQLen/>
<SoapThreadsMin/>
<SoapThreadsMax/>
<ProxyIP/>
<ProxyPort/>
<ProxyUsername/>
<ProxyPassword/>
<DaemonIP/>
<DaemonPort/>
<OfflineMode>0</OfflineMode>
<NSAEnabled>0</NSAEnabled>
<NSLEnabled>1</NSLEnabled>
<SecurityValue>uint32 sec val</SecurityValue>
</SHAFERXMLParams>

 

By using a XML parameter any future expansion of NalpLibOpen will always be backward compatible with existing applications. These values have the following meaning:

WorkDir

The storage location for the library. License files, cache files, log files, etc are stored in the location. The WorkDir can be any location where your application has read/write privileges.

WorkGroup

Modify the ownership/permissions of all files created by the library to allow access by this group.  The special group "nalpworld" exists which will allow access by all users of the system. NOTE - This parameter may be sent to Windows machines but will have no effect there.  On a you can create the containing directory with the permissions you want and let the files inherit those permissions.

LogLevel  The amount of detail written to the log file. 0 (off) no logging, 1 log only errors, 2 log errors and warnings, 3 log errors, warnings and informational messages, 4 log all the preceeding and display debug info.
LogQLen  The number of log messages that may be queued up waiting for write to the log. 300 is a good value for this to ensure no log messages are lost while not drastically increasing the library's footprint.
CacheQLen  

The maximum size of the cache file. The cache file is where NSA transactions are written if the SOAP server is unavailable for some reason. Once the file reaches maximum size, it wraps over writing the oldest information.

SoapThreadsMin/SoapThreadsMaxThe minimum and maximum number of thread used for NSA SOAP transactions.
ProxyIP/ProxyPort/ProxyUsername/ProxyPasswordProxy information, if needed.
DaemonIP/DaemonPort  Not yet implemented
OfflineMode  If OfflineMode is enabled (1), all NSA information is cached to disk rather than being sent to the Nalpeiron server.
NSA/NSLEnabledEnable the NSA/NSL libraries. 0 (default) disables the library. 1 enables it.
SecurityValue The security offset value (see below).
If any values are not present in the XML passed into NalpLibOpen, that feature will be disabled or default values will be used as appropriate.

3. Access the Desired Function(s)

To call into any of the libraries routines, we'll have to resolve the symbol then use it to call the routine.

The symbol returned from the library in this manner is a function pointer. To use the pointer, we'll need a prototype for the function, the pointer and any parameters necessary for the function call.

Prototypes for all the Nalpeiron library functions can be found in NalpeironNSA.h (NSA prototypes),NalpeironNSL.h (NSL prototypes) and NalpeironSHA.h (generic prototypes). All three header files are available in the C codekit and may be used freely in your code.
 

The three functions we are using in this example are NalpLibOpenNalpLibClose and NSLValidateLibrary. The first two prototype are found in NalpeironSHA.h and are

 

typedef int (*NalpLibOpen_t)(char *xmlParams);
typedef int (*NalpLibClose_t)();

 

NSLValidate if found in NalpeironNSL.h and is:

 

typedef int (*NSLValidateLibrary_t)(int custID, int prodID);

 

As an example, we can look at the shim-NalpLibOpen wrapper function found in file SHACalls.c. You can see that this obtains the pointer to the NalpLibOpen function by calling another wrapper function, getSynbol, which has different implementations depending on the OS you are using. The different OS specific implementations can be found below.

C Example -
int
shim_NalpLibOpen(
char *xmlParams,
void *libHandle
)
{
int status;
NalpLibOpen_t NalpLibOpen_ptr = NULL;

if (!(NalpLibOpen_ptr = getSymbol("NalpLibOpen", libHandle)))
{
return -1;
}

status = NalpLibOpen_ptr(xmlParams);
return status;
}

 

For Unix like systems (including Linux and OSX)

You will find the implementation of getSymbol in the shaUnix.c file. The symbols are retrieved with dlsym:

 

C Example
void *
getSymbol(
	char	*name,
	void	*libHandle
	)
{
	return dlsym(libHandle, name);
}

 

For Windows

You will find the implementation of getSymbol in the shaWin.c file. The symbols are retrieved with GetProcAddress:
void *
	getSymbol(
		char	*name,
		void	*libHandle
	)
{
	return GetProcAddress((HINSTANCE)libHandle, name);
}

 

In the both code snippets above, libHandle is the value found.

4. Close the Library

To close the library you must call NalpLibClose followed by dlclose or FreeLibrary.

 

If NalpLibClose isn't called when you're finished, the main program won't wait for any working threads to finish before shutting down. This will result in a loss of any information still being processed by the threads. It may also cause memory corruption.

 

Putting It Altogether

The following code shows how to how and where to setup your customer ID, product ID and security constants required for validation, open the library and initialise it by building the XML string and passing this into shim_NalpLibOpen, then calling the validate function. At this point, assuming validation passes you may continue to call any of the Nalpeiron library functions. At the end you should always close the library by calling shim_NalpLibClose

 

 

C Example - A Complete Example
int
main(
	int argc,
	char *argv[]
	)
{
	int nextArg;
	uint32_t noProcs;
	uint32_t maxProcs;
	int32_t featureStatus;
	int32_t licenseStatus;
	int retVal;
	char *version;
	char *compID;
	char *hostName;
	char *licNo;
	char *pdataValue;
	unsigned int expSecs;
	char *expDate;
	char *xmlParams;
	int security;
	int offset;
	
	//These are the security values stamped into your library.
	// They should be changed to match your vaues.
	unsigned int xauth = 10;
	unsigned int yauth = 20;
	unsigned int zauth = 30;

	//These values should be set to your customer ID and
	// product ID. They are used to verify that the library
	// being accessed corresponds to your product.
	char custID[] = "3183";
	char prodID[] = "100";

	comArgs = (struct command_arg *)
	malloc(sizeof(struct command_arg));
	nextArg = parseargs(argc, argv, comArgs);
	if ((argc - nextArg) != 0)
	{
		usage();
	}
	
	//Prepare the library for access via dlsym.
	if ((comArgs->libPath == NULL) ||
	(SetupLib(comArgs->libPath, &(comArgs->libHandle)) < 0))
	{
		fprintf(stderr, "Could not find the lib\n");
		usage();
	}
	// Random number between 1 and 500. The security value is used
	// along with the authentication values stamped into the library
	// to create a unique offset that is added to all returns. Using
	// a random number for security ensures that the offset is
	// different for every run of your software. This feature is
	// enabled by setting the <SecurityValue> when contructing
	// the XML passed into NalpLibOpen.
	srand((unsigned)time(NULL));
	security = 1 + (unsigned int)(500.0 * rand() / (RAND_MAX + 1.0));
	offset = xauth + ((security * yauth) % zauth);

	//You must always call NalpLibOpen before using the NSL library. 
	// NalpLibOpen initializes necessary structures and kicks off the
	// threads. To guard against future changes, NalpLibOpen takes
	// a xml string as its parameter. Construct that xml
	// parameter string.
	retVal = constNSLParams(&xmlParams, security, comArgs);
	if (retVal < 0)
	{
		return -1;
	}
	retVal = shim_NalpLibOpen(xmlParams, comArgs->libHandle);
	
	free(xmlParams);
	if (retVal < 0)
	{
		fprintf(stderr, "Initialization of library failed\n");
		NSLHandleError(retVal, comArgs->libHandle);
		return -1;
	}

	//Validate the library. This ensures that the customerID
	// and product ID stamped into the library match those
	// of your software. In a real application
	// NSLValidateLibrary should be called immediately upon
	// opening the library. If the function returns an error
	// value, the software should immediately exit.
	retVal = shim_NSLValidateLibrary(custID,
	prodID, comArgs->libHandle);
	retVal = retVal - offset;
	if (retVal != 0)
	{
		fprintf(stderr, "Library failed security\n");
		NSLHandleError(retVal, comArgs->libHandle);
	}
	else
	{
		fprintf(stdout, "Library validated\n");
	}

	//You're ready to use the library!!!
	//When you're down, shutdown
	retVal = shim_NalpLibClose(comArgs->libHandle);
	cleanup(comArgs);
	return 0;
}

 

Library Usage


All functions return positive numbers (or 0) on success and negative number on error. Strings passed into NSL are expected to be either ANSI C strings or UTF8 encoded unicode. The following functions are provided by the NSL library. Of course, as you will be accessing them from the shared libraries rather than directly you need to use the typedeffed functions pointers (see NalpeironNSL.h in the c/c++ codekit) rather than these prototypes. For example usage see nslExample.c in the code kit.

Click here for the full API Docs (opens a window)

The C code kit contains an example usage of the NSL Library. The example can be built from the command line with the included Makefile. The result is a command line program that accesses each of the NSL functions. It can be incorporated into your project (especially the header files) or used to test/debug. Usage information may be obtained with the -? parameter:
 

Specify a NSL function via:
-ANSLGetActivationCertReq
-CNSLGetComputerID
-DNSLGetDeactivationCertReq
-ENSLGetLeaseExp (date | sec)
-FNSLFeatureStatus
-GNSLGetTrialExp (date | sec)
-HNSLGetHostname
-INSLImportCertificate
-KNSLGetSubExp (date | sec)
-LNSLGetLicense
-NNSLGetLicenseCode
-PNSLGetNumbAvailProc
-RNSLReturnLicense
-SNSLGetLicenseStatus
-TNSLValidateLibrary
-VNSLGetVersion

 

 
Specify NSL parameters via:
-b stringlog directory path
-c stringCustomer ID
-d stringlog level [0 - 6]
-f stringFeature nAME
-h stringMax log queue length
-n stringLicense Number
-p stringProduct ID
-u stringUsername
-w stringProxy IP address
-x stringProxy Port number
-y stringProxy Username
-z stringProxy Password

 

 
Other:-l value library path

-? This message
 

NSL Examples Usage

Example functionCall

Retrieve the system's computer ID

./nslExample -l /tmp/test.so -C

Retrieve the name of the SOAP server used to retrieve license

./nslExample -l /tmp/test.so -H

Validate the library against your customer and product IDs

./nslExample -l /tmp/test.so -c custID -p prodID -T
Retrieve the NSL library version./nslExample -l /tmp/test.so -V

Retrieve the Status of the current license

./nslExample -l /tmp/test.so -S
Retrieve the Status of a given feature./nslExample -l /tmp/test.so -f featureName -F

Retrieve the expiration time of the current license as number of seconds remaining

./nslExample -l /tmp/test.so -E s

Retrieve the expiration time of the current license as time/data string

./nslExample -l /tmp/test.so -E d

Retrieve the expiration time of the current license as numeric DD/MM/YYYY

./nslExample -l /tmp/test.so -N

Contact the Nalpeiron server and attempt to get a license.  If
licenseNo is not specified the license will be a trial license.

./nslExample -l /tmp/test.so -n licenseNo -L

In addition to providing an example and debugging tool, you will find NalpeironNSL.h useful. It contains typedeffed function pointers that you may use in your project to access the NSL functions.
 


THE SOFTWARE IS PROVIDED "AS IS." TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, NALPEIRON DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING DOCUMENTATION. YOU ASSUME RESPONSIBILITY FOR SELECTING THE SOFTWARE TO ACHIEVE YOUR INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED FROM THE SOFTWARE. WITHOUT LIMITING THE FOREGOING PROVISIONS, NALPEIRON MAKES NO WARRANTY THAT THE SOFTWARE WILL BE ERROR-FREE OR FREE FROM INTERRUPTIONS OR OTHER FAILURES OR THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS.

View the full Licence Agreement (English) - With the download or use of the software you agree to the licence agreement.
  • No labels