// wmsoaplistener.h: interface for the wmsoaplistener class.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// WMSOAPListener class - a class for HTTP protocol support.
// Uses Winsock2, supports HTTP Version 1.0.
// 
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WMSOAPLISTENER_H__DF6A4CFB_2B16_411B_AD9C_A2D7DD0151D8__INCLUDED_)
#define AFX_WMSOAPLISTENER_H__DF6A4CFB_2B16_411B_AD9C_A2D7DD0151D8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "WMLogMgr.h"
#include "WMSOAPBindingHandlers.h"
#include "WMWSDLParser.h"

// version of Winsock we need 
#define VERSION_MAJOR         2 
#define VERSION_MINOR         0 
 
// listening socket stuff
typedef struct tagLISTENSOCK
{
	SOCKET hSocket;
	LPWSAPROTOCOL_INFO ProtoInfo;
} LISTENSOCK, *PLISTENSOCK;

typedef struct tagWSDLCacheEntry
{
	DWORD dwTickCount;
	IDispatch *pIWSDLParser;
} WSDLCacheEntry;


class SOAPSvcDesc
{
public:

    SOAPSvcDesc(const string& strReqURI,
                const string& strWsdlDocURL,
                const wstring& wstrWsdlSvc,
                const wstring& wstrWsdlPort,
                const wstring& wstrBodyProc,
                const wstring& wstrNextHopURL,
                list<wstring>& listRoles,
                const wstring& wstrNodeURI,
                bool bEnabled,
                bool bExplicitTypingEnabled,
                bool bNodeTypeEnabled,
                bool bExtraPathEnabled,
                list<wstring>& listHeaderProcs,
                bool bLoopbackEnabled) :    m_strReqURI(strReqURI),
                                            m_strWsdlDocURL(strWsdlDocURL),
                                            m_wstrWsdlSvc(wstrWsdlSvc),
                                            m_wstrWsdlPort(wstrWsdlPort),
                                            m_wstrBodyProcProgId(wstrBodyProc),
                                            m_wstrNextHopURL(wstrNextHopURL),
                                            m_listRoles(listRoles),
                                            m_wstrNodeURI(wstrNodeURI),
                                            m_bEnabled(bEnabled),
                                            m_bExplicitTypingEnabled(bExplicitTypingEnabled),
                                            m_bNodeTypeEnabled(bNodeTypeEnabled),
                                            m_bExtraPathEnabled(bExtraPathEnabled),
                                            m_listHeaderProcProgIds(listHeaderProcs),
                                            m_bLoopbackEnabled(bLoopbackEnabled)
    {}
    string          m_strReqURI;
    string          m_strWsdlDocURL;
    wstring         m_wstrWsdlSvc;
    wstring         m_wstrWsdlPort;
    wstring         m_wstrBodyProcProgId;
    list<wstring>   m_listHeaderProcProgIds;
    wstring         m_wstrNextHopURL;
    list<wstring>   m_listRoles;
    wstring         m_wstrNodeURI;
    bool            m_bEnabled;
    bool            m_bExtraPathEnabled;
    bool            m_bLoopbackEnabled;
    bool            m_bExplicitTypingEnabled;
    bool            m_bNodeTypeEnabled;
};

#define MAX_LISTENING_SOCKETS 4

class WMSOAPClientConn;

// the class
class WMSOAPListener  
{
public:
	WMSOAPListener();
	virtual ~WMSOAPListener();

