Click here to Skip to main content
15,885,365 members
Articles / Programming Languages / C++

Implementation of the Licensing System for a Software Product

,
Rate me:
Please Sign up or sign in to vote.
4.80/5 (47 votes)
5 Aug 2010CPOL6 min read 160.5K   14.1K   254  
This article is devoted to the development of the key licensing system for the applications.
#ifndef CRYPTOPP_WAIT_H
#define CRYPTOPP_WAIT_H

#include "config.h"

#ifdef SOCKETS_AVAILABLE

#include "misc.h"
#include "cryptlib.h"
#include <vector>

#ifdef USE_WINDOWS_STYLE_SOCKETS
#include <winsock2.h>
#else
#include <sys/types.h>
#endif

#include "hrtimer.h"

NAMESPACE_BEGIN(CryptoPP)

class Tracer
{
public:
	Tracer(unsigned int level) : m_level(level) {}
	virtual ~Tracer() {}

protected:
	//! Override this in your most-derived tracer to do the actual tracing.
	virtual void Trace(unsigned int n, std::string const& s) = 0;

	/*! By default, tracers will decide which trace messages to trace according to a trace level
		mechanism. If your most-derived tracer uses a different mechanism, override this to
		return false. If this method returns false, the default TraceXxxx(void) methods will all
		return 0 and must be overridden explicitly by your tracer for trace messages you want. */
	virtual bool UsingDefaults() const { return true; }

protected:
	unsigned int m_level;

	void TraceIf(unsigned int n, std::string const&s)
		{ if (n) Trace(n, s); }

	/*! Returns nr if, according to the default log settings mechanism (using log levels),
	    the message should be traced. Returns 0 if the default trace level mechanism is not
		in use, or if it is in use but the event should not be traced. Provided as a utility
		method for easier and shorter coding of default TraceXxxx(void) implementations. */
	unsigned int Tracing(unsigned int nr, unsigned int minLevel) const
		{ return (UsingDefaults() && m_level >= minLevel) ? nr : 0; }
};

// Your Tracer-derived class should inherit as virtual public from Tracer or another
// Tracer-derived class, and should pass the log level in its constructor. You can use the
// following methods to begin and end your Tracer definition.

// This constructor macro initializes Tracer directly even if not derived directly from it;
// this is intended, virtual base classes are always initialized by the most derived class.
#define CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) \
	public: DERIVED(unsigned int level = 0) : Tracer(level) {}

#define CRYPTOPP_BEGIN_TRACER_CLASS_1(DERIVED, BASE1) \
	class DERIVED : virtual public BASE1 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)

#define CRYPTOPP_BEGIN_TRACER_CLASS_2(DERIVED, BASE1, BASE2) \
	class DERIVED : virtual public BASE1, virtual public BASE2 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)

#define CRYPTOPP_END_TRACER_CLASS };

// In your Tracer-derived class, you should define a globally unique event number for each
// new event defined. This can be done using the following macros.

#define CRYPTOPP_BEGIN_TRACER_EVENTS(UNIQUENR)	enum { EVENTBASE = UNIQUENR,
#define CRYPTOPP_TRACER_EVENT(EVENTNAME)				EventNr_##EVENTNAME,
#define CRYPTOPP_END_TRACER_EVENTS				};

// In your own Tracer-derived class, you must define two methods per new trace event type:
// - unsigned int TraceXxxx() const
//   Your default implementation of this method should return the event number if according
//   to the default trace level system the event should be traced, or 0 if it should not.
// - void TraceXxxx(string const& s)
//   This method should call TraceIf(TraceXxxx(), s); to do the tracing.
// For your convenience, a macro to define these two types of methods are defined below.
// If you use this macro, you should also use the TRACER_EVENTS macros above to associate
// event names with numbers.

#define CRYPTOPP_TRACER_EVENT_METHODS(EVENTNAME, LOGLEVEL) \
	virtual unsigned int Trace##EVENTNAME() const { return Tracing(EventNr_##EVENTNAME, LOGLEVEL); } \
	virtual void Trace##EVENTNAME(std::string const& s) { TraceIf(Trace##EVENTNAME(), s); }


