Matlab Compiler: protecting re-distribution of software during installation - matlab

I'm considering using Matlab Compiler to distribute software for a price. I'm investigating (very) simple methods to discourage re-distribution without annoying users. Any recommendations?
One thought is to email a user a license key and have them input this during the installation process to be verified on a license server. If the key matches what is on the server, the installation proceeds as usual, otherwise, a warning message is shown to inform the user to purchase another license. However, this method requires a specified function to run only during the installation process, and not thereafter (so as not to annoy the user). Is this possible using Matlab Compiler or otherwise?
I suppose I could create a file on the user's disk that the program looks for when it starts (if it exists, then it is not being run for the first time), but if the user copies the whole directory, that file would get copied too.

In order to create an effective licensing system, you have to link it to one or more properties of a user machine (MAC address, OS ID, hard disk serial numbers, CPU serial numbers, etc...).
If you don't to this, you are just going to release licenses that can be transferred from one user to another. If one user decides to spread his license file worldwide, you are doomed because everyone could potentially take that license file and use it to unlock your application.
But if you link your license files to one or more properties of a user machine, as mentioned above, you must be able to obtain these properties either:
before the user decides to buy your application;
when the user activates his license.
First Scenario
You release your software as a trial. When it is started for the first time, you set an expiration date in the registry or in a file well hidden somewhere. You check against the expiration date when the application starts and, once it is reached, you throw an error and you don't let the used play with your application anymore.
Within the application, you create a Register Now button somewhere. When it is clicked, the application retrieves the machine properties and passes them to the web page / form that will be opened to let the user perform the payment. That page will be in charge to validate the machine properties, receive the payment and, finally, deliver a valid license code based on these properties.
Within the application, you must implement the same logics that allowed your form to create the license code, because you will need to use them in order to validate the code itself every time your application starts. A pseudo-code example:
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lc = GetLicenseCode();
if (~strcmp(sha1([mp1 mp2 mp3]),lc))
errordlg('Invalid license code!');
return;
end
This is the simplest path. But keep in mind that if one or more properties of the user machine change (because he changes a device or reinstalls his OS), his license will be invalidated and you will have to provide a customer assistance service that takes care of this kind of situations.
Second Scenario
This one is much harder. You will not be able to know the user's machine properties in advance. So your licensing system will work on a two-steps basis. You release a unique code (called LID for example) when the used purchases your application. Then, once the user inserts that it in your application, your application must send it back together with the machine properties. The final key (called LKey for example) is then computed and sent back to the user.
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lkey = GetLicenseKey();
if (~strcmp(sha1([mp1 mp2 mp3]),lkey))
errordlg('Invalid license code!');
return;
end
Machine Properties
The first solution has been provided to you through a comment: the MachineGuid value located in the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography. It's pretty solid. But it will only work on Windows machines. Use winqueryreg to access the registry.
Another good alternative is the Window Domain Controller Security ID, which is another machine-specific unique identifier. You can retrieve it using Java code within Matlab:
wdc_sid = com.sun.security.auth.module.NTSystem.getDomainSID();
or through the Windows registry key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\GroupMembership. The registry approach should be the one to use if you want to maintain a certain backward compatibility with old Matlab releases. Unfortunately, the Window Domain Controller Security ID is another identifier that is available only on machines that run under Windows.
If you want to adapt your licensing system to every possible OS and environment, you have to use a more generic approach, based on universally accessible hardware properties: MAC adresses, hard disk serials and such things. As far as I know, the most reliable property is the MAC address, because its uniqueness, althrough not granted, is almost certain and it's very unfrequent to change a network adapter (there are more chances to break an hard disk actually). Retrieve the MAC adresses of the machine network adapters using Java code as follows:
mac_addrs = '';
net_int = java.net.NetworkInterface.getNetworkInterfaces();
while (net_int.hasMoreElements)
mac_addr = net_int.nextElement.getHardwareAddress();
if (~isempty(mac_addr))
mac_addrs = [mac_addrs, '-', sprintf('%.2X',typecast(mac_addr,'uint8'))];
end
end
mac_addrs = mac_addrs(2:end);
The above computation produces a character array that represents the result of the concatenation of all the MAC addresses found on the machine. Again, for compatibility reasons, this may not work on old Matlab releases, so you have to use a much more complex approach, described here.
[EDIT]
This approach to retrieve the MAC address based on the underlying OS could be easier:
switch computer('arch')
case {'maci','maci64'}
[~,a]=system('ifconfig');
c=strfind(a,'en0');if ~isempty(c),a=a(c:end);end
c=strfind(a,'en1');if ~isempty(c),a=a(1:c-1);end
% find the mac address
b=strfind(a,'ether');
mac_add=a(1,b(1)+6:b(1)+22);
case {'win32','win64'}
[~,a]=system('getmac');b=strfind(a,'=');
mac_add=a(b(end)+1:b(end)+19);
case {'glnx86','glnxa64'}
[~,a]=system('ifconfig');b=strfind(a,'Ether');
mac_add=a(1,b(1)+17:b(1)+33);
otherwise,mac_add=[];
end
I found it in the comments of this article.