	BOOL  Start();
	void  Stop();
	void  OnAccept(DWORD dwIndex);
	// client queue
	ULONG DeQueueClient();
	void  ReQueueClient(ULONG uIndex);
	BOOL  IsClientAvail();
	// client watchdog timer handler
	void  OnWatchdogTimer();
	// stats
	void  UpdateNumBytesSent(DWORD dwNumBytes);
	DWORD GetNumBytesSent();
	void  IncNumHTTPErrors();
	DWORD GetNumHTTPErrors();
	void  IncNumInternalErrors();
	DWORD GetNumInternalErrors();
	void  IncNumNetworkErrors();
	DWORD GetNumNetworkErrors();
	DWORD GetNumConnectTotal();
	// server settings
	int   GetListenPort();
	void  SetListenPort(int nPort);
	int   GetNumWorkThreads();
	void  SetNumWorkThreads(int nNumThreads);
	int   GetNumClientConn();
	void  SetNumClientConn(int nNumClients);
	int   GetClientTimeout();
	void  SetClientTimeout(int nNumSecs);
	ULONG GetWatchdogTimer();
	void  SetWatchdogTimer(ULONG uNumSecs);
	// configuration settings read/write
	BOOL  LoadSettings();
	void  StoreSettings();

protected:
	// Implementation
	BOOL InitWinsock2();
	BOOL GetAvailProtocols();
	BOOL StartListening();

public:
	// protocols
	LPWSAPROTOCOL_INFO m_pAvailProtocols;
	int		        m_nNumProtocols;
	// listening sockets
    string          m_strBindAddress;
	int		        m_nPort;
	int		        m_nNumListeningSockets;
	LISTENSOCK      m_ListeningSockets[MAX_LISTENING_SOCKETS];
	HANDLE          m_hListenEventObj[MAX_LISTENING_SOCKETS];
	// concurrency
	int		        m_nNumWorkThreads;
	HANDLE	        m_hCompletionPort;
	// clients
	int		        m_nNumClients;
	int		        m_nClientTimeout;
	deque<ULONG>    m_dequeClients;
	vector<WMSOAPClientConn *> m_arrClients;
	// logging
	WMLogMgr        m_LogMgr;
	// watchdog timer
	UINT_PTR	    m_uWatchDogTimerID;
	UINT	        m_uWatchDogTimerInterval;
	// counters
	DWORD	        m_dwNumConnections;
	DWORD	        m_dwNumConnectTotal;
	DWORD	        m_dwNumBytesSent;
	DWORD	        m_dwNumHTTPErrors;
	DWORD	        m_dwNumInternalErrors;
	DWORD	        m_dwNumNetworkErrors;
	// thread synchronization
	CRITICAL_SECTION m_CSClients;
	CRITICAL_SECTION m_CSProperties;
	// document defaults
	string	        m_strDocBasePath;  // root path for document files
	string	        m_strDocDefault;  // default HTML file
	// SOAP Services map
	map<string, SOAPSvcDesc *> m_mapSOAPSvcDescriptions;
	// MIME type map
	map<string, string> m_mapMIMETypes;
	// WSDL file cache
	int		        m_nWSDLFileCacheSize;
	unsigned int	m_uLastTickCount;
	bool	        m_bFlushWSDLCache;
	map<string, WSDLCacheEntry *>	m_mapWSDLCacheEntries;
	IDispatch *FindWSDLCacheEntry(const string& strWSDLFileURL);
	bool AddWSDLCacheEntry(const string& strWSDLFileURL,
							IDispatch *pIWSDLParser);
	void FlushWSDLCache();
	void SetFlushWSDLCacheFlag();
	// misc
    string          m_strConfigFilePath;
	string	        m_strListenerName;
	bool	        m_bResolveClientname;
};

#define WATCHDOG_TIMER_ID 999

typedef unsigned (__stdcall *PTHREAD_START) (void *);

#define BEGINTHREADEX(psa, cbStack, pfnStartAddr,    \
     pvParam, fdwCreate, pdwThreadID)                \
       ((HANDLE) _beginthreadex(                     \
          (void *) (psa),                            \
          (unsigned) (cbStack),                      \
          (PTHREAD_START) (pfnStartAddr),            \
          (void *) (pvParam),                        \
          (unsigned) (fdwCreate),                    \
          (unsigned *) (pdwThreadID))) 

#endif // !defined(AFX_WMSOAPLISTENER_H__DF6A4CFB_2B16_411B_AD9C_A2D7DD0151D8__INCLUDED_)
