147 lines
4.5 KiB
C#
147 lines
4.5 KiB
C#
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
using System.IO;
|
||
|
using System.Net;
|
||
|
using System.Net.Sockets;
|
||
|
using UnityEditor;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace UnityEditor.Build.Pipeline.Tests
|
||
|
{
|
||
|
class LocalCacheServer : ScriptableSingleton<LocalCacheServer>
|
||
|
{
|
||
|
[SerializeField] public string m_path;
|
||
|
[SerializeField] public int m_port;
|
||
|
[SerializeField] public int m_pid = -1;
|
||
|
|
||
|
public static string Combine(params string[] components)
|
||
|
{
|
||
|
if (components.Length < 1)
|
||
|
throw new ArgumentException("At least one component must be provided!");
|
||
|
|
||
|
var path1 = components[0];
|
||
|
|
||
|
for (var index = 1; index < components.Length; ++index)
|
||
|
path1 = Path.Combine(path1, components[index]);
|
||
|
|
||
|
return path1;
|
||
|
}
|
||
|
|
||
|
private void Create(int port, ulong size, string cachePath)
|
||
|
{
|
||
|
var nodeExecutable = Combine(EditorApplication.applicationContentsPath, "Tools", "nodejs");
|
||
|
nodeExecutable = Application.platform == RuntimePlatform.WindowsEditor
|
||
|
? Combine(nodeExecutable, "node.exe")
|
||
|
: Combine(nodeExecutable, "bin", "node");
|
||
|
|
||
|
if (!Directory.Exists(cachePath))
|
||
|
Directory.CreateDirectory(cachePath);
|
||
|
|
||
|
m_path = cachePath;
|
||
|
|
||
|
var cacheServerJs = Combine(EditorApplication.applicationContentsPath, "Tools", "CacheServer", "main.js");
|
||
|
var processStartInfo = new ProcessStartInfo(nodeExecutable)
|
||
|
{
|
||
|
Arguments = "\"" + cacheServerJs + "\""
|
||
|
+ " --port " + port
|
||
|
+ " --path \"" + m_path
|
||
|
+ "\" --nolegacy"
|
||
|
+ " --monitor-parent-process " + Process.GetCurrentProcess().Id
|
||
|
// node.js has issues running on windows with stdout not redirected.
|
||
|
// so we silence logging to avoid that. And also to avoid CacheServer
|
||
|
// spamming the editor logs on OS X.
|
||
|
+ " --silent"
|
||
|
+ " --size " + size,
|
||
|
UseShellExecute = false,
|
||
|
CreateNoWindow = true
|
||
|
};
|
||
|
|
||
|
var p = new Process { StartInfo = processStartInfo };
|
||
|
p.Start();
|
||
|
|
||
|
m_port = port;
|
||
|
m_pid = p.Id;
|
||
|
Save(true);
|
||
|
}
|
||
|
|
||
|
public static string CachePath
|
||
|
{
|
||
|
get { return instance.m_path; }
|
||
|
}
|
||
|
|
||
|
public static int Port
|
||
|
{
|
||
|
get { return instance.m_port; }
|
||
|
}
|
||
|
|
||
|
public static void Setup(ulong size, string cachePath)
|
||
|
{
|
||
|
Kill();
|
||
|
instance.Create(GetRandomUnusedPort(), size, cachePath);
|
||
|
WaitForServerToComeAlive(instance.m_port);
|
||
|
}
|
||
|
|
||
|
public static void Kill()
|
||
|
{
|
||
|
if (instance.m_pid == -1)
|
||
|
return;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
var p = Process.GetProcessById(instance.m_pid);
|
||
|
p.Kill();
|
||
|
instance.m_pid = -1;
|
||
|
}
|
||
|
catch
|
||
|
{
|
||
|
// if we could not get a process, there is non alive. continue.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void Clear()
|
||
|
{
|
||
|
Kill();
|
||
|
if (Directory.Exists(instance.m_path))
|
||
|
Directory.Delete(instance.m_path, true);
|
||
|
}
|
||
|
|
||
|
private static void WaitForServerToComeAlive(int port)
|
||
|
{
|
||
|
var start = DateTime.Now;
|
||
|
var maximum = start.AddSeconds(5);
|
||
|
while (DateTime.Now < maximum)
|
||
|
{
|
||
|
if (!PingHost("localhost", port, 10)) continue;
|
||
|
Console.WriteLine("Server Came alive after {0} ms", (DateTime.Now - start).TotalMilliseconds);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static int GetRandomUnusedPort()
|
||
|
{
|
||
|
var listener = new TcpListener(IPAddress.Any, 0);
|
||
|
listener.Start();
|
||
|
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||
|
listener.Stop();
|
||
|
return port;
|
||
|
}
|
||
|
|
||
|
private static bool PingHost(string host, int port, int timeout)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
using (var client = new TcpClient())
|
||
|
{
|
||
|
var result = client.BeginConnect(host, port, null, null);
|
||
|
result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(timeout));
|
||
|
return client.Connected;
|
||
|
}
|
||
|
}
|
||
|
catch
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|