/*! A simple unidirectional linked list with m_prev == 0 to indicate the final entry.
    The aim of this implementation is to provide a very lightweight and practical
	tracing mechanism with a low performance impact. Functions and methods supporting
	this call-stack mechanism would take a parameter of the form "CallStack const& callStack",
	and would pass this parameter to subsequent functions they call using the construct:

	SubFunc(arg1, arg2, CallStack("my func at place such and such", &callStack));
	
	The advantage of this approach is that it is easy to use and should be very efficient,
	involving no allocation from the heap, just a linked list of stack objects containing
	pointers to static ASCIIZ strings (or possibly additional but simple data if derived). */
class CallStack
{
public:
	CallStack(char const* i, CallStack const* p) : m_info(i), m_prev(p) {}
	CallStack const* Prev() const { return m_prev; }
	virtual std::string Format() const;

protected:
	char const* m_info;
	CallStack const* m_prev;
};

/*! An extended CallStack entry type with an additional numeric parameter. */
class CallStackWithNr : public CallStack
{
public:
	CallStackWithNr(char const* i, word32 n, CallStack const* p) : CallStack(i, p), m_nr(n) {}
	std::string Format() const;

protected:
	word32 m_nr;
};

/*! An extended CallStack entry type with an additional string parameter. */
class CallStackWithStr : public CallStack
{
public:
	CallStackWithStr(char const* i, char const* z, CallStack const* p) : CallStack(i, p), m_z(z) {}
	std::string Format() const;

protected:
	char const* m_z;
};

CRYPTOPP_BEGIN_TRACER_CLASS_1(WaitObjectsTracer, Tracer)
	CRYPTOPP_BEGIN_TRACER_EVENTS(0x48752841)
		CRYPTOPP_TRACER_EVENT(NoWaitLoop)
	CRYPTOPP_END_TRACER_EVENTS
	CRYPTOPP_TRACER_EVENT_METHODS(NoWaitLoop, 1)
CRYPTOPP_END_TRACER_CLASS

struct WaitingThreadData;

//! container of wait objects
class WaitObjectContainer : public NotCopyable
{
public:
	//! exception thrown by WaitObjectContainer
	class Err : public Exception
	{
	public:
		Err(const std::string& s) : Exception(IO_ERROR, s) {}
	};

	static unsigned int MaxWaitObjects();

	WaitObjectContainer(WaitObjectsTracer* tracer = 0);

	void Clear();
	void SetNoWait(CallStack const& callStack);
	void ScheduleEvent(double milliseconds, CallStack const& callStack);
	// returns false if timed out
	bool Wait(unsigned long milliseconds);

#ifdef USE_WINDOWS_STYLE_SOCKETS
	~WaitObjectContainer();
	void AddHandle(HANDLE handle, CallStack const& callStack);
#else
	void AddReadFd(int fd, CallStack const& callStack);
	void AddWriteFd(int fd, CallStack const& callStack);
#endif

private:
	WaitObjectsTracer* m_tracer;

#ifdef USE_WINDOWS_STYLE_SOCKETS
	void CreateThreads(unsigned int count);
	std::vector<HANDLE> m_handles;
	std::vector<WaitingThreadData *> m_threads;
	HANDLE m_startWaiting;
	HANDLE m_stopWaiting;
#else
	fd_set m_readfds, m_writefds;
	int m_maxFd;
#endif
	bool m_noWait;
	double m_firstEventTime;
	Timer m_eventTimer;

#ifdef USE_WINDOWS_STYLE_SOCKETS
	typedef size_t LastResultType;
#else
	typedef int LastResultType;
#endif
	enum { LASTRESULT_NOWAIT = -1, LASTRESULT_SCHEDULED = -2, LASTRESULT_TIMEOUT = -3 };
	LastResultType m_lastResult;
	unsigned int m_sameResultCount;
	Timer m_noWaitTimer;
	void SetLastResult(LastResultType result);
	void DetectNoWait(LastResultType result, CallStack const& callStack);
};

NAMESPACE_END

#endif

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Technical Lead Apriorit Inc.
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions