From 26aa71233c256cd3af027af5dbdcd30329d6e762 Mon Sep 17 00:00:00 2001
From: Ghislain MARY <ghislain.mary@belledonne-communications.com>
Date: Mon, 28 Nov 2016 17:30:25 +0100
Subject: [PATCH] Build linphone-daemon on Windows.

---
 CMakeLists.txt                                |  2 +-
 coreapi/private.h                             |  6 +-
 .../commands/adaptive-jitter-compensation.cc  |  8 +--
 daemon/commands/netsim.cc                     | 10 +--
 daemon/daemon-pipetest.c                      | 50 ++++++++++---
 daemon/daemon.cc                              | 72 +++++++++++++------
 daemon/daemon.h                               |  4 +-
 include/linphone/core_utils.h                 | 34 ++++-----
 8 files changed, 126 insertions(+), 60 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index afc499fe99..7d0dd35d0f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@ option(ENABLE_SHARED "Build shared library." YES)
 option(ENABLE_STATIC "Build static library." YES)
 option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES)
 option(ENABLE_DATE "Use build date in internal version number." NO)
-cmake_dependent_option(ENABLE_DAEMON "Enable the linphone daemon interface." YES "NOT WIN32" NO)
+option(ENABLE_DAEMON "Enable the linphone daemon interface." YES)
 option(ENABLE_DOC "Enable documentation generation with Doxygen." YES)
 option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO)
 option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES)
diff --git a/coreapi/private.h b/coreapi/private.h
index 492d7a56ab..bca1a9a876 100644
--- a/coreapi/private.h
+++ b/coreapi/private.h
@@ -528,7 +528,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
 LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable);
 LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable);
 void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
-void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev);
+LINPHONE_PUBLIC void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev);
 void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *result);
 void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy);
 void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call);
@@ -587,7 +587,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call);
 bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md);
 extern SalCallbacks linphone_sal_callbacks;
 LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc);
-bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc);
+LINPHONE_PUBLIC bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc);
 
 void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description);
 
@@ -1165,7 +1165,7 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
 void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted);
 bool_t linphone_core_sound_resources_available(LinphoneCore *lc);
 void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, LinphoneCall *newcall);
-unsigned int linphone_core_get_audio_features(LinphoneCore *lc);
+LINPHONE_PUBLIC unsigned int linphone_core_get_audio_features(LinphoneCore *lc);
 
 void _linphone_core_codec_config_write(LinphoneCore *lc);
 
