

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.1.1.260726 (26 July 2026)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2026
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//#include <stdio.h>
//#include <string.h>
//#include <iostream>

/*! @file PsySSL.h
	@brief Minimal OpenSSL-based TLS server helpers for the CMSDK.

	Only compiled with real content when @c _USE_SSL_ is defined (requires linking
	against OpenSSL); otherwise only the TestSSL() stub declaration remains.
	Provides two small wrappers: PsySSLServer (context + certificate loading) and
	SSLServer (a select()-based accept loop dispatching each client connection to a
	pthread worker function).

	@note Platform: the socket/select usage follows the BSD API; on Windows the
	equivalent Winsock calls are used via the CMSDK utils layer. OpenSSL headers
	are only included inside the @c _USE_SSL_ branch.
	@warning The trailing include-guard comments in this header are misleading:
	the final `#endif` closes the include guard, not `_USE_SSL_` (see source).
*/
#ifndef __SSL_SERVER_H__
#define __SSL_SERVER_H__

#include "Utils.h"

namespace	cmlabs{

/*! Standalone smoke test for the SSL server functionality.
	@param port TCP port to listen on for the test.
	@return 0 on success, non-zero on failure. Blocking call.
*/
int TestSSL(int port);

#ifdef _USE_SSL_
	#include <openssl/ssl.h>
	#include <openssl/err.h>

/*! @brief Thin wrapper owning an OpenSSL context and certificate/key pair.

	Only available when compiled with @c _USE_SSL_. Create, then call init() with
	PEM certificate and private-key files before using the context.
*/
class PsySSLServer {
public:
	/*! Construct with no context; call init() next. */
	PsySSLServer();
	/*! Destructor; frees the SSL context/session if created. */
	~PsySSLServer();

	/*! Initialise the SSL context and load certificates.
		@param cFile Path to the PEM certificate file.
		@param kFile Path to the PEM private-key file.
		@return true if the context was created and the certificate/key pair loaded and verified.
	*/
	bool init(char *cFile, char *kFile);

private:
	SSL_CTX *ctx; //!< OpenSSL context (owned).
	SSL *ssl;     //!< Current SSL session handle (owned).

	void CreateCTX(void);                   //!< Load algorithms and create the SSL_CTX.
	void LoadCerts(char *cFile, char *kFile); //!< Load and verify the certificate/key pair.
};


using namespace std;

/*! Worker-thread function signature: receives the per-client argument, returns void*. */
typedef void *(*P_ARG)(void *);

/*! @brief select()-based TLS accept server dispatching each client to a pthread.

	Construct with certificate, key and port; then call CheckClients() regularly
	from the application main loop. Each accepted connection is handed to the
	thread function set via SetPthread_F(). Only available with @c _USE_SSL_.
*/
class SSLServer {
  // Private data
  private:
    SSL_CTX *ctx;
    int PORT;
    fd_set fdset;
    // FD for server
    int master;
    // Thread function
    P_ARG pthr_f;

  // Private Functions
  private:
    // Load algorithms and create context.
    void CreateCTX(void);
    // Load certification files.
    void LoadCerts(const char *cFile, const char *kFile);
    // Create and attach socket.
    void BindPort(void);

  public:
    /*! Set the worker function each accepted client connection is dispatched to.
		@param fp Thread function receiving the connection context.
	*/
    void SetPthread_F(P_ARG fp) { pthr_f = fp; }

    /*! Create the server: build the SSL context, load certificates and bind/listen on @a port.
		@param cFile Path to the PEM certificate file.
		@param kFile Path to the PEM private-key file.
		@param port TCP port to listen on.
	*/
    SSLServer(const char *cFile, const char *kFile, int port);

    /*! Poll for new client connections.

		Blocks in select() for up to @a wait_t seconds; if a connection is pending it
		is accepted, the TLS handshake performed, and a worker thread started via the
		function set with SetPthread_F(). Must be called regularly from the
		application's main loop.
		@param wait_t Maximum seconds to block waiting for a connection (0 = return immediately).
	*/
    void CheckClients(int wait_t = 0);
};

#endif

}

#endif // _USE_SSL_