Related

serial monitoring method to test communication via com ports without a serial communication device

I have a Verilog code simulated and synthesized on ISE design toolkit. I've got an FPGA spartan 6 device which is to be used for the implementation. But there is a problem with the device (probably a power issue) which makes the device unavailable in any of the COM ports when I connected it to my PC. So I want to check whether my Matlab code which I made for serial communication through the device does the desired job. So I need a method to test serial communication via any of the COM ports without connecting a serial com device to the PC. Is there any such method that I can Tx Rx serial data from Matlab to COM ports? Any software or any other method would be highly appreciated :)
I found a way to test Matlab serial communication using virtual serial ports.
Download "Freeware Virtual COM Ports Emulator" from: http://freevirtualserialports.com/
I installed it in Windows 10, and it's working (as trial).
Add a pair of two serial ports:
Execute the following Matlab code sample to verify it's working:
s3 = serial('COM3','BaudRate',115200);
s4 = serial('COM4','BaudRate',115200);
fopen(s3);
fopen(s4);
fwrite(s3, uint8([1, 2, 3, 4, 5]));
%fprintf(s3, '12345');
pause(0.1);
RxBuf = fread(s4, 5)
fclose(s3);
delete(s3);
clear s3
fclose(s4);
delete(s4);
clear s4
The output is:
RxBuf =
1
2
3
4
5
Bypassing the problem "it only stays for a single test session".
There is a problem when creating a pair of virtual ports using the software, it only stays for a single test session.
I guess it's a problem with the COM port emulation software.
The following solution, is not a good practice (and not a true solution).
Declare the serial object as global, keeping the object persistent.
Create the serial object only if it's not created.
Don't delete and don't clear the serial object.
See the following code sample:
global s3 s4
if isempty(s3)
s3 = serial('COM3','BaudRate',115200);
end
if isempty(s4)
s4 = serial('COM4','BaudRate',115200);
end
fopen(s3);
fopen(s4);
fwrite(s3, uint8([1, 2, 3, 4, 5]));
pause(0.1);
RxBuf = fread(s4, 5)
fclose(s3);
%delete(s3);
%clear s3
fclose(s4);
%delete(s4);
%clear s4
You can also look for a better virtual COM port software.
As Rotem suggested, if you need to communicate via serial line between 2 program of your PC you need a virtual COM port emulator.
It seems you are running on Windows OS so I would recommend a completely free emulator (not a trial one). For Windows I use com0com Null-modem emulator (from SourceForge).
In the example below I will show how to communicate with "another" device so Matlab will not handle both side of the communication. The other device will be simulated by a simple terminal. For windows I use RealTerm: Serial/TCP Terminal (also from SourceForge).
Setup:
Execute the setup of both program with all default options. by default com0com will create a virtual pair COM3/COM4 but if these port already exist on your system the program may assign other numbers. Check the numbers before you run the example. (it will also create a CNCA0/CNCB0 pair but you can ignore this one for now).
For RealTerm, once installed (don't forget to activate the server registration at the end of the setup, it should be ticked by default though), it will look like below. Keep all default options, just set the port number and the baud rate if they need to be changed.
Test MATLAB -> Terminal
You are ready to send Ascii characters or binary values from MATLAB to your device. The animation below shows you an example of both option:
you can click on the picture to see it full size. It is running in loop so you may want to wait until it restart from the beginning.
Test Terminal -> MATLAB
Below animation shows you how to test the communication in the other way:
Don't forget to tick [CR] [LF] on RealTerm when you send Ascii characters and want to use the '%s' format specifier on MATLAB, as it needs these characters to detect the end of the string.
Note:
If you have another terminal program that you are more used too, it
will work the same.
If the RealTerm option does not suit you, or if you want to handle
both sides of communication from Matlab, then you can use the code
provided by Rotem in his first answer. Just install com0com but
ignore all the RealTerm part.

Moving from file-based tracing session to real time session

I need to log trace events during boot so I configure an AutoLogger with all the required providers. But when my service/process starts I want to switch to real-time mode so that the file doesn't explode.
I'm using TraceEvent and I can't figure out how to do this move correctly and atomically.
The first thing I tried:
const int timeToWait = 5000;
using (var tes = new TraceEventSession("TEMPSESSIONNAME", #"c:\temp\TEMPSESSIONNAME.etl") { StopOnDispose = false })
{
tes.EnableProvider(ProviderExtensions.ProviderName<MicrosoftWindowsKernelProcess>());
Thread.Sleep(timeToWait);
}
using (var tes = new TraceEventSession("TEMPSESSIONNAME", TraceEventSessionOptions.Attach))
{
Thread.Sleep(timeToWait);
tes.SetFileName(null);
Thread.Sleep(timeToWait);
Console.WriteLine("Done");
}
Here I wanted to make that I can transfer the session to real-time mode. But instead, the file I got contained events from a 15s period instead of just 10s.
The same happens if I use new TraceEventSession("TEMPSESSIONNAME", #"c:\temp\TEMPSESSIONNAME.etl", TraceEventSessionOptions.Create) instead.
It seems that the following will cause the file to stop being written to:
using (var tes = new TraceEventSession("TEMPSESSIONNAME"))
{
tes.EnableProvider(ProviderExtensions.ProviderName<MicrosoftWindowsKernelProcess>());
Thread.Sleep(timeToWait);
}
But here I must reenable all the providers and according to the documentation "if the session already existed it is closed and reopened (thus orphans are cleaned up on next use)". I don't understand the last part about orphans. Obviously some events might occur in the time between closing, opening and subscribing on the events. Does this mean I will lose these events or will I get the later?
I also found the following in the documentation of the library:
In real time mode, events are buffered and there is at least a second or so delay (typically 3 sec) between the firing of the event and the reception by the session (to allow events to be delivered in efficient clumps of many events)
Does this make the above code alright (well, unless the improbable happens and for some reason my thread is delayed for more than a second between creating the real-time session and starting processing the events)?
I could close the session and create a new different one but then I think I'd miss some events. Or I could open a new session and then close the file-based one but then I might get duplicate events.
I couldn't find online any examples of moving from a file-based trace to a real-time trace.
I managed to contact the author of TraceEvent and this is the answer I got:
Re the exception of the 'auto-closing and restarting' feature, it is really questions about the OS (TraceEvent simply calls the underlying OS API). Just FYI, the deal about orphans is that it is EASY for your process to exit but leave a session going. This MAY be what you want, but often it is not, and so to make the common case 'just work' if you do Create (which is the default), it will close a session if it already existed (since you asked for a new one).
Experimentation of course is the touchstone of 'truth' but I would frankly expecting unusual combinations to just work is generally NOT true.
My recommendation is to keep it simple. You need to open a new session and close the original one. Yes, you will end up with duplicates, but you CAN filter them out (after all they are IDENTICAL timestamps).
The other possibility is use SetFileName in its intended way (from one file to another). This certainly solves your problem of file size growth, and often is a good way to deal with other scenarios (after all you can start up you processing and start deleting files even as new files are being generated).

JTAG: How do I know the width of the Instruction Register?

Assumed I have a JTAG-chain with several devices from different manufactures:
How does my software, which shall communicate with a specific system within that chain, known the length of the IR for all the others devices within the chain? I do have to know them to send a certain instruction to my device, right?
It is possible to detect the total length of all IR registers in your JTAG daisy-chain. It is also possible to detect the number of devices (or TAPs) in your chain. But you can't detect the individual IR length of a single TAP.
What you can do: You can read out the JTAG ID code register of all of you TAPs. The ID code register (in DR path) is always 32 bit and gets selected by test-logic-reset.
With the ID code you can identify the existing TAPs and look up in the datasheet the length of the individual IR registers.
And yes: In general you do have to know the individual IR length of all the TAPs in your chain to communicate with one of them.
try here: http://www.fpga4fun.com/JTAG3.html
When IR = '1...1', the BYPASS is selected.
The idea is to send a lot of '1' so regardless of IR length all devices will select BYPASS.

Mimic 'Pick up Line 1' On Asterisk/SPA504G Phone System

We have a customer who is using a new Asterisk phone system we set up for them using SPA504Gs and SPA500DS sidecars. They want to mimic their old system, where once a call is picked up on an extension it can be placed on hold and picked up from anywhere without having to actively transfer it to a single phone.
For instance, person A picks up Line 1. Person A pages all the phones to say there is a call available on Line 1 for Person B. Person B needs to be able to pick that call up wherever they are.
We currently have the SPA504G's set up where Line 1 is the inbound extension, and Lines2-4 represent the DID's for the customer. When a call is picked up off one of the DIDs it is only active on that phone, so that other callers could call into the DID.
We're unclear how to make it so the call can be picked up from anywhere, could be make a 'Parked Call' key on the sidecar that could old these calls somehow? Is there an easier way that would actively mimic their old PBX more directly (where 'Line 1' was actually 'Line 1' everywhere).
That feature called call parking and it already present in most asterisk system
Or maybe you are reffering to call pickup(*8) - if so you have put same pickupgroup on all extensions.
Unfortanly no way say which system you have and how to enable it on your system.

How can I make a 'trial version' of a matlab GUI

My aim is to make a GUI, then by using deploytool to make an exe file from it.
Since I don't want the user to be able to use it for ever I want to make it as a trial version meaning that it will work only for a certain time.
I thought maybe by somehow connecting to the user's computer clock and date, and using the code for a time limit, but I found some problems it this logic.
Any ideas, how it can be done?
Using the computer's clock seems a reasonable way to go. Sure, the user than thwart that by changing the clock, but this will most likely create sufficient inconvenience that they rather pay the reasonable price of the software.
Simply put the following inside the OpeningFcn of your GUI
expiryDate = '2012-12-31';
if now > datenum(expiryDate)
h = errordlg('please upgrade to a full license');
uiwait(h)
return %# or throw an error
end