コード例 #1
0
        void readCb(IAsyncResult ar)
        {
            try
            {
                Request request = (Request)ar.AsyncState;
                int     nRead   = request.read_stream.EndRead(ar);
                if (nRead > 0)
                {
                    request.read_offset += nRead;
                    request.read_stream.BeginRead(request.body.Array, request.read_offset,
                                                  request.body.Count - request.read_offset,
                                                  new AsyncCallback(readCb), request);
                }
                else
                {
                    if (request.web_response == null)
                    {
                        FunDebug.LogError("Host manager response failed.");
                        return;
                    }

                    webRequestCallback(request);

                    request.read_stream.Close();
                    request.web_response.Close();
                }
            }
            catch (Exception e)
            {
                if (e is ObjectDisposedException || e is NullReferenceException)
                {
                    FunDebug.LogDebug("Dedicated server request operation has been cancelled.");
                }
            }
        }
コード例 #2
0
        void requestStreamCb(IAsyncResult ar)
        {
            try
            {
                Request request = (Request)ar.AsyncState;
                Stream  stream  = request.web_request.EndGetRequestStream(ar);

                ArraySegment <byte> body = request.body;
                if (body.Count > 0)
                {
                    stream.Write(body.Array, 0, body.Count);
                }
                stream.Close();

                IAsyncResult result = request.web_request.BeginGetResponse(new AsyncCallback(responseCb), request);
                ThreadPool.RegisterWaitForSingleObject(
                    result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request,
                    heartbeat_seconds_ == 0 ? default_timeout_ : (int)(heartbeat_seconds_ / 2f) * 1000, true);
            }
            catch (Exception e)
            {
                WebException we = e as WebException;
                if (we != null && we.Status == WebExceptionStatus.ConnectFailure)
                {
                    onRequestFailed((Request)ar.AsyncState);
                }
                else if ((we != null && we.Status == WebExceptionStatus.RequestCanceled) ||
                         (e is ObjectDisposedException || e is NullReferenceException))
                {
                    // When Stop is called HttpWebRequest.EndGetRequestStream may return an Exception
                    FunDebug.LogDebug("Dedicated Server - Request operation has been cancelled.");
                }
            }
        }
        void downloadFileCompleteCb(object sender, System.ComponentModel.AsyncCompletedEventArgs ar)
        {
            try
            {
                if (ar.Error != null)
                {
                    throw ar.Error;
                }

                image_list_.RemoveAt(0);
                if (image_list_.Count > 0)
                {
                    KeyValuePair <string, string> item = image_list_[0];
                    web_client_.DownloadFileAsync(new Uri(item.Key), item.Value);
                    FunDebug.LogDebug("Announcement - Downloading image: {0}", item.Key);
                }
                else
                {
                    FunDebug.Log("Announcement - All images have been downloaded.\npath:{0}", local_path_);
                    onResult(AnnounceResult.kSucceeded);
                }
            }
            catch (Exception e)
            {
                FunDebug.LogError("Announcement - Failure in downloadFileCompleteCb:\n{0}", e.ToString());
                onResult(AnnounceResult.kExceptionError);
            }
        }
コード例 #4
0
        public void LogDebug(string message, params object[] args)
        {
#if ENABLE_LOG && ENABLE_DEBUG
            message = string.Format("[{0}] {1}", hash_, message);
            FunDebug.LogDebug(message, args);
#endif
        }
コード例 #5
0
        void parseMessages()
        {
            lock (message_lock_)
            {
                while (true)
                {
                    if (next_decoding_offset_ >= received_size_ - 4)
                    {
                        // Not enough bytes. Wait for more bytes to come.
                        break;
                    }

                    int length = 0;
                    if (BitConverter.IsLittleEndian)
                    {
                        byte[] bytes = new byte [4];
                        Buffer.BlockCopy(receive_buffer_, next_decoding_offset_, bytes, 0, 4);
                        Array.Reverse(bytes); // gets big endian
                        length = (int)BitConverter.ToUInt32(bytes, 0);
                    }
                    else
                    {
                        length = (int)BitConverter.ToUInt32(receive_buffer_, next_decoding_offset_);
                    }

                    if (length > 0)
                    {
                        int offset = next_decoding_offset_ + 4;
                        if (received_size_ - offset < length)
                        {
                            // Need more bytes for a message body. Waiting.
                            break;
                        }

                        object obj = FunapiDSRpcMessage.Deserialize(new ArraySegment <byte>(receive_buffer_, offset, length));
                        if (obj != null)
                        {
                            FunDedicatedServerRpcMessage msg = obj as FunDedicatedServerRpcMessage;
                            messages_.Enqueue(msg);

#if ENABLE_DEBUG
                            StringBuilder log = new StringBuilder();
                            log.AppendFormat("[Peer:{0}] [S->C] type={1}, length={2} ", peer_id_, msg.type, length);
                            FunapiDSRpcMessage.DebugString(msg, log);
                            FunDebug.LogDebug(log.ToString());
#endif
                        }

                        next_decoding_offset_ = offset + length;
                    }
                    else
                    {
                        next_decoding_offset_ += 4;
                    }
                }
            }
        }
コード例 #6
0
        void onSend()
        {
            try
            {
                lock (send_lock_)
                {
                    if (send_queue_.Count <= 0 || sending_.Count > 0)
                    {
                        return;
                    }

                    Queue <FunDedicatedServerRpcMessage> list = send_queue_;
                    send_queue_ = new Queue <FunDedicatedServerRpcMessage>();

                    foreach (FunDedicatedServerRpcMessage msg in list)
                    {
                        byte[] buf = FunapiDSRpcMessage.Serialize(msg);
                        if (buf == null)
                        {
                            continue;
                        }

#if ENABLE_DEBUG
                        StringBuilder log = new StringBuilder();
                        log.AppendFormat("[Peer:{0}] [C->S] type={1}, length={2} ", peer_id_, msg.type, buf.Length);
                        FunapiDSRpcMessage.DebugString(msg, log);
                        FunDebug.LogDebug(log.ToString());
#endif

                        sending_.Add(new ArraySegment <byte>(buf));
                    }

                    if (sending_.Count <= 0)
                    {
                        return;
                    }

                    lock (sock_lock_)
                    {
                        if (sock_ == null)
                        {
                            return;
                        }

                        sock_.BeginSend(sending_, SocketFlags.None, new AsyncCallback(this.sendCb), this);
                    }
                }
            }
            catch (Exception e)
            {
                logWarning("Sending failed. {0}", e.ToString());
                onDisconnect(PeerEventType.kDisconnected);
            }
        }
コード例 #7
0
        IEnumerator sendHeartbeat()
        {
            yield return(new WaitForSeconds(heartbeat_seconds_));

            while (isActive)
            {
                FunDebug.LogDebug("Send a heart beat to host manager.");

                httpPost("heartbeat");
                yield return(new WaitForSeconds(heartbeat_seconds_));
            }
        }
コード例 #8
0
        void loadCachedList()
        {
            cached_list_.Clear();

            string path = target_path_ + kCachedFileName;

            if (!File.Exists(path))
            {
                return;
            }

            StreamReader stream = File.OpenText(path);
            string       data   = stream.ReadToEnd();

            stream.Close();

            if (data.Length <= 0)
            {
                FunDebug.LogWarning("Downloader.loadCachedList - Failed to load a cached file list.");
                return;
            }

            Dictionary <string, object> json = Json.Deserialize(data) as Dictionary <string, object>;
            List <object> list = json["list"] as List <object>;

            foreach (Dictionary <string, object> node in list)
            {
                DownloadFileInfo info = new DownloadFileInfo();
                info.path = node["path"] as string;
                info.size = Convert.ToUInt32(node["size"]);
                info.hash = node["hash"] as string;
                if (node.ContainsKey("front"))
                {
                    info.hash_front = node["front"] as string;
                }
                else
                {
                    info.hash_front = "";
                }

                cached_list_.Add(info);
            }

            FunDebug.LogDebug("[Downloader] Cached list loaded : {0}", cached_list_.Count);
        }
