Beispiel #1
0
        //
        // Methods...
        //

        /// <summary>
        /// Save a file (& generate C# code)
        ///
        /// Called by an incoming http connection =>
        /// THREADSAFETY: Called from web server thread => do not call Unity code from this thread!
        /// </summary>
        /// <param name="data">Data.</param>
        public void Save(Dictionary <string, string> data)
        {
            string filename    = data ["file"];
            string content     = data ["content"];
            string codecontent = data ["code"];

            ServerLog.Log("Saving \"" + filename + "\"");

            string fullpath  = Path.Combine(scriptOutputDir, filename);
            string directory = Path.GetDirectoryName(fullpath);

            // Save the file
            Directory.CreateDirectory(directory);

            SaveEntry entry = new SaveEntry();

            entry.filename = "Assets/" + filename;
            entry.content  = content;
            entry.code     = VubbiFileHandler.GenerateHeader() + codecontent;

            lock (lockThis) {
                specificAssetsToSave.Add(entry);
            }

            // Note: if the save throws an error we will never know (we are in a different thread and we are not waiting for the save)
        }
Beispiel #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="vubbiscript.VubbiServer"/> class.
        ///
        /// This instance handles the incoming HTTP GET & POST requests with logic specific for Vubbi
        /// </summary>
        /// <param name="config">Config.</param>
        /// <param name="api">API.</param>
        public VubbiServer(ServerConfig config, VubbiApi api) : base(config.IP, config.Port)
        {
            this.config = config;
            this.api    = api;

            try {
                Thread thread = new Thread(new ThreadStart(this.listen));
                thread.Start();
                ServerLog.Log("Server Running");
            } catch (Exception e) {
                ServerLog.Log("Server Start Exception");
                ServerLog.Log(e);
            }
        }
Beispiel #3
0
        public void process()
        {
            // we can't use a StreamReader for input, because it buffers up extra data on us inside it's
            // "processed" view of the world, and we want the data raw after the headers
            inputStream = new BufferedStream(socket.GetStream());

            // we probably shouldn't be using a streamwriter for all output from handlers either
            outputStream = new StreamWriter(new BufferedStream(socket.GetStream()));
            try {
                // Keep processing requests from the browser (keep alive)
                while (true)
                {
                    parseRequest();
                    readHeaders();
                    if (http_method.Equals("GET"))
                    {
                        handleGETRequest();
                    }
                    else if (http_method.Equals("POST"))
                    {
                        handlePOSTRequest();
                    }
                    outputStream.Flush();
                }
            } catch (EndOfStreamException eose) {
                if (eose.Message == "EOS_BROWSER")
                {
                    return;
                }
            } catch (Exception e) {
                ServerLog.Log("Exception: " + e.ToString());
                writeFailure();
                outputStream.Flush();
            } finally {
                // bs.Flush(); // flush any remaining output
                inputStream = null; outputStream = null;                 // bs = null;
                socket.Close();
            }
        }
Beispiel #4
0
 public void listen()
 {
     try{
         listener = new TcpListener(address, port);
         listener.Start();
         while (is_active)
         {
             ServerLog.LogInfo("Listening!");
             TcpClient s = listener.AcceptTcpClient();
             ServerLog.LogInfo("Client accepted!");
             s.ReceiveTimeout = 1000;                    // After 1 seconds, time out the read operation!!!
             // Why? Because as long as the operation is waiting, this thread is in "native code" and Unity cannot go to "play" mode or reload the scripts!
             HttpProcessor processor = new HttpProcessor(s, this);
             Thread        thread    = new Thread(new ThreadStart(processor.process));
             thread.Start();
             Thread.Sleep(1);
         }
     } catch (Exception e) {
         ServerLog.Log("Server Listening Exception!");
         ServerLog.Log(e);
     }
 }
Beispiel #5
0
        /// <summary>
        /// HTTP POST => Implement to do API calls (saving/loading/deleting/listing Vubbi files)
        /// </summary>
        /// <param name="p">P.</param>
        /// <param name="inputData">Input data.</param>
        public override void handlePOSTRequest(HttpProcessor p, StreamReader inputData)
        {
            if (p.http_url.Equals("/api/save"))
            {
                // Save the file...
                api.Save(ParseQuery(inputData));
                SendApiOk(p, "");
                return;
            }
            if (p.http_url.Equals("/api/load"))
            {
                // Save the file...
                String content = api.Load(ParseQuery(inputData));
                SendApiOk(p, content);
                return;
            }
            if (p.http_url.Equals("/api/lang"))
            {
                // Send back the language preference of the user...
                SendApiOk(p, api.GetLanguagePreference());
                return;
            }
            if (p.http_url.StartsWith("/api/setlang/"))
            {
                // Send back the language preference of the user...
                api.SetLanguagePreference(p.http_url.Substring("/api/setlang/".Length));
                SendApiOk(p, "");
                return;
            }



            ServerLog.Log(p.http_url);
            String errorMessage = "<H2>Http Post not supported yet...</H2>";

            SendHeader(config.DefaultMime, errorMessage.Length, ServerHttpStatusCode.ERR_404_FILENOTFOUND, p);
            p.outputStream.Write(errorMessage);
        }
Beispiel #6
0
        /// <summary>
        ///
        /// This code is called when the Unity Editor starts. It starts Vubbi (installation + web server).
        ///
        /// </summary>
        static Init()
        {
            //
            // Check command line arguments...
            //
            string commandlinebuildkeyword = "+exportvubbiscriptunitypackage";

            if (System.Environment.GetCommandLineArgs().Contains(commandlinebuildkeyword))
            {
                // So, we need to do a build instead of running the code...
                string[] cargs     = System.Environment.GetCommandLineArgs();
                string   outputdir = null;
                for (int i = 0; i < cargs.Length; i++)
                {
                    if (cargs [i] == commandlinebuildkeyword)
                    {
                        outputdir = cargs [i + 1];
                    }
                }
                AssetDatabase.ExportPackage("Assets/Editor Default Resources/Editor/VubbiScript", outputdir, ExportPackageOptions.Recurse);
                return;                // DO NOT CONTINUE... Exit Unity now...
            }

            //
            // Set the icon for Vubbi files
            //
            VubbiFileHandler.InitVubbiIcon();

            //
            // Server Configuration
            //
            ServerConfig config = new ServerConfig();

                        #if UNITY_EDITOR
            // When running in development mode => the "web" code can be found in the folder "web" next to the actual unity project folder
            config.HostDirectory = System.IO.Path.Combine(UnityEngine.Application.dataPath, "../../web");
                        #else
            // When compiling for the release build, we do not define UNITY_EDITOR
            // For released code, the HTML & JavaScript can be found in:
            config.HostDirectory = System.IO.Path.Combine(UnityEngine.Application.dataPath, "../WebRoot");
                        #endif
            config.Port = 8040;

            //
            // Update Web directory
            // This is part of the "installer"...
            // Right after importing the unity package, we will unzip the data file and put it in the main project folder.
            // => Resulting in a "WebRoot" folder
            //
            string dataFile = System.IO.Path.Combine(UnityEngine.Application.dataPath, "Editor Default Resources/Editor/VubbiScript/Vubbi.data");
            if (System.IO.File.Exists(dataFile))
            {
                System.IO.Directory.CreateDirectory(config.HostDirectory + "/");
                UnzipDataDir(dataFile, config.HostDirectory + "/");
                System.IO.File.Delete(dataFile);
                AssetDatabase.Refresh();
                ServerLog.Log("Installation successful!");
            }

            //
            // Start Server
            //
            VubbiApi api = new VubbiApi();

            new VubbiServer(config, api);

            //
            // Register update callback
            //
            EditorApplication.update += api.OnUpdate;
        }
Beispiel #7
0
        /// <summary>
        /// HTTP GET => Implement to load actual files from the server... Returns the html/js/css/... files.
        /// </summary>
        /// <param name="p">P.</param>
        public override void handleGETRequest(HttpProcessor p)
        {
            String requestedUrl = p.http_url;

            ServerLog.Log(String.Format("request: {0}", requestedUrl));

            if (requestedUrl.EndsWith("/"))
            {
                // We are looking in a directory...
            }

            //Extract the requested file name
            String directory = requestedUrl.Substring(requestedUrl.IndexOf("/"), requestedUrl.LastIndexOf("/") - requestedUrl.IndexOf("/"));
            String filename  = requestedUrl.Substring(requestedUrl.LastIndexOf("/") + 1);

            /////////////////////////////////////////////////////////////////////
            // Identify the Physical Directory
            /////////////////////////////////////////////////////////////////////
            String physicalDirectory = config.GetPhysicalPath(directory);

            // TODO: check if directory exists...

            /////////////////////////////////////////////////////////////////////
            // Identify the File Name
            /////////////////////////////////////////////////////////////////////

            //If The file name is not supplied then look in the default file list
            if (filename.Length == 0)
            {
                // Get the default filename
                filename = config.GetDefaultFileInFolder(physicalDirectory);
            }

            // TODO: check if filename is no longer "" and check if file exists...

            String mimeHeader = config.GetMimeType(filename);

            String fullPath = Path.Combine(physicalDirectory, filename);

            ServerLog.LogInfo(" < " + fullPath);

            if (!File.Exists(fullPath))
            {
                ServerLog.Log("    [!]" + ServerHttpStatusCode.ERR_404_FILENOTFOUND);
                String errorMessage = "<H2>404 Error! File Does Not Exists...</H2>";
                SendHeader(config.DefaultMime, errorMessage.Length, ServerHttpStatusCode.ERR_404_FILENOTFOUND, p);
                p.outputStream.Write(errorMessage);
            }
            else
            {
                ServerLog.LogInfo("    [+]" + HttpStatusCode.OK);
                FileInfo f           = new FileInfo(fullPath);
                Stream   filecontent = new BufferedStream(f.OpenRead());
                try{
                    SendHeader(mimeHeader, f.Length, ServerHttpStatusCode.OK, p);
                    p.outputStream.Flush();
                    CopyStream(filecontent, p.socket.GetStream());
                }finally{
                    filecontent.Close();
                }
            }
        }