Click here to Skip to main content
15,888,521 members
Articles / Desktop Programming / MFC

The Ultimate TCP/IP Home Page

Rate me:
Please Sign up or sign in to vote.
4.98/5 (77 votes)
25 Aug 2007CPOL13 min read 2.6M   45.4K   267  
Ultimate TCP-IP is now Open Source
// =================================================================
//  class: CUT_WSThread
//  class: CUT_WSServer
//  struct:UT_THREADLIST
//  struct:UT_THREADINFO
//  File:  Ut_Srvr.h
//
//  Purpose:
//
//  Class declarations of the server and thread base classes 
//  for the server framework.
//       
// ===================================================================
// Ultimate TCP/IP v4.2
// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// ===================================================================

#ifndef IncludeCUT_WSServer //make sure this class is only included once
#define IncludeCUT_WSServer
#pragma warning(disable:4245) /* the extern before template is a non-standard extension */
#include "UTDataSource.h"
#include "UTErr.h"
#include "ut_clnt.h"


     
//#pragma warning (disable :4239)
// =========================================================
//          WINSOCK LIBRARY & HEADER
#ifndef _WINSOCK_2_0_
    // WINSOCK 1.1
    // When you you want to include winsock 1,1
    // the you need to link or load winsock.lib 
    // (for 16 bit apps)  or wsock32.lib ( 32 bit apps)
    #pragma comment(lib, "wsock32.lib")
    #include <winsock.h>        //use for Winsock v1.x
    #define WINSOCKVER  MAKEWORD(1,1)
#else
    // WINSOCK 2.0
    // When you you want to include winsock 2.0
    // the you need to link or load ws2_32.lib 
    // (There is only a 32 bit version of it )
    #pragma comment(lib, "ws2_32.lib")
    #include <winsock2.h>     //use for Winsock v2.x
    #define WINSOCKVER    MAKEWORD(2,0)
#endif

//blocking defines
#ifndef CUT_BLOCKING
#define CUT_BLOCKING        0
#define CUT_NONBLOCKING     1
#endif
/*
//success/error  define
#define CUT_SUCCESS 0
#define CUT_ERROR   1
*/
#define	WSS_BUFFER_SIZE				256
#define	WSS_LINE_BUFFER_SIZE		1000

//classes
class CUT_WSServer;
class CUT_WSThread;

// Define base class for the server
#ifndef CUT_SERVER_BASE_CLASS
	#ifdef CUT_SECURE_SOCKET
		#include "..\Security\Include\UTSecureSocket.h"
		#define CUT_SERVER_BASE_CLASS	CUT_SecureSocketServer
	#else
		#define CUT_SERVER_BASE_CLASS	CUT_Socket
	#endif
#else
	#include "CustomSocket.h"
#endif


	// in order to allow the developer access to overiding the implementation 
	// of the Access control object 
	// we will check for a define MY_UT_ACCESS_CONTROL_CLASS
	// if this macro is not defined 
	// then we will inherit from the default access control class
#ifndef CUT_ACCESSCONTROL_BASE_CLASS
	#include "UT_AccessControl.h"
	#define	CUT_ACCESSCONTROL_BASE_CLASS 	CUT_AccessControl
#else
	// if the user developer elected to provide his/her own implementation of the access control object
	// we must include the defenition of the new class
	// this is done by 
	//first defining a constant that will contain the name of the header file	
	#include MYACCESS_CONTROL_HEADER
	// second we will inherit use the identifier of the class provided by the developer
	// YOU MUST define MY_UT_ACCESS_CONTROL_CLASS_BASE as the identifier of the new class
#endif //MY_UT_ACCESS_CONTROL_CLASS


/***************************************
CUT_WSThread
    Thread class, this class is created
    by the server class when a new connection
    comes in
****************************************/
class CUT_WSThread : public CUT_SERVER_BASE_CLASS
{

friend CUT_WSServer;

    public:

        SOCKET          m_clientSocket;			// Client socket
        SOCKADDR_IN     m_clientSocketAddr;		// Client socket address
        SOCKET          m_serverSocket;			// Server socket
        CUT_WSServer *  m_winsockclass_this;	// Pointer to the WinSock server class
        BOOLEAN         m_bIsUDP;				// Is UDP flag
		BOOLEAN         m_bBlockingMode;		// Blocking mode flag
        long            m_lReceiveTimeOut;		// Receive time-out
        long            m_lSendTimeOut;			// Send tie-out
        int             m_nShutDownFlag;		// Shut down flag
		int				m_nSockType;

		char			m_szAddress[32];

    public:
	    void SetSecurityAttrib(CUT_WSServer * wss, CUT_WSThread  *wst);
        