diff --git a/daemon/commands/adaptive-jitter-compensation.cc b/daemon/commands/adaptive-jitter-compensation.cc
index 8985a782e5..ecbfd81573 100644
--- a/daemon/commands/adaptive-jitter-compensation.cc
+++ b/daemon/commands/adaptive-jitter-compensation.cc
@@ -40,17 +40,17 @@ AdaptiveBufferCompensationResponse::AdaptiveBufferCompensationResponse(LinphoneC
 	ostringstream ost;
 	switch (type) {
 		case AudioStream:
-			enabled = linphone_core_audio_adaptive_jittcomp_enabled(core);
+			enabled = linphone_core_audio_adaptive_jittcomp_enabled(core) ? true : false;
 			outputAdaptiveBufferCompensation(core, ost, "Audio", enabled);
 			break;
 		case VideoStream:
-			enabled = linphone_core_video_adaptive_jittcomp_enabled(core);
+			enabled = linphone_core_video_adaptive_jittcomp_enabled(core) ? true : false;
 			outputAdaptiveBufferCompensation(core, ost, "Video", enabled);
 			break;
 		case AllStreams:
-			enabled = linphone_core_audio_adaptive_jittcomp_enabled(core);
+			enabled = linphone_core_audio_adaptive_jittcomp_enabled(core) ? true : false;
 			outputAdaptiveBufferCompensation(core, ost, "Audio", enabled);
-			enabled = linphone_core_video_adaptive_jittcomp_enabled(core);
+			enabled = linphone_core_video_adaptive_jittcomp_enabled(core) ? true : false;
 			outputAdaptiveBufferCompensation(core, ost, "Video", enabled);
 			break;
 	}
diff --git a/daemon/commands/netsim.cc b/daemon/commands/netsim.cc
index 204289ba46..dcc277fbca 100644
--- a/daemon/commands/netsim.cc
+++ b/daemon/commands/netsim.cc
@@ -87,25 +87,25 @@ void NetsimCommand::exec(Daemon* app, const char* args){
 		char value[128]={0};
 		ist >> parameters;
 		if (fmtp_get_value(parameters.c_str(),"max_bandwidth",value, sizeof(value))){
-			params.max_bandwidth=atoi(value);
+			params.max_bandwidth=(float)atoi(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"max_buffer_size",value, sizeof(value))){
 			params.max_buffer_size=atoi(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"loss_rate",value, sizeof(value))){
-			params.loss_rate=atoi(value);
+			params.loss_rate=(float)atoi(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"latency",value, sizeof(value))){
 			params.latency=atoi(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"consecutive_loss_probability",value, sizeof(value))){
-			params.consecutive_loss_probability=atof(value);
+			params.consecutive_loss_probability=(float)atof(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"jitter_burst_density",value, sizeof(value))){
-			params.jitter_burst_density=atof(value);
+			params.jitter_burst_density=(float)atof(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"jitter_strength",value, sizeof(value))){
-			params.jitter_strength=atof(value);
+			params.jitter_strength=(float)atof(value);
 		}
 		if (fmtp_get_value(parameters.c_str(),"mode",value, sizeof(value))){
 			OrtpNetworkSimulatorMode mode=ortp_network_simulator_mode_from_string(value);
diff --git a/daemon/daemon-pipetest.c b/daemon/daemon-pipetest.c
index 9704136620..f0686fb6a0 100644
--- a/daemon/daemon-pipetest.c
+++ b/daemon/daemon-pipetest.c
@@ -19,8 +19,11 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 
 #define _GNU_SOURCE
 #include <fcntl.h>
+#include <stdio.h>
 
+#ifndef _WIN32
 #include <poll.h>
+#endif
 
 
 
@@ -29,9 +32,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 static int running=1;
 
 int main(int argc, char *argv[]){
-	struct pollfd pfds[2]={{0}};
-	char buf[4096];
-	int fd;
+	char buf[32768];
+	ortp_pipe_t fd;
 
 	/* handle args */
 	if (argc < 2) {
@@ -39,21 +41,51 @@ int main(int argc, char *argv[]){
 		return 1;
 	}
 
-	fd=ortp_client_pipe_connect(argv[1]);
-
 	ortp_init();
-	ortp_set_log_level_mask(NULL,ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
-	if (fd==-1){
+	ortp_set_log_level_mask(NULL, ORTP_MESSAGE | ORTP_WARNING | ORTP_ERROR | ORTP_FATAL);
+
+	fd=ortp_client_pipe_connect(argv[1]);
+	if (fd==(ortp_pipe_t)-1){
 		ortp_error("Could not connect to control pipe: %s",strerror(errno));
 		return -1;
 	}
+
+#ifdef _WIN32
+	DWORD fdwMode, fdwOldMode;
+	HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
+	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
+	GetConsoleMode(hin, &fdwOldMode);
+	fdwMode = fdwOldMode ^ ENABLE_MOUSE_INPUT ^ ENABLE_WINDOW_INPUT;
+	SetConsoleMode(hin, fdwMode);
+	FlushConsoleInputBuffer(hin);
+	while (running) {
+		DWORD read = 0;
+		DWORD written = 0;
+		ReadFile(hin, buf, sizeof(buf), &read, NULL);
+		if (read > 2) {
+			buf[read - 2] = '\0'; // Remove ending '\r\n'
+			if (ortp_pipe_write(fd, (uint8_t *)buf, strlen(buf)) < 0) {
+				running = 0;
+			} else {
+				read = ortp_pipe_read(fd, (uint8_t *)buf, sizeof(buf));
+				if (read > 0) {
+					WriteFile(hout, buf, read, &written, NULL);
+				} else {
+					running = 0;
+				}
+			}
+		}
+	}
+	SetConsoleMode(hin, fdwOldMode);
+#else
+	struct pollfd pfds[2] = { { 0 } };
+	int bytes;
 	pfds[0].fd=fd;
 	pfds[0].events=POLLIN;
 	pfds[1].fd=1;
 	pfds[1].events=POLLIN;
 	while (running){
 		int err;
-		int bytes;
 		err=poll(pfds,2,-1);
 		if (err>0){
 			/*splice to stdout*/
@@ -81,6 +113,8 @@ int main(int argc, char *argv[]){
 			}
 		}
 	}
+#endif
+
 	return 0;
 }
 
diff --git a/daemon/daemon.cc b/daemon/daemon.cc
index 85083cc202..82f3fa3261 100644
--- a/daemon/daemon.cc
+++ b/daemon/daemon.cc
@@ -18,18 +18,23 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */
 
 #include <cstdio>
+#ifndef _WIN32
 #include <sys/ioctl.h>
+#endif
 #include <iostream>
 #include <iomanip>
 #include <sstream>
 #include <algorithm>
+#include <functional>
 
 #ifdef HAVE_READLINE
 #include <readline/readline.h>
 #include <readline/history.h>
 #endif
 
+#ifndef _WIN32
 #include <poll.h>
+#endif
 
 #include "daemon.h"
 #include "commands/adaptive-jitter-compensation.h"
@@ -315,8 +320,8 @@ bool DaemonCommand::matches(const char *name) const {
 Daemon::Daemon(const char *config_path, const char *factory_config_path, const char *log_file, const char *pipe_name, bool display_video, bool capture_video) :
 		mLSD(0), mLogFile(NULL), mAutoVideo(0), mCallIds(0), mProxyIds(0), mAudioStreamIds(0) {
 	ms_mutex_init(&mMutex, NULL);
-	mServerFd = -1;
-	mChildFd = -1;
+	mServerFd = (ortp_pipe_t)-1;
+	mChildFd = (ortp_pipe_t)-1;
 	if (pipe_name == NULL) {
 #ifdef HAVE_READLINE
 		const char *homedir = getenv("HOME");
@@ -329,8 +334,12 @@ Daemon::Daemon(const char *config_path, const char *factory_config_path, const c
 #endif
 	} else {
 		mServerFd = ortp_server_pipe_create(pipe_name);
+#ifndef _WIN32
 		listen(mServerFd, 2);
-		fprintf(stdout, "Server unix socket created, name=%s fd=%i\n", pipe_name, mServerFd);
+		fprintf(stdout, "Server unix socket created, name=%s fd=%i\n", pipe_name, (int)mServerFd);
+#else
+		fprintf(stdout, "Named pipe  created, name=%s fd=%i\n", pipe_name, (int)mServerFd);
+#endif
 	}
 
 	if (log_file != NULL) {
@@ -566,7 +575,7 @@ void Daemon::iterateStreamStats() {
 void Daemon::iterate() {
 	linphone_core_iterate(mLc);
 	iterateStreamStats();
-	if (mChildFd == -1) {
+	if (mChildFd == (ortp_pipe_t)-1) {
 		if (!mEventQueue.empty()) {
 			Response *r = mEventQueue.front();
 			mEventQueue.pop();
@@ -595,8 +604,8 @@ void Daemon::sendResponse(const Response &resp) {
 	char buf[4096] = { 0 };
 	int size;
 	size = resp.toBuf(buf, sizeof(buf));
-	if (mChildFd != -1) {
-		if (write(mChildFd, buf, size) == -1) {
+	if (mChildFd != (ortp_pipe_t)-1) {
+		if (ortp_pipe_write(mChildFd, (uint8_t *)buf, size) == -1) {
 			ms_error("Fail to write to pipe: %s", strerror(errno));
 		}
 	} else {
@@ -606,43 +615,64 @@ void Daemon::sendResponse(const Response &resp) {
 }
 
 char *Daemon::readPipe(char *buffer, int buflen) {
+#ifdef _WIN32
+	if (mChildFd == (ortp_pipe_t)-1) {
+		mChildFd = ortp_server_pipe_accept_client(mServerFd);
+		ms_message("Client accepted");
+	}
+	if (mChildFd != (ortp_pipe_t)-1) {
+		int ret = ortp_pipe_read(mChildFd, (uint8_t *)buffer, buflen);
+		if (ret == -1) {
+			ms_error("Fail to read from pipe: %s", strerror(errno));
+			mChildFd = (ortp_pipe_t)-1;
+		} else {
+			if (ret == 0) {
+				ms_message("Client disconnected");
+				mChildFd = (ortp_pipe_t)-1;
+				return NULL;
+			}
+			buffer[ret] = 0;
+			return buffer;
+		}
+	}
+#else
 	struct pollfd pfd[2];
 	int nfds = 1;
 	memset(&pfd[0], 0, sizeof(pfd));
-	if (mServerFd != -1) {
+	if (mServerFd != (ortp_pipe_t)-1) {
 		pfd[0].events = POLLIN;
 		pfd[0].fd = mServerFd;
 	}
-	if (mChildFd != -1) {
+	if (mChildFd != (ortp_pipe_t)-1) {
 		pfd[1].events = POLLIN;
 		pfd[1].fd = mChildFd;
 		nfds++;
 	}
 	int err = poll(pfd, nfds, 50);
 	if (err > 0) {
-		if (mServerFd != -1 && (pfd[0].revents & POLLIN)) {
+		if (mServerFd != (ortp_pipe_t)-1 && (pfd[0].revents & POLLIN)) {
 			struct sockaddr_storage addr;
 			socklen_t addrlen = sizeof(addr);
 			int childfd = accept(mServerFd, (struct sockaddr*) &addr, &addrlen);
 			if (childfd != -1) {
-				if (mChildFd != -1) {
+				if (mChildFd != (ortp_pipe_t)-1) {
 					ms_error("Cannot accept two client at the same time");
 					close(childfd);
 				} else {
-					mChildFd = childfd;
+					mChildFd = (ortp_pipe_t)childfd;
 					return NULL;
 				}
 			}
 		}
-		if (mChildFd != -1 && (pfd[1].revents & POLLIN)) {
+		if (mChildFd != (ortp_pipe_t)-1 && (pfd[1].revents & POLLIN)) {
 			int ret;
-			if ((ret = read(mChildFd, buffer, buflen)) == -1) {
+			if ((ret = ortp_pipe_read(mChildFd, (uint8_t *)buffer, buflen)) == -1) {
 				ms_error("Fail to read from pipe: %s", strerror(errno));
 			} else {
 				if (ret == 0) {
 					ms_message("Client disconnected");
-					close(mChildFd);
-					mChildFd = -1;
+					ortp_server_pipe_close_client(mChildFd);
+					mChildFd = (ortp_pipe_t)-1;
 					return NULL;
 				}
 				buffer[ret] = 0;
@@ -650,6 +680,7 @@ char *Daemon::readPipe(char *buffer, int buflen) {
 			}
 		}
 	}
+#endif
 	return NULL;
 }
 
@@ -780,7 +811,7 @@ int Daemon::run() {
 	startThread();
 	while (mRunning) {
 		bool eof=false;
-		if (mServerFd == -1) {
+		if (mServerFd == (ortp_pipe_t)-1) {
 			ret = readLine(line,&eof);
 			if (ret && ret[0] != '\0') {
 #ifdef HAVE_READLINE
@@ -793,7 +824,7 @@ int Daemon::run() {
 		if (ret && ret[0] != '\0') {
 			execCommand(ret);
 		}
-		if (mServerFd == -1 && ret != NULL) {
+		if (mServerFd == (ortp_pipe_t)-1 && ret != NULL) {
 			free(ret);
 		}
 		if (eof && mRunning) {
@@ -836,10 +867,10 @@ Daemon::~Daemon() {
 
 	enableLSD(false);
 	linphone_core_destroy(mLc);
-	if (mChildFd != -1) {
-		close(mChildFd);
+	if (mChildFd != (ortp_pipe_t)-1) {
+		ortp_server_pipe_close_client(mChildFd);
 	}
-	if (mServerFd != -1) {
+	if (mServerFd != (ortp_pipe_t)-1) {
 		ortp_server_pipe_close(mServerFd);
 	}
 	if (mLogFile != NULL) {
@@ -884,6 +915,7 @@ int main(int argc, char *argv[]) {
 				return -1;
 			}
 			pipe_name = argv[++i];
+			stats_enabled = false;
 		} else if (strcmp(argv[i], "--factory-config") == 0) {
 			if (i + 1 >= argc) {
 				fprintf(stderr, "no file specify after --factory-config\n");
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 40813adf9b..8c33cfc069 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -264,8 +264,8 @@ private:
 	LinphoneSoundDaemon *mLSD;
 	std::list<DaemonCommand*> mCommands;
 	std::queue<Response*> mEventQueue;
-	int mServerFd;
-	int mChildFd;
+	ortp_pipe_t mServerFd;
+	ortp_pipe_t mChildFd;
 	std::string mHistfile;
 	bool mRunning;
 	bool mUseStatsEvents;
diff --git a/include/linphone/core_utils.h b/include/linphone/core_utils.h
index f15e9e9a43..5e618007f7 100644
--- a/include/linphone/core_utils.h
+++ b/include/linphone/core_utils.h
@@ -30,23 +30,23 @@ typedef struct _LinphoneSoundDaemon LinphoneSoundDaemon;
 
 typedef void (*LsdEndOfPlayCallback)(LsdPlayer *p);
 
-void lsd_player_set_callback(LsdPlayer *p, LsdEndOfPlayCallback cb);
-void lsd_player_set_user_pointer(LsdPlayer *p, void *up);
-void *lsd_player_get_user_pointer(const LsdPlayer *p);
-int lsd_player_play(LsdPlayer *p, const char *filename);
-int lsd_player_stop(LsdPlayer *p);
-void lsd_player_enable_loop(LsdPlayer *p, bool_t loopmode);
-bool_t lsd_player_loop_enabled(const LsdPlayer *p);
-void lsd_player_set_gain(LsdPlayer *p, float gain);
-LinphoneSoundDaemon *lsd_player_get_daemon(const LsdPlayer *p);
-
-LinphoneSoundDaemon * linphone_sound_daemon_new(MSFactory* factory, const char *cardname, int rate, int nchannels);
-LsdPlayer * linphone_sound_daemon_get_player(LinphoneSoundDaemon *lsd);
-void linphone_sound_daemon_release_player(LinphoneSoundDaemon *lsd, LsdPlayer *lsdplayer);
-void linphone_sound_daemon_stop_all_players(LinphoneSoundDaemon *obj);
-void linphone_sound_daemon_release_all_players(LinphoneSoundDaemon *obj);
-void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSoundDaemon *lsd);
-void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj);
+LINPHONE_PUBLIC void lsd_player_set_callback(LsdPlayer *p, LsdEndOfPlayCallback cb);
+LINPHONE_PUBLIC void lsd_player_set_user_pointer(LsdPlayer *p, void *up);
+LINPHONE_PUBLIC void *lsd_player_get_user_pointer(const LsdPlayer *p);
+LINPHONE_PUBLIC int lsd_player_play(LsdPlayer *p, const char *filename);
+LINPHONE_PUBLIC int lsd_player_stop(LsdPlayer *p);
+LINPHONE_PUBLIC void lsd_player_enable_loop(LsdPlayer *p, bool_t loopmode);
+LINPHONE_PUBLIC bool_t lsd_player_loop_enabled(const LsdPlayer *p);
+LINPHONE_PUBLIC void lsd_player_set_gain(LsdPlayer *p, float gain);
+LINPHONE_PUBLIC LinphoneSoundDaemon *lsd_player_get_daemon(const LsdPlayer *p);
+
+LINPHONE_PUBLIC LinphoneSoundDaemon * linphone_sound_daemon_new(MSFactory* factory, const char *cardname, int rate, int nchannels);
+LINPHONE_PUBLIC LsdPlayer * linphone_sound_daemon_get_player(LinphoneSoundDaemon *lsd);
+LINPHONE_PUBLIC void linphone_sound_daemon_release_player(LinphoneSoundDaemon *lsd, LsdPlayer *lsdplayer);
+LINPHONE_PUBLIC void linphone_sound_daemon_stop_all_players(LinphoneSoundDaemon *obj);
+LINPHONE_PUBLIC void linphone_sound_daemon_release_all_players(LinphoneSoundDaemon *obj);
+LINPHONE_PUBLIC void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSoundDaemon *lsd);
+LINPHONE_PUBLIC void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj);
 
 /**
  * Enum describing the result of the echo canceller calibration process.
-- 
GitLab