/*
 * Copyright (C) 2004 Red Hat Inc.
 * Copyright (C) 2005 Martin Koegler
 * Copyright (C) 2010 TigerVNC Team
 * Copyright (C) 2015-2026 m-privacy GmbH
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */

#ifndef __S_SECURITY_MULTI_H__
#define __S_SECURITY_MULTI_H__

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define FLAG_FILE "/tmp/print_signal_allowed"
#define PULSEAUDIO_UNIX_SOCKET "/tmp/.vncpasocket"
#define INITIALURL_FILE "/tmp/.initialurl"

#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#endif

#include <rdr/types.h>
#include <rfb/SSecurity.h>
#include <rfb/SSecurityVeNCrypt.h>
#include <rfb/Timer.h>
#include <rdr/mutex.h>
#include <rdr/MultiInStream.h>
#include <rdr/MultiOutStream.h>
#include <rfb/SWebcamHandler.h>

#if defined(__APPLE__)
#include </usr/SDK/MacOSX10.15.sdk/usr/include/c++/v1/math.h>
#include </usr/SDK/MacOSX10.15.sdk/usr/include/c++/v1/cmath>
#include </usr/SDK/MacOSX10.15.sdk/usr/include/c++/v1/queue>
#include </usr/SDK/MacOSX10.15.sdk/usr/include/c++/v1/unordered_map>
#else
#include <math.h>
#include <cmath>
#include <queue>
#include <unordered_map>
#endif

#define MAXPABUFFERSIZE (10 * 1024 * 1024)

namespace rfb {

	typedef std::unordered_map<rdr::U32, int> handleToSocketMap_t;
	typedef std::unordered_map<int, rdr::U8 *> bufferMap_t;
	typedef std::unordered_map<int, int> bufferLenMap_t;

	class SSecurityMulti : public SSecurity, public Timer::Callback {
	public:
		SSecurityMulti(SConnection* sc);
		virtual ~SSecurityMulti();
		virtual bool processMsg();
		virtual const char* getUserName() const {
			return 0;
		}
		virtual unsigned int getType() const {
			return secTypeMulti;
		}
		virtual void postAuth();
		virtual void setClientSupportsSound(bool value);
		virtual void setClientSupportsPrint(bool value);

		static THREAD_FUNC paListenerThread(void* param);
		static THREAD_FUNC paReadThread(void* param);
		static THREAD_ID paListenerThreadId;

		/*
		 * Refactored sendPdf to be able to send any file (e.g. for autotransfer)
		 *
		 * The original sendPdf only sent the filename.
		 * We are going to send the whole path in case we want to send subfolders at some point.
		 * The client will be able to decide what it wants to do with this path.
		 *
		 * The 'sendOnlyFilename' parameter is there to be able to use the client as is for the
		 * sendPdf function (the client side expects only a filename).
		 * protocol: this parameter was always 1 for printing. Nobody knows what this is for anymore. From now own, we'll use it to have different protocols (for only one STREAM_ID used to send files). It is set to 1 as default if it is not explicitely set while calling the function. It can be used to have different callbacks for every protocol (like 'print temp file' or 'move temp file to the user's autotransfer folder'). We are defining PRINT_PROTOCOL_V1 and AUTOTRANSFER_PROTOCOL_V1 for now.
		 */
		static void* sendFile(const char* path, rdr::U8 streamId, const unsigned int protocol, bool sendOnlyFilename);

		bool sendSignal(rdr::U16 sigId, const void* data = NULL, rdr::U16 dataLength = 0);

		static rdr::U32 lastPaHandle;
		static handleToSocketMap_t handleToSocketMap;
		static bufferMap_t paBufferMap;
		static bufferLenMap_t paBufferLenMap;

	protected:
		bool handleTimeout(Timer * t);
		Timer keepAliveTimer;
		Timer frameRateResetTimer;

	private:
		static void* pulseaudioListener(void* myself);
		static void* sendPdf(void* pdfFileName);

		static void* sendPdfThread(void*);
		int readPaData(int sock);
		static bool incomingPaCallback(const rdr::U8* buf, int bufLen);
		static bool incomingSignalCallback(const rdr::U8* buf, int bufLen);
		static bool incomingWebcamFfmpegCallback(const rdr::U8* buf, int bufLen);
		static bool incomingOldWebcamFfmpegCallback(const rdr::U8* buf, int bufLen);
		static void usr2SignalHandler(int sig);
		void deleteAllPdfs();

		static bool sendPdfThreadRunning;
		static bool sendPdfThreadRunAgain;
		int type;
		static int paInSocket;
#ifndef WIN32
		struct sockaddr_un paInSockaddr;
#else
		struct sockaddr_in paInSockaddr;
#endif
		static fd_set activeFdSet;
		static MUTEX_TYPE mapLock;
	};

}

#endif