		// Contructors/Destructors
        CUT_WSThread();
        virtual ~CUT_WSThread();

	
		// Starts shutdown
        int		StartShutdown();
        
        // Get/Set blocking mode
        int		SetBlockingMode(int mode);
		BOOL	GetBlockingMode() const;

        // Set/Get Send time out
        int		SetSendTimeOut(long miliSecs);
		long	GetSendTimeOut() const;

		// Set/Get Receive time out
        int		SetReceiveTimeOut(long miliSecs);
		long	GetReceiveTimeOut() const;
        
		// Set/Get Socket options
        int		SetSocketOption(int option,void *optionValue, int iBufferSize = 4); // NOTE: no implementation for this function exists 
        int		GetSocketOption(int option,void *optionValue); // NOTE: no implementation for this function exists 

        // Address functions
        int     GetClientName(LPSTR name,int maxLen);
        int     GetClientAddress(LPSTR address,int maxLen);
        LPCSTR  GetClientAddress();
        int     GetNameFromAddress(LPCSTR address,LPSTR name,int maxLen);
        int     GetAddressFromName(LPCSTR name,LPSTR address,int maxLen);

        // Send functions
        virtual int     Send(CUT_DataSource & source, long *bytesSent);
        virtual int     Send(LPCSTR data, int len = -1,int flags = 0);
        virtual int     SendBlob(LPBYTE data,int dataLen,int flags = 0);
        virtual long    SendAsLine(LPCSTR data, long len, int lineLen);
        virtual int     SendFile(LPCTSTR path, long *bytesSent);
        int     GetMaxSend() const;
        int     SetMaxSend(int length);
        int     WaitForSend(long secs,long uSecs);

        // Receive functions
		virtual int		Receive(CUT_DataSource & dest, long* bytesReceived, OpenMsgType type, int timeOut = 0);
        virtual int     Receive(LPSTR data,int maxDataLen,int timeOut = 0);
        virtual int     ReceiveBlob(LPBYTE data,int dataLen,int timeOut = 0);
        virtual int     ReceiveToFile(LPCTSTR name, OpenMsgType type,long* bytesReceived,int timeOut = 0);
        virtual int     ReceiveLine(LPSTR data,int maxDataLen,int timeOut = 0);
		int     WaitForReceive(long secs,long uSecs);
        BOOL    IsDataWaiting() const;
        int     ClearReceiveBuffer();
        int     GetMaxReceive() const;
        int     SetMaxReceive(int length);
        
        // Error functions
        DWORD   GetLastError();        // NOTE: no implementation for this function exists 
        LPCSTR  GetLastErrorString();  // NOTE: no implementation for this function exists 

        // Connection
        BOOL	IsConnected();


		// Added to support connection in thread class
		// Connect. default type is TCP Stream, and family AF_INET
		virtual int Connect(unsigned int port, LPCSTR address, long timeout = -1, 
        int family = AF_INET, int sockType = SOCK_STREAM);


		// Terminate current connection 
		virtual int CloseConnection();
  


protected:        

		/////////////////////////////////////////////////////////////
        // Overridables
        /////////////////////////////////////////////////////////////
        
        virtual void OnConnect();
        virtual void OnMaxConnect();
        virtual void OnUnAuthorizedConnect();

        // Send and receive file status
        virtual int ReceiveFileStatus(long BytesReceived);
        virtual int SendFileStatus(long BytesSent);

		// This virtual function is called each time we return a value
		virtual int OnError(int error);

#ifdef CUT_SECURE_SOCKET
		
		// Function can be overwritten to handle security errors
		virtual void HandleSecurityError(char *lpszErrorDescription);

#endif // #ifdef CUT_SECURE_SOCKET

// v4.2 removed these to get rid of warnings for derived classes (VC6)
//private:
//	CUT_WSThread& operator=(const CUT_WSThread&); // no implementation
//	CUT_WSThread(const CUT_WSThread&); // no implementation
};


/**********************************
CUT_WSServer
    Main server class, this class 
    listens for connections then spins
    off threads for each connection
***********************************/
class CUT_WSServer : public CUT_SERVER_BASE_CLASS
{

    /**********************************
    UT_THREADLIST
        Structure for storing the list of
        open connections
    ***********************************/
    typedef struct UT_THREADLISTtag{
        CUT_WSThread		*WSThread;				// Pointer to the thread class
        DWORD				ThreadID;				// Thread ID
        SOCKET				cs;						// Thread socket
        UT_THREADLISTtag	*prev;					// Pointer to the previous item
        UT_THREADLISTtag	*next;					// Pointer to the next item
    }UT_THREADLIST;