コード例 #9
0
        void deleteLocalFiles()
        {
            if (delete_file_list_.Count <= 0)
            {
                return;
            }

            FunDebug.Log("[Downloader] Try to delete {0} local files.", delete_file_list_.Count);

            foreach (string path in delete_file_list_)
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                    FunDebug.LogDebug("'{0}' file deleted.\npath: {1}", Path.GetFileName(path), path);
                }
            }

            delete_file_list_.Clear();
        }
コード例 #10
0
        void updateCachedList()
        {
            StringBuilder data = new StringBuilder();

            data.Append("{ \"list\": [ ");

            int index = 0;

            foreach (DownloadFileInfo info in cached_list_)
            {
                data.AppendFormat("{{ \"path\":\"{0}\", ", info.path);
                data.AppendFormat("\"size\":{0}, ", info.size);
                if (info.hash_front.Length > 0)
                {
                    data.AppendFormat("\"front\":\"{0}\", ", info.hash_front);
                }
                data.AppendFormat("\"hash\":\"{0}\" }}", info.hash);

                if (++index < cached_list_.Count)
                {
                    data.Append(", ");
                }
            }

            data.Append(" ] }");

            string       path   = target_path_ + kCachedFileName;
            FileStream   file   = File.Open(path, FileMode.Create);
            StreamWriter stream = new StreamWriter(file);

            stream.Write(data.ToString());
            stream.Flush();
            stream.Close();

            FunDebug.LogDebug("[Downloader] Updates cached list : {0}", cached_list_.Count);
        }
コード例 #11
0
        void responseCb(IAsyncResult ar)
        {
            try
            {
                Request request = (Request)ar.AsyncState;
                if (request.was_aborted)
                {
                    FunDebug.Log("Dedicated Server - Response callback. Request aborted.");
                    return;
                }

                request.web_response = (HttpWebResponse)request.web_request.EndGetResponse(ar);
                request.web_request  = null;

                if (request.web_response.StatusCode == HttpStatusCode.OK)
                {
                    byte[]   header     = request.web_response.Headers.ToByteArray();
                    string   str_header = System.Text.Encoding.ASCII.GetString(header, 0, header.Length);
                    string[] lines      = str_header.Replace("\r", "").Split('\n');

                    int length = 0;

                    foreach (string n in lines)
                    {
                        if (n.Length > 0)
                        {
                            string[] tuple = n.Split(kHeaderSeparator, StringSplitOptions.RemoveEmptyEntries);
                            string   key   = tuple[0].ToLower();
                            if (key == "content-length" && tuple.Length >= 2)
                            {
                                length = Convert.ToInt32(tuple[1]);
                                break;
                            }
                        }
                    }

                    byte[] buffer = new byte[length];
                    request.body = new ArraySegment <byte>(buffer);

                    request.read_stream = request.web_response.GetResponseStream();
                    request.read_stream.BeginRead(buffer, 0, length, new AsyncCallback(readCb), request);
                }
                else
                {
                    FunDebug.LogError("Host manager response failed. status:{0}",
                                      request.web_response.StatusDescription);
                }
            }
            catch (Exception e)
            {
                WebException we = e as WebException;
                if (we != null && we.Status == WebExceptionStatus.ConnectFailure)
                {
                    onRequestFailed((Request)ar.AsyncState);
                }
                else if ((we != null && we.Status == WebExceptionStatus.RequestCanceled) ||
                         (e is ObjectDisposedException || e is NullReferenceException))
                {
                    // When Stop is called HttpWebRequest.EndGetResponse may return a Exception
                    FunDebug.LogDebug("Dedicated server request operation has been cancelled.");
                }
            }
        }
コード例 #12
0
        void httpPostSync(string command, string data, Action <object> callback = null) // for send version only
        {
            string url = server_url_ + command;

            // Request
            HttpWebRequest web_request = (HttpWebRequest)WebRequest.Create(url);

            web_request.Method      = "POST";
            web_request.ContentType = "application/octet-stream";

            Request request = new Request();

            request.web_request = web_request;
            request.callback    = callback;
            request.command     = command;

            try
            {
                byte[] bytes             = System.Text.Encoding.UTF8.GetBytes(data);
                ArraySegment <byte> body = new ArraySegment <byte>(bytes);
                web_request.ContentLength = body.Count;
                request.body = body;

                Stream stream = web_request.GetRequestStream();
                stream.Write(request.body.Array, 0, request.body.Count);
                stream.Close();

                request.web_response = (HttpWebResponse)web_request.GetResponse();
                request.web_request  = null;

                if (request.web_response.StatusCode == HttpStatusCode.OK)
                {
                    request.read_stream = request.web_response.GetResponseStream();
                    StreamReader sr = new StreamReader(request.read_stream);

                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(sr.ReadToEnd());
                    request.body = new ArraySegment <byte>(buffer);

                    webRequestCallback(request);

                    request.read_stream.Close();
                    request.web_response.Close();
                }
                else
                {
                    FunDebug.LogError("Host manager response failed. status:{0}",
                                      request.web_response.StatusDescription);
                }
            }
            catch (Exception e)
            {
                WebException we = e as WebException;
                if (we != null && we.Status == WebExceptionStatus.ConnectFailure)
                {
                    onRequestFailed(request);
                }
                else if ((we != null && we.Status == WebExceptionStatus.RequestCanceled) ||
                         (e is ObjectDisposedException || e is NullReferenceException))
                {
                    FunDebug.LogDebug("Dedicated Server - httpPostServerVersionSync operation has been cancelled.");
                }
            }
        }
コード例 #13
0
 void logDebug(string format, params object[] args)
 {
     FunDebug.LogDebug(makeLogText(format, args));
 }
コード例 #14
0
        void downloadDataCompleteCb(object sender, DownloadDataCompletedEventArgs ar)
        {
            try
            {
                if (ar.Error != null)
                {
                    throw ar.Error;
                }

                // Parse json
                string data = Encoding.UTF8.GetString(ar.Result);
                Dictionary <string, object> json = Json.Deserialize(data) as Dictionary <string, object>;
                if (json == null)
                {
                    FunDebug.LogWarning("Announcement - Deserialize json failed. json: {0}", data);
                    onResult(AnnounceResult.kInvalidJson);
                    return;
                }

                FunDebug.Assert(json.ContainsKey("list"));
                List <object> list = json["list"] as List <object>;
                if (list == null || list.Count <= 0)
                {
                    if (list == null)
                    {
                        FunDebug.LogWarning("Announcement - Announcement list is null.");
                    }
                    else if (list.Count <= 0)
                    {
                        FunDebug.LogWarning("Announcement - There is no announcement list.");
                    }

                    onResult(AnnounceResult.kListIsNullOrEmpty);
                    return;
                }

                announce_list_.Clear();

                foreach (Dictionary <string, object> node in list)
                {
                    announce_list_.Add(node);

                    // download image
                    if (node.ContainsKey(kImageUrlKey) && node.ContainsKey(kImageMd5Key))
                    {
                        checkDownloadImage(node[kImageUrlKey] as string, node[kImageMd5Key] as string);
                    }

                    if (node.ContainsKey(kExtraImagesKey))
                    {
                        List <object> extra_images = node[kExtraImagesKey] as List <object>;
                        foreach (Dictionary <string, object> extra_image in extra_images)
                        {
                            if (extra_image.ContainsKey(kExtraImageUrlKey) && extra_image.ContainsKey(kExtraImageMd5Key))
                            {
                                checkDownloadImage(extra_image[kExtraImageUrlKey] as string, extra_image[kExtraImageMd5Key] as string);
                            }
                        }
                    }
                }

                FunDebug.Log("Announcement - List has been updated. total: {0}", announce_list_.Count);

                if (image_list_.Count > 0)
                {
                    // Request a file.
                    KeyValuePair <string, string> item = image_list_[0];
                    web_client_.DownloadFileAsync(new Uri(item.Key), item.Value);
                    FunDebug.LogDebug("Download announcement image: {0}", item.Key);
                }
                else
                {
                    onResult(AnnounceResult.kSucceeded);
                }
            }
            catch (Exception e)
            {
                FunDebug.LogError("Failure in Announcement.downloadDataCompleteCb:\n{0}", e.ToString());
                onResult(AnnounceResult.kExceptionError);
            }
        }
コード例 #15
0
        // Downloading files.
        void downloadResourceFile()
        {
            if (state_ != State.Downloading)
            {
                return;
            }

            if (download_list_.Count <= 0 ||
                (partial_downloading_ && partial_download_list_.Count <= 0))
            {
                updateCachedList();

                download_time_.Stop();
                FunDebug.Log("[Downloader] Took {0:F2}s for downloading all files.",
                             download_time_.ElapsedMilliseconds / 1000f);

                if (partial_downloading_)
                {
                    if (download_list_.Count > 0)
                    {
                        state_ = State.Ready;
                    }
                    else
                    {
                        state_ = State.Completed;
                    }

                    partial_downloading_ = false;
                    FunDebug.Log("[Downloader] Partial downloading completed.");
                }
                else
                {
                    state_ = State.Completed;
                    FunDebug.Log("[Downloader] Download completed.");
                }

                onFinished(DownloadResult.SUCCESS);
            }
            else
            {
                DownloadFileInfo info = null;

                if (partial_downloading_)
                {
                    info = partial_download_list_[0];
                }
                else
                {
                    info = download_list_[0];
                }

                // Check directory
                string path   = target_path_;
                int    offset = info.path.LastIndexOf('/');
                if (offset > 0)
                {
                    path += info.path.Substring(0, offset);
                }

                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                string file_path = target_path_ + info.path;
                if (File.Exists(file_path))
                {
                    File.Delete(file_path);
                }

                // Requests a file.
                string request_url = host_url_ + info.path;
                FunDebug.LogDebug("Download a file - {0}\nSave to {1}\n", request_url, file_path);
                cur_download_path_  = Path.GetDirectoryName(file_path);
                cur_download_path_ += "/" + Path.GetRandomFileName();

                web_client_.DownloadFileAsync(new Uri(request_url), cur_download_path_, info);
            }
        }
コード例 #16
0
        // Checks download file list
        IEnumerator checkFileList(List <DownloadFileInfo> list)
        {
            List <DownloadFileInfo> tmp_list         = new List <DownloadFileInfo>(list);
            List <string>           verify_file_list = new List <string>();
            List <string>           remove_list      = new List <string>();
            Queue <int>             rnd_list         = new Queue <int>();
            bool verify_success = true;
            int  rnd_index      = -1;

            DateTime  cached_time  = File.GetLastWriteTime(target_path_ + kCachedFileName);
            Stopwatch elapsed_time = new Stopwatch();

            elapsed_time.Start();

            delete_file_list_.Clear();

            // Randomly check list
            if (cached_list_.Count > 0)
            {
                int           max_count = cached_list_.Count;
                int           count     = Math.Min(Math.Max(1, max_count / 10), 10);
                System.Random rnd       = new System.Random((int)DateTime.Now.Ticks);

                while (rnd_list.Count < count)
                {
                    rnd_index = rnd.Next(1, max_count + 1) - 1;
                    if (!rnd_list.Contains(rnd_index))
                    {
                        rnd_list.Enqueue(rnd_index);
                    }
                }
                FunDebug.LogDebug("[Downloader] {0} files are randomly selected for check.", rnd_list.Count);

                rnd_index = rnd_list.Count > 0 ? rnd_list.Dequeue() : -1;
            }

            // Checks local files
            int index = 0;

            foreach (DownloadFileInfo file in cached_list_)
            {
                DownloadFileInfo item = list.Find(i => i.path == file.path);
                if (item != null)
                {
                    string   path = target_path_ + file.path;
                    FileInfo info = new FileInfo(path);

                    if (!File.Exists(path) || item.size != info.Length || item.hash != file.hash)
                    {
                        remove_list.Add(file.path);
                        FunDebug.LogWarning("'{0}' file has been changed or deleted.", file.path);
                    }
                    else
                    {
                        string filename = Path.GetFileName(item.path);
                        if (filename[0] == '_' || index == rnd_index ||
                            File.GetLastWriteTime(path).Ticks > cached_time.Ticks)
                        {
                            if (index == rnd_index)
                            {
                                rnd_index = rnd_list.Count > 0 ? rnd_list.Dequeue() : -1;
                            }

                            verify_file_list.Add(file.path);

                            StartCoroutine(MD5Async.Compute(path, item,
                                                            delegate(string p, DownloadFileInfo f, bool is_match)
                            {
                                if (VerifyCallback != null)
                                {
                                    VerifyCallback(p);
                                }

                                verify_file_list.Remove(f.path);

                                if (is_match)
                                {
                                    list.Remove(f);
                                }
                                else
                                {
                                    remove_list.Add(f.path);
                                    verify_success = false;
                                }
                            }
                                                            ));
                        }
                        else
                        {
                            list.Remove(item);
                        }
                    }
                }
                else
                {
                    remove_list.Add(file.path);
                }

                ++index;
            }

            while (verify_file_list.Count > 0)
            {
                yield return(new SleepForSeconds(0.1f));
            }

            removeCachedList(remove_list);

            FunDebug.LogDebug("[Downloader] Random validation has {0}",
                              (verify_success ? "succeeded" : "failed"));

            // Checks all local files
            if (!verify_success)
            {
                foreach (DownloadFileInfo file in cached_list_)
                {
                    DownloadFileInfo item = tmp_list.Find(i => i.path == file.path);
                    if (item != null)
                    {
                        verify_file_list.Add(file.path);

                        string path = target_path_ + file.path;
                        StartCoroutine(MD5Async.Compute(path, item,
                                                        delegate(string p, DownloadFileInfo f, bool is_match)
                        {
                            if (VerifyCallback != null)
                            {
                                VerifyCallback(p);
                            }

                            verify_file_list.Remove(f.path);

                            if (!is_match)
                            {
                                remove_list.Add(f.path);

                                if (!list.Contains(f))
                                {
                                    list.Add(f);
                                }
                            }
                        }
                                                        ));
                    }
                }

                while (verify_file_list.Count > 0)
                {
                    yield return(new SleepForSeconds(0.1f));
                }

                removeCachedList(remove_list);
            }

            elapsed_time.Stop();

            FunDebug.Log("[Downloader] Took {0:F2}s to check local files.",
                         elapsed_time.ElapsedMilliseconds / 1000f);

            total_download_count_ = list.Count;

            foreach (DownloadFileInfo item in list)
            {
                total_download_size_ += item.size;
            }

            // Deletes files
            deleteLocalFiles();

            if (total_download_count_ > 0)
            {
                state_ = State.Ready;

                event_.Add(delegate
                {
                    FunDebug.Log("[Downloader] Ready to download.");

                    if (ReadyCallback != null)
                    {
                        ReadyCallback(total_download_count_, total_download_size_);
                    }
                });
            }
            else
            {
                updateCachedList();

                state_ = State.Completed;
                FunDebug.Log("[Downloader] All resources are up to date.");
                onFinished(DownloadResult.SUCCESS);
            }
        }