public static FunapiTransport CreateTransport(TransportProtocol protocol, FunEncoding encoding = FunEncoding.kJson, EncryptionType encryption = EncryptionType.kDefaultEncryption) { if (data_ == null) { DebugUtils.Log("There's no config data. You should call FunapiConfig.Load first."); return(null); } string str_protocol; if (protocol == TransportProtocol.kTcp) { str_protocol = "tcp"; } else if (protocol == TransportProtocol.kUdp) { str_protocol = "udp"; } else if (protocol == TransportProtocol.kHttp) { str_protocol = "http"; } else { DebugUtils.Log("CreateTransport - Invalid protocol. protocol: {0}", protocol); return(null); } string str_ip = string.Format("{0}_server_ip", str_protocol); string str_port = string.Format("{0}_server_port", str_protocol); if (!data_.ContainsKey(str_ip) || !data_.ContainsKey(str_port)) { DebugUtils.Log("CreateTransport - Can't find values with '{0}'", str_protocol); return(null); } string hostname_or_ip = data_[str_ip] as string; UInt16 port = Convert.ToUInt16(data_[str_port]); if (hostname_or_ip.Length <= 0 || port == 0) { DebugUtils.Log("CreateTransport - Invalid value. ip:{0} port:{1} encoding:{2}", hostname_or_ip, port, encoding); return(null); } if (protocol == TransportProtocol.kTcp) { FunapiTcpTransport transport = new FunapiTcpTransport(hostname_or_ip, port, encoding); if (data_.ContainsKey("disable_nagle")) { transport.DisableNagle = (bool)data_["disable_nagle"]; } if (encryption != EncryptionType.kDefaultEncryption) { transport.SetEncryption(encryption); } return(transport); } else if (protocol == TransportProtocol.kUdp) { FunapiUdpTransport transport = new FunapiUdpTransport(hostname_or_ip, port, encoding); if (encryption != EncryptionType.kDefaultEncryption) { transport.SetEncryption(encryption); } return(transport); } else if (protocol == TransportProtocol.kHttp) { bool with_https = false; if (data_.ContainsKey("http_with_secure")) { with_https = (bool)data_["http_with_secure"]; } FunapiHttpTransport transport = new FunapiHttpTransport(hostname_or_ip, port, with_https, encoding); if (encryption != EncryptionType.kDefaultEncryption) { transport.SetEncryption(encryption); } return(transport); } return(null); }
private void DownloadDataCompleteCb(object sender, DownloadDataCompletedEventArgs ar) { try { if (ar.Error != null) { DebugUtils.Log("Exception Error: {0}", ar.Error); OnResultCallback(AnnounceResult.kExceptionError); DebugUtils.Assert(false); } else { // Parse json string data = Encoding.UTF8.GetString(ar.Result); Dictionary <string, object> json = Json.Deserialize(data) as Dictionary <string, object>; if (json == null) { DebugUtils.Log("Deserialize json failed. json: {0}", data); OnResultCallback(AnnounceResult.kInvalidJson); return; } DebugUtils.Assert(json.ContainsKey("list")); List <object> list = json["list"] as List <object>; if (list == null || list.Count <= 0) { DebugUtils.Log("Invalid announcement list. list: {0}", list); OnResultCallback(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); } } DebugUtils.Log("Announcement has been updated. total count: {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); DebugUtils.Log("Download url: {0}", item.Key); } else { OnResultCallback(AnnounceResult.kSuccess); } } } catch (Exception e) { DebugUtils.Log("Failure in DownloadDataCompleteCb: {0}", e.ToString()); OnResultCallback(AnnounceResult.kExceptionError); } }
// Callback function for list of files private void DownloadDataCompleteCb(object sender, DownloadDataCompletedEventArgs ar) { mutex_.WaitOne(); bool failed = false; try { if (ar.Error != null) { DebugUtils.Log("Exception Error: {0}", ar.Error); DebugUtils.Assert(false); failed = true; } else { // It can be true when CancelAsync() called in Stop(). if (ar.Cancelled) { return; } // Parse json string data = Encoding.UTF8.GetString(ar.Result); Dictionary <string, object> json = Json.Deserialize(data) as Dictionary <string, object>; //DebugUtils.Log("Json data >> {0}", data); // Redirect url if (json.ContainsKey("url")) { string url = json["url"] as string; if (url[url.Length - 1] != '/') { url += "/"; } host_url_ = url; DebugUtils.Log("Redirect download url: {0}", host_url_); } List <object> list = json["data"] as List <object>; if (list.Count <= 0) { DebugUtils.Log("Invalid list data. List count is 0."); DebugUtils.Assert(false); failed = true; } else { download_list_.Clear(); 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["md5"] as string; if (node.ContainsKey("md5_front")) { info.hash_front = node["md5_front"] as string; } else { info.hash_front = ""; } download_list_.Add(info); } // Checks files manager_.AddEvent(() => manager_.StartCoroutine(CheckFileList(download_list_))); } } } catch (Exception e) { DebugUtils.Log("Failure in DownloadDataCompleteCb: {0}", e.ToString()); failed = true; } finally { mutex_.ReleaseMutex(); } if (failed) { Stop(); } }
// Callback function for downloaded file. private void DownloadFileCompleteCb(object sender, System.ComponentModel.AsyncCompletedEventArgs ar) { mutex_.WaitOne(); bool failed = false; try { // It can be true when CancelAsync() called in Stop(). if (ar.Cancelled) { return; } if (ar.Error != null) { DebugUtils.Log("Exception Error: {0}", ar.Error); DebugUtils.Assert(false); failed = true; } else { var info = (DownloadFileInfo)ar.UserState; if (info == null) { DebugUtils.Log("DownloadFileInfo object is null."); failed = true; } else { string path = target_path_ + info.path; File.Move(cur_download_path_, path); ++cur_download_count_; cur_download_size_ += info.size; download_list_.Remove(info); cached_list_.Add(info); DownloadResourceFile(); } } } catch (Exception e) { DebugUtils.Log("Failure in DownloadFileCompleteCb: {0}", e.ToString()); failed = true; } finally { mutex_.ReleaseMutex(); } if (failed) { web_client_.Dispose(); File.Delete(cur_download_path_); if (retry_download_count_ < kMaxRetryCount) { ++retry_download_count_; FunapiManager.instance.StartCoroutine(AsyncDownloadFile()); } else { Stop(); } } }
// Checks download file list private 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); check_time_ = DateTime.Now; 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); } } DebugUtils.DebugLog("Random check file count is {0}", 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); } 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); MD5Async.Compute(ref path, ref 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 WaitForSeconds(0.1f)); } RemoveCachedList(remove_list); DebugUtils.Log("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; MD5Async.Compute(ref path, ref 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 WaitForSeconds(0.1f)); } RemoveCachedList(remove_list); } TimeSpan span = new TimeSpan(DateTime.Now.Ticks - check_time_.Ticks); DebugUtils.Log("File check total time - {0:F2}s", span.TotalMilliseconds / 1000f); total_download_count_ = list.Count; foreach (DownloadFileInfo item in list) { total_download_size_ += item.size; } if (total_download_count_ > 0) { state_ = State.Ready; if (ReadyCallback != null) { ReadyCallback(total_download_count_, total_download_size_); } } else { DeleteLocalFiles(); UpdateCachedList(); state_ = State.Completed; DebugUtils.Log("All resources are up to date."); OnFinishedCallback(DownloadResult.SUCCESS); } }