    /**********************************
    UT_THREADINFO
        structure for passing informtion
        from the server to the connect 
        thread
    ***********************************/
    typedef struct UT_THREADINFOTag{
        SOCKET				cs;						// Client socket
        SOCKET				ss;						// Server socket
        SOCKADDR_IN			csAddr;					// Client socket address
        int					MaxConnectionFlag;		// Max connection flag
        CUT_WSServer		*winsockclass_this;		// Pointer to the Server class
    }UT_THREADINFO;


friend CUT_WSThread;

    protected:

        WSADATA			m_wsaData;				// Server socket information
        SOCKADDR_IN		m_serverSockAddr;		// Server socket address
        SOCKET			m_serverSocket;			// Server socket

        UT_THREADLIST	*m_ptrThreadList;		// Pointer to the start of the thread list

        DWORD			m_dwAcceptThread;		// Thread ID of accept function
        int				m_nAcceptFlag;			// Accept in progress flag
        int				m_nShutDownAccept;		// Shutdown accept flag

        int				m_nMaxConnections;		// Max. connections number
        int				m_nNumConnections;		// Connection counters

        int				m_nProtocol;			// Protocol type 
        unsigned short	m_nPort;				// Port connected to
		BOOL			m_bShutDown;			// Server shutdown flag
		BOOL			m_bCloseSocket;			// Close socket when thread is done

		CRITICAL_SECTION	 m_criticalSection;		// Critical section variables
	


	protected:
    
		///////////////////////////////
		// Thread list functions
		///////////////////////////////

		// Add thread to the list
        int		ThreadListAdd(CUT_WSThread* WSThread,DWORD ThreadID,SOCKET cs);

		// Remove thread from list
        int		ThreadListRemove(DWORD ThreadID);

		// Get num threads in list
        int		ThreadListGetLength();

		// Suspend threads
        int		ThreadListSuspend();                        

		// Resume suspended threads
        int		ThreadListResume();                     

		// Kill all and remove
        int		ThreadListKill();                           


        // Accept connection thread
        static void AcceptConnections(void *_this);

        static void ThreadEntry(void *ptr);

    public:
	  
        // Contructors/Destructors
        CUT_WSServer();
        virtual ~CUT_WSServer();

        // Set up the port to connect to
        virtual int		ConnectToPort(unsigned short port, int queSize = 5, short family = AF_INET, unsigned long address = htonl(INADDR_ANY));
        int		TempConnect(unsigned int Port, LPSTR Address);

		// Set/Get connect port
		int				SetPort(unsigned short newPort);
		unsigned int	GetPort() const;

		// Set/Get protocol
        int		SetProtocol(int protocol);
		int		GetProtocol() const;

		// Set/Get maximum connection number
        int		SetMaxConnections(int max);
        int		GetMaxConnections() const;

        // Start and stop accepting connections
        int		StartAccept();
        int		StopAccept();

        // Retrieves the current number of connections
        int		GetNumConnections() const;

		// Set/Get shutdown flag
        void	SetShutDownFlag(BOOL newVal);
		BOOL	GetShutDownFlag() const;
		CUT_ACCESSCONTROL_BASE_CLASS	 m_aclObj;			// Access Control object to manage blocked IP list 

		// added for v4.2 - winsock equivalent takes only char
		static unsigned long Inet_Addr(LPCSTR string);
#if defined _UNICODE
		static unsigned long Inet_Addr(LPCWSTR string);
#endif // _UNICODE

   

protected:        
        /////////////////////////////////////////////////////////////
        // Overridables
        /////////////////////////////////////////////////////////////

        // Pause and resume
        virtual int Pause();        //pause all threads, including the accept thread
        virtual int Resume();       //resume all threads,     "      "   "      "

        // Create class instance callback, this is where a C_WSTHREAD clss is created
        virtual CUT_WSThread* CreateInstance() = 0;
        
        // This function is called so that the instance created above can be released
        virtual void ReleaseInstance(CUT_WSThread * ptr) = 0;

        // Called for every socket trying to connect
        virtual long OnCanAccept(LPCSTR address);

		// This virtual function is called each time we have any
		// status information to display.
		virtual int OnStatus(LPCTSTR StatusText);
#if defined _UNICODE
		virtual int OnStatus(LPCSTR StatusText);
#endif

		// This virtual function is called each time we return a value
		virtual int OnError(int error);

// v4.2 removed these to get rid of warnings for derived classes (VC6)")
//private:
//	CUT_WSServer& operator=(const CUT_WSServer&); // no implementation
//	CUT_WSServer(const CUT_WSServer&); // no implementation
};
#pragma warning(default:4245) /* the extern before template is a non-standard extension */
#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
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions