using UnityEngine; using UnityEditor.SceneManagement; using System.Text; using System.IO; using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; public class ftClient { public const byte SERVERTASK_COPY = 0; public const byte SERVERTASK_FTRACE = 1; public const byte SERVERTASK_FTRACERTX = 2; public const byte SERVERTASK_COMBINEMASKS = 3; public const byte SERVERTASK_COMBINESH = 4; public const byte SERVERTASK_DENOISE5 = 5; public const byte SERVERTASK_DENOISE6 = 6; public const byte SERVERTASK_DENOISE7 = 7; public const byte SERVERTASK_DENOISEOIDN = 8; public const byte SERVERTASK_HF2HDR = 9; public const byte SERVERTASK_RGBA2TGA = 10; public const byte SERVERTASK_SEAMFIX = 11; public const byte SERVERTASK_LMREBAKE = 12; public const byte SERVERTASK_LMREBAKESIMPLE = 13; public const byte SERVERTASK_LODGEN = 14; public const byte SERVERTASK_LODGENINIT = 15; public const byte SERVERTASK_GIPARAMS = 16; public const byte SERVERTASK_RECEIVEFILE = 17; public const byte SERVERTASK_REPORTSTATUS = 18; public const byte SERVERTASK_SETSCENENAME = 19; public const byte SERVERTASK_GETDATA = 20; public const byte SERVERTASK_GETDATAREADY = 21; public const byte SERVERERROR_IDLE = 0; public const byte SERVERERROR_COPY = 1; public const byte SERVERERROR_EXEC = 2; public const byte SERVERERROR_APPERR = 3; public const byte SERVERERROR_GIPARAMS = 4; public const byte SERVERERROR_NOTIMPLEMENTED = 5; public const byte SERVERERROR_UNKNOWNTASK = 6; public const byte SERVERERROR_BUSY = 7; public const byte SERVERERROR_UNKNOWN = 8; public const byte SERVERERROR_SCENENAMETOOLONG = 9; public const byte SERVERERROR_FILENOTFOUND = 10; public const byte SERVERERROR_FILEHASZEROSIZE = 11; public const byte SERVERERROR_NOMEM = 12; public const byte SERVERERROR_INCORRECT = 13; public const byte SERVERERROR_INCORRECTFILENAME = 14; public const byte SERVERERROR_WRITEFAILED = 15; public const byte SERVERERROR_INCORRECTARGS = 16; public const byte SERVERERROR_FILESIZE = 17; public const byte SERVERERROR_STATUSLIMIT = 18; public static string serverAddress = "127.0.0.1"; const int serverPort = 27777; public static bool connectedToServer = false; public static string lastServerMsg = "Server: no data"; public static string lastServerScene = ""; // last baked scene public static int lastServerErrorCode = 0; public static bool lastServerMsgIsError = false; public static bool serverGetDataMode = false; // if we're in download mode or status polling mode public static bool serverMustRefreshData = false; // if ready to apply downloaded data static string lastServerFile = ""; // last file loaded via GETDATA on the server static int lastServerFileHash = 0; static int lastServerFileSize = 0; static double timeToUpdateServerStatus = 0; static double serverStatusInterval = 1000.0; static double serverConnectionTimeout = 2000.0; static Socket statusSocket; //static System.Threading.Thread statusThread; static IEnumerator statusProc; public static Dictionary app2serverTask = new Dictionary { {"ftrace", SERVERTASK_FTRACE}, {"ftraceRTX", SERVERTASK_FTRACERTX}, {"combineMasks", SERVERTASK_COMBINEMASKS}, {"combineSH", SERVERTASK_COMBINESH}, {"denoiserLegacy", SERVERTASK_DENOISE5}, {"denoiser", SERVERTASK_DENOISE6}, {"denoiser72", SERVERTASK_DENOISE7}, {"denoiserOIDN", SERVERTASK_DENOISEOIDN}, {"halffloat2hdr", SERVERTASK_HF2HDR}, {"rgba2tga", SERVERTASK_RGBA2TGA}, {"seamfixer", SERVERTASK_SEAMFIX}, {"lmrebake (simple)", SERVERTASK_LMREBAKESIMPLE}, {"lmrebake", SERVERTASK_LMREBAKE} }; public static List serverFileList, serverGetFileList; public static int serverGetFileIterator = 0; public static IEnumerator UpdateConnection()//WaitForMessages() { var ipAdd = System.Net.IPAddress.Parse(serverAddress); var remoteEP = new IPEndPoint(ipAdd, serverPort); var request = new byte[1]; request[0] = SERVERTASK_REPORTSTATUS; var requestGet = new byte[5]; requestGet[0] = SERVERTASK_GETDATAREADY; int numTasks = 1; var taskGet = new byte[1]; var nullByte = new byte[1]; taskGet[0] = SERVERTASK_GETDATA; nullByte[0] = 0; lastServerMsg = "Connecting..."; lastServerErrorCode = 0; lastServerMsgIsError = false; var status = new byte[256]; byte[] fileBuffer = null; bool waitingForGet = false; while (connectedToServer) { if (statusSocket != null) { statusSocket.Close(); statusSocket = null; } waitingForGet = false; // Attempt connecting to server bool connectionInProgress = true; bool connectionError = false; double timeout = ftRenderLightmap.GetTimeMs() + serverConnectionTimeout; while(connectionInProgress) { connectionInProgress = false; try { if (statusSocket == null) { statusSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); statusSocket.Blocking = false; statusSocket.Connect(remoteEP); } else { if (statusSocket.Poll(0, SelectMode.SelectError)) { connectionError = true; break; } if (!statusSocket.Poll(0, SelectMode.SelectWrite) && ftRenderLightmap.GetTimeMs() < timeout) { connectionInProgress = true; } } } catch(SocketException s) { if (s.ErrorCode == 10035) // WSAEWOULDBLOCK { connectionInProgress = true; } else { connectionError = true; break; } } if (connectionInProgress) yield return null; } statusSocket.Blocking = true; // Send request(s) try { if (connectionError) throw new SocketException(); if (serverGetDataMode && serverGetFileList == null) serverGetDataMode = false; if (serverGetDataMode && serverGetFileList.Count <= serverGetFileIterator) { serverMustRefreshData = true; serverGetDataMode = false; } if (serverGetDataMode) { var fname = serverGetFileList[serverGetFileIterator]; if (lastServerFile != fname) { int len = fname.Length; statusSocket.Send(System.BitConverter.GetBytes(numTasks)); statusSocket.Send(taskGet); statusSocket.Send(System.BitConverter.GetBytes(len)); statusSocket.Send(Encoding.ASCII.GetBytes(fname)); statusSocket.Send(nullByte); statusSocket.Close(); statusSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); statusSocket.Connect(remoteEP); statusSocket.Send(request); #if BAKERY_NETDEBUG Debug.Log("Request sent (load file " + fname + ")"); #endif } else { fileBuffer = new byte[lastServerFileSize]; System.Buffer.BlockCopy(System.BitConverter.GetBytes(lastServerFileHash), 0, requestGet, 1, 4); statusSocket.Send(requestGet); #if BAKERY_NETDEBUG Debug.Log("Request sent (get file)"); #endif waitingForGet = true; } } else { statusSocket.Send(request); #if BAKERY_NETDEBUG Debug.Log("Request sent"); #endif } } catch(SocketException s) { lastServerMsg = "Failed to get data from server (" + s.ErrorCode + ")"; lastServerMsgIsError = true; lastServerErrorCode = 0; Debug.LogError(lastServerMsg); statusSocket.Close(); statusSocket = null; statusProc = null; //statusThread = null; connectedToServer = false; //return; yield break; } #if BAKERY_NETDEBUG Debug.Log("Waiting for server to respond"); #endif int serverErrCode = 0; int appCode = 0; int appErrCode = 0; int textLen = 0; int fileReady = 0; int fileHash = 0; int fileSize = 0; string text = ""; string fileNameReady = ""; int byteCount = 0; bool interrupted = false; double maxTimeToReceive = 10.0; double timeToInterrupt = ftRenderLightmap.GetTimeMs() + maxTimeToReceive; while(!interrupted) { if (ftRenderLightmap.GetTimeMs() > timeToInterrupt) { timeToInterrupt = ftRenderLightmap.GetTimeMs() + maxTimeToReceive; yield return null; } //while(statusSocket.Available == 0) yield return null; //while(!statusSocket.Poll(0, SelectMode.SelectRead)) yield return null; try { //while(true) //{ if (waitingForGet) { int bytesReceived = statusSocket.Receive(fileBuffer, byteCount, fileBuffer.Length - byteCount, SocketFlags.None); byteCount += bytesReceived; //Debug.Log("Received " + bytesReceived); if (bytesReceived == 0) interrupted = true;//break; } else { byteCount = statusSocket.Receive(status); //break; interrupted = true; } //} } catch { if (waitingForGet) { Debug.LogError("Error getting file from server - retrying"); lastServerFile = ""; } else { lastServerMsg = "Server disconnected"; lastServerMsgIsError = true; lastServerErrorCode = 0; Debug.LogError(lastServerMsg); statusSocket.Close(); statusSocket = null; //statusThread = null; statusProc = null; connectedToServer = false; yield break; } } } if (byteCount > 0) { if (waitingForGet) { Debug.Log("Data received: " + byteCount); var ext = lastServerFile.Substring(lastServerFile.Length-3).ToLower(); string outPath; if (ext == "lz4" || ext == "dds") { outPath = ftRenderLightmap.scenePath + "/" + lastServerFile; } else { outPath = "Assets/" + ftRenderLightmap.outputPath + "/" + lastServerFile; } BinaryWriter bw = null; try { bw = new BinaryWriter(File.Open(outPath, FileMode.Create)); } catch { Debug.LogError("Failed writing " + outPath); } if (bw != null) { bw.Write(fileBuffer); bw.Close(); Debug.Log("File saved: " + outPath); } yield return null; serverGetFileIterator++; } else { if (byteCount == 150) { serverErrCode = System.BitConverter.ToInt32(status, 0); appCode = System.BitConverter.ToInt32(status, 4); appErrCode = System.BitConverter.ToInt32(status, 8); textLen = status[12]; fileReady = status[13]; fileHash = System.BitConverter.ToInt32(status, 14); fileSize = System.BitConverter.ToInt32(status, 18); if (textLen > 0) { text = Encoding.ASCII.GetString(status, 22, textLen); } if (fileReady > 0) { fileNameReady = Encoding.ASCII.GetString(status, 22 + textLen + 1, fileReady); } } else { serverErrCode = SERVERERROR_UNKNOWN; Debug.LogError("Unrecognized response size: " + byteCount); } //if (serverErrCode != 0) { var serverMsg = "Server: " + ftErrorCodes.TranslateServer(serverErrCode, appCode, appErrCode); bool isError = serverErrCode != SERVERERROR_IDLE && serverErrCode != SERVERERROR_BUSY; if (isError) { Debug.LogError(serverMsg); } else { #if BAKERY_NETDEBUG Debug.Log(serverMsg); #else if (lastServerMsg != serverMsg) Debug.Log(serverMsg); #endif } lastServerMsg = serverMsg; lastServerMsgIsError = isError; lastServerErrorCode = serverErrCode; lastServerScene = text; lastServerFile = fileNameReady; lastServerFileHash = fileHash; lastServerFileSize = fileSize; } } } if (!serverGetDataMode) { //var sleepTime = timeToUpdateServerStatus - curTime; //if (sleepTime > 0) System.Threading.Thread.Sleep((int)sleepTime); while(true) { var curTime = ftRenderLightmap.GetTimeMs(); if (curTime >= timeToUpdateServerStatus) break; yield return null; } timeToUpdateServerStatus = ftRenderLightmap.GetTimeMs() + serverStatusInterval; } } statusSocket.Close(); statusSocket = null; //statusThread = null; statusProc = null; } public static void Disconnect() { if (statusSocket != null) { statusSocket.Close(); statusSocket = null; } statusProc = null; /*if (statusThread != null) { statusThread.Abort(); statusThread = null; }*/ connectedToServer = false; serverGetDataMode = false; } public static void ConnectToServer() { try { Disconnect(); connectedToServer = true; timeToUpdateServerStatus = 0; //statusThread = new System.Threading.Thread(WaitForMessages); //statusThread.Start(); statusProc = UpdateConnection(); statusProc.MoveNext(); } catch { Debug.LogError("Failed getting data from server"); throw; } } public static bool SendRenderSequence(byte[] renderSequence) { Socket soc = null; var ipAdd = System.Net.IPAddress.Parse(serverAddress); var remoteEP = new IPEndPoint(ipAdd, serverPort); bool connectionInProgress; for(int i=0; i fileList) { serverGetFileList = fileList; serverGetFileIterator = 0; serverGetDataMode = true; } public static void Update() { if (statusProc != null) statusProc.MoveNext(); } }