Click here to Skip to main content
15,892,298 members
Articles / Desktop Programming / Win32

Pipe template classes

Rate me:
Please Sign up or sign in to vote.
4.69/5 (9 votes)
2 Nov 2010MPL12 min read 146.3K   1.9K   33  
A template classes library to support pipe development with minimum programmer effort.
// test_server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "test_server.h"
#include <conio.h>
#include "../utils/typelist.h"
#include "../utils/security.h"
#include "../pipe/server.h"
#include "Messages.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

//CWinApp theApp;

using namespace std;

void run_server();

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		return 0;
	}

	run_server();

	return 0;
}

struct COutput
{
	void operator()(const CString& _str) {cout << (LPCTSTR)_str;}
	void operator()(CPipeMsg_State::StateEn _state) {cout<<to_str(_state);}
	COutput& operator << (const CString& _str) {cout << (LPCTSTR)_str; return *this;}
	COutput& operator << (long _lv) {cout << _lv; return *this;}
	COutput& operator << (LPCTSTR _sz) {cout << _sz; return *this;}
	COutput& operator << (CPipeMsg_State::StateEn _state) {cout<<to_str(_state); return *this;}
	COutput& operator << (const CTime& _time) {cout << (LPCTSTR)_time.Format(_T("%c")); return *this;}
	void endline() {cout << endl;}
	operator CCriticalSection& () {return m_cs;}
protected:
	CCriticalSection m_cs;
};//struct COutput

extern COutput g_output;

struct CClientInfo
{
	CString m_sName;
	CTime m_lastactive;
	CTime m_started;
	CTime m_closed;
	long m_msgcnt;

	CClientInfo(const CString& _sName = _T(""))
		:m_sName(_sName),m_msgcnt(0)
	{
		m_lastactive = m_started = CTime::GetCurrentTime();
	}

	void print_info() const
	{
		g_output << _T("Name :") << m_sName << _T(" started :") << m_started;
		g_output << _T(" state:");
		CTimeSpan ts = CTime::GetCurrentTime() - m_lastactive;
		CTimeSpan maxts(0,0,3,0);
		g_output << (ts>maxts?_T("inactive"):_T("active"));
		g_output << _T(" messages = ") << m_msgcnt;
		g_output.endline();
	}
	bool operator==(const CString& _sName) const {return !m_sName.CompareNoCase(_sName);}
	bool operator==(const CClientInfo& ) const;
	bool operator!=(const CClientInfo& ) const;
	bool operator<(const CClientInfo& ) const;
	bool operator>(const CClientInfo& ) const;
};//struct CClientInfo

struct CStatistics
{
	typedef std::list<CClientInfo> ClientInfoLst;
	void on_state(const CString& _sClientName,CPipeMsg_State::StateEn _state)
	{
		CAutoLock __al(m_cs);

		ClientInfoLst::iterator fit = std::find(m_clients.begin(),m_clients.end(),_sClientName);
		if(EQL(_state,CPipeMsg_State::S_Started))
		{
			if(fit!=m_clients.end()) m_clients.erase(fit);
			m_clients.push_back(CClientInfo(_sClientName));
		}
		else if(EQL(_state,CPipeMsg_State::S_Stoped))
		{
			if(fit!=m_clients.end()) 
			{
				fit->m_closed = CTime::GetCurrentTime();
				m_clients.erase(fit);
			}
		}
		else
		{
			if(fit!=m_clients.end()) 
			{
				fit->m_lastactive = CTime::GetCurrentTime();
			}
		}
	}

	void on_text(const CString& _sClientName)
	{
		CAutoLock __al(m_cs);

		ClientInfoLst::iterator fit = std::find(m_clients.begin(),m_clients.end(),_sClientName);
		if(fit!=m_clients.end()) 
		{
			fit->m_lastactive = CTime::GetCurrentTime();
			fit->m_msgcnt++;
		}
	}

	void print_all()
	{
		CAutoLock __al(m_cs);
		CAutoLock __al1(g_output);	// XXX possible deadlock creating

		g_output << _T("-------------------- Information ----------------------");
		g_output.endline();
		g_output << _T("clients count = ") << m_clients.size();
		g_output.endline();
		ClientInfoLst::const_iterator it,ite;
		it = m_clients.begin();
		ite = m_clients.end();
		for(;it!=ite;++it) it->print_info();
		g_output << _T("-------------------------------------------------------");
		g_output.endline();
	}
protected:
	ClientInfoLst m_clients;
	CCriticalSection m_cs;
};//struct CStatistics


// global variables
COutput g_output;		// synchronized output
CStatistics g_stat;		// statistics

// declare type list of messages to recieve by pipe server

typedef TYPELIST_2(CPipeMsg_State,CPipeMsg_Text) PipeServerMsgsList;

// declare pipe server class

struct CTestPipeServer : public CServerPipeCommImpl<CTestPipeServer,PipeServerMsgsList>
{
	CTestPipeServer(const CString& _sPipeName,CStatistics& _stat)
		:CServerPipeCommImpl<CTestPipeServer,PipeServerMsgsList>(_sPipeName)
		,m_stat(_stat)
	{
		m_psa = &m_sa;
	}

	bool process(CPipeMsg_State* _pstate)
	{
		VERIFY_EXIT1(NOT_NULL(_pstate),false);

		m_stat.on_state(_pstate->get_ClientName(),_pstate->get_state());

		CAutoLock __al(g_output);
		g_output << _T("\"") << _pstate->get_ClientName() << _T("\" state:") <<  _pstate->get_state();
		g_output.endline();
		return true;
	}

	bool process(CPipeMsg_Text* _ptext)
	{
		VERIFY_EXIT1(NOT_NULL(_ptext),false);

		m_stat.on_text(_ptext->get_ClientName());

		CAutoLock __al(g_output);
		g_output << _T("\"") << _ptext->get_ClientName() << _T("\" :") << _ptext->get_Text();
		g_output.endline();
		return true;
	}

	CSecurityAttributes& get_security() {return m_sa;}
protected:
	CSecurityAttributes m_sa;
	CStatistics& m_stat;
};//struct CTestPipeServer

void run_server()
{
	CTestPipeServer* pserver = new CTestPipeServer(_T("TestPipeLib"),g_stat);

	//activate security
	CSid everyone = security::Sids::World();
	CSid owner = security::Sids::Self();

	CDacl dacl;
	dacl.AddDeniedAce(everyone,security::AccessRights_WriteDac);
	dacl.AddAllowedAce(everyone,security::AccessRights_GenericWrite|security::AccessRights_GenericRead);
	dacl.AddAllowedAce(owner,security::AccessRights_GenericAll);

	CSecurityDesc secrdesc;
	secrdesc.SetDacl(dacl);

	pserver->get_security().Set(secrdesc);

	// run pipe server
	pserver->start();

	cout << _T("Type 'q' -- to exit and 'i' -- for inforamtion") << endl;

	char ch = 0;
	while((ch=toupper(getch()))!='Q')
	{
		if(ch=='I')	g_stat.print_all();
	}

	pserver->stop();
	delete pserver;

	cout << _T("pipe server was stoped");
}

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 Mozilla Public License 1.1 (MPL 1.1)


Written By
Software Developer
Belarus Belarus
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions