Exemplo n.º 1
0
func Start(dir string, thrustWindowLoder *window.Window) {

	var err error
	IosLog("start")

	defer func() {
		if r := recover(); r != nil {
			log.Error("Recovered", r)
			panic(r)
		}
	}()

	if dir != "" {
		fmt.Println("dir", dir)
		*utils.Dir = dir
	}
	IosLog("dir:" + dir)
	fmt.Println("utils.Dir", *utils.Dir)

	fmt.Println("dcVersion:", consts.VERSION)
	log.Debug("dcVersion: %v", consts.VERSION)

	// читаем config.ini
	configIni := make(map[string]string)
	configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
	} else {
		configIni, err = configIni_.GetSection("default")
	}

	// убьем ранее запущенный Dcoin
	if !utils.Mobile() {
		fmt.Println("kill dcoin.pid")
		if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
			dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			var pidMap map[string]string
			err = json.Unmarshal(dat, &pidMap)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			fmt.Println("old PID ("+*utils.Dir+"/dcoin.pid"+"):", pidMap["pid"])

			utils.DB, err = utils.NewDbConnect(configIni)

			err = KillPid(pidMap["pid"])
			if nil != err {
				fmt.Println(err)
				log.Error("KillPid %v", utils.ErrInfo(err))
			}
			if fmt.Sprintf("%s", err) != "null" {
				fmt.Println(fmt.Sprintf("%s", err))
				// даем 15 сек, чтобы завершиться предыдущему процессу
				for i := 0; i < 15; i++ {
					log.Debug("waiting killer %d", i)
					if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
						fmt.Println("waiting killer")
						utils.Sleep(1)
					} else { // если dcoin.pid нет, значит завершился
						break
					}
				}
			}
		}
	}

	// сохраним текущий pid и версию
	if !utils.Mobile() {
		pid := os.Getpid()
		PidAndVer, err := json.Marshal(map[string]string{"pid": utils.IntToStr(pid), "version": consts.VERSION})
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		err = ioutil.WriteFile(*utils.Dir+"/dcoin.pid", PidAndVer, 0644)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
		}
	}

	controllers.SessInit()
	controllers.ConfigInit()
	daemons.ConfigInit()

	go func() {
		utils.DB, err = utils.NewDbConnect(configIni)
		log.Debug("%v", utils.DB)
		IosLog("utils.DB:" + fmt.Sprintf("%v", utils.DB))
		if err != nil {
			IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}()

	f, err := os.OpenFile(*utils.Dir+"/dclog.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
		panic(err)
		os.Exit(1)
	}
	defer f.Close()
	IosLog("configIni:" + fmt.Sprintf("%v", configIni))
	var backend *logging.LogBackend
	switch configIni["log_output"] {
	case "file":
		backend = logging.NewLogBackend(f, "", 0)
	case "console":
		backend = logging.NewLogBackend(os.Stderr, "", 0)
	case "file_console":
		//backend = logging.NewLogBackend(io.MultiWriter(f, os.Stderr), "", 0)
	default:
		backend = logging.NewLogBackend(f, "", 0)
	}
	backendFormatter := logging.NewBackendFormatter(backend, format)
	backendLeveled := logging.AddModuleLevel(backendFormatter)

	logLevel_ := "DEBUG"
	if *utils.LogLevel == "" {
		logLevel_ = configIni["log_level"]
	} else {
		logLevel_ = *utils.LogLevel
	}

	logLevel, err := logging.LogLevel(logLevel_)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
	}

	log.Debug("logLevel: %v", logLevel)
	backendLeveled.SetLevel(logLevel, "")
	logging.SetBackend(backendLeveled)

	rand.Seed(time.Now().UTC().UnixNano())

	// если есть OldFileName, значит работаем под именем tmp_dc и нужно перезапуститься под нормальным именем
	log.Error("OldFileName %v", *utils.OldFileName)
	if *utils.OldFileName != "" {

		// вначале нужно обновить БД в зависимости от версии
		dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		var pidMap map[string]string
		err = json.Unmarshal(dat, &pidMap)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("OldFileName %v", *utils.OldFileName)
		err = utils.CopyFileContents(*utils.Dir+`/dc.tmp`, *utils.OldFileName)
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		// ждем подключения к БД
		for {
			if utils.DB == nil || utils.DB.DB == nil {
				utils.Sleep(1)
				continue
			}
			break
		}
		if len(pidMap["version"]) > 0 {
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("1.0.2b5") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN analytics_disabled smallint")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN analytics_disabled smallint`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("2.0.1b2") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
		}
		err = utils.DB.Close()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		fmt.Println("DB Closed")
		err = os.Remove(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("dc.tmp %v", *utils.Dir+`/dc.tmp`)
		err = exec.Command(*utils.OldFileName, "-dir", *utils.Dir).Start()
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		log.Debug("OldFileName %v", *utils.OldFileName)
		os.Exit(1)
	}
	// откат БД до указанного блока
	if *utils.RollbackToBlockId > 0 {
		utils.DB, err = utils.NewDbConnect(configIni)
		parser := new(dcparser.Parser)
		parser.DCDB = utils.DB
		err = parser.RollbackToBlockId(*utils.RollbackToBlockId)
		if err != nil {
			fmt.Println(err)
			panic(err)
		}
		fmt.Print("complete")
		os.Exit(0)
	}

	log.Debug("public")
	IosLog("public")
	if _, err := os.Stat(*utils.Dir + "/public"); os.IsNotExist(err) {
		err = os.Mkdir(*utils.Dir+"/public", 0755)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}

	log.Debug("daemonsStart")
	IosLog("daemonsStart")

	daemons.StartDaemons()

	IosLog("MonitorDaemons")
	// мониторинг демонов
	daemonsTable := make(map[string]string)
	go func() {
		for {
			daemonNameAndTime := <-daemons.MonitorDaemonCh
			daemonsTable[daemonNameAndTime[0]] = daemonNameAndTime[1]
			if utils.Time()%10 == 0 {
				log.Debug("daemonsTable: %v\n", daemonsTable)
			}
		}
	}()

	// сигналы демонам для выхода
	IosLog("signals")
	stopdaemons.Signals()

	utils.Sleep(1)

	// мониторим сигнал из БД о том, что демонам надо завершаться
	go stopdaemons.WaitStopTime()

	BrowserHttpHost := "http://localhost:8089"
	HandleHttpHost := ""
	ListenHttpHost := ":" + *utils.ListenHttpHost
	go func() {
		// уже прошли процесс инсталяции, где юзер указал БД и был перезапуск кошелька
		if len(configIni["db_type"]) > 0 && !utils.Mobile() {
			for {
				// ждем, пока произойдет подключение к БД в другой гоурутине
				if utils.DB == nil || utils.DB.DB == nil {
					utils.Sleep(1)
					fmt.Println("wait DB")
				} else {
					break
				}
			}
			fmt.Println("GET http host")
			BrowserHttpHost, HandleHttpHost, ListenHttpHost = GetHttpHost()
			// для биржы нужен хост или каталог, поэтому нужно подключение к БД
			exhangeHttpListener(HandleHttpHost)
			// для ноды тоже нужна БД
			tcpListener()
		}
		IosLog(fmt.Sprintf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v", BrowserHttpHost, HandleHttpHost, ListenHttpHost))
		fmt.Printf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v\n", BrowserHttpHost, HandleHttpHost, ListenHttpHost)
		// включаем листинг веб-сервером для клиентской части
		http.HandleFunc(HandleHttpHost+"/", controllers.Index)
		http.HandleFunc(HandleHttpHost+"/content", controllers.Content)
		http.HandleFunc(HandleHttpHost+"/ajax", controllers.Ajax)
		http.HandleFunc(HandleHttpHost+"/tools", controllers.Tools)
		http.HandleFunc(HandleHttpHost+"/cf/", controllers.IndexCf)
		http.HandleFunc(HandleHttpHost+"/cf/content", controllers.ContentCf)
		http.Handle(HandleHttpHost+"/public/", noDirListing(http.FileServer(http.Dir(*utils.Dir))))
		http.Handle(HandleHttpHost+"/static/", http.FileServer(&assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, Prefix: ""}))

		log.Debug("ListenHttpHost", ListenHttpHost)

		IosLog(fmt.Sprintf("ListenHttpHost: %v", ListenHttpHost))

		fmt.Println("ListenHttpHost", ListenHttpHost)

		httpListener(ListenHttpHost, BrowserHttpHost)

		if *utils.Console == 0 && !utils.Mobile() {
			utils.Sleep(1)
			if thrustWindowLoder != nil {
				thrustWindowLoder.Close()
				thrustWindow := thrust.NewWindow(thrust.WindowOptions{
					RootUrl: BrowserHttpHost,
					Size:    commands.SizeHW{Width: 1024, Height: 600},
				})
				thrustWindow.HandleEvent("*", func(cr commands.EventResult) {
					fmt.Println("HandleEvent", cr)
				})
				thrustWindow.HandleRemote(func(er commands.EventResult, this *window.Window) {
					fmt.Println("RemoteMessage Recieved:", er.Message.Payload)
					openBrowser(er.Message.Payload)
					// Keep in mind once we have the message, lets say its json of some new type we made,
					// We can unmarshal it to that type.
					// Same goes for the other way around.
					this.SendRemoteMessage("boop")
				})
				thrustWindow.Show()
				thrustWindow.Focus()
			} else {
				openBrowser(BrowserHttpHost)
			}
		}
	}()

	// ожидает появления свежих записей в чате, затем ждет появления коннектов
	// (заносятся из демеона connections и от тех, кто сам подключился к ноде)
	go utils.ChatOutput(utils.ChatNewTx)

	log.Debug("ALL RIGHT")
	IosLog("ALL RIGHT")
	fmt.Println("ALL RIGHT")
	utils.Sleep(3600 * 24 * 90)
	log.Debug("EXIT")
}
Exemplo n.º 2
0
func (c *Controller) AlertMessage() (string, error) {

	if c.SessRestricted != 0 {
		return "", nil
	}

	c.r.ParseForm()
	if ok, _ := regexp.MatchString(`install`, c.r.FormValue("tpl_name")); ok {
		return "", nil
	}

	show := false
	// проверим, есть ли сообщения от админа
	data, err := c.OneRow("SELECT * FROM alert_messages WHERE close  =  0 ORDER BY id DESC").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	var message map[string]string
	var adminMessage string
	if len(data["message"]) > 0 {
		err = json.Unmarshal([]byte(data["message"]), &message)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if len(message[utils.Int64ToStr(c.LangInt)]) > 0 {
			adminMessage = message[utils.Int64ToStr(c.LangInt)]
		} else {
			adminMessage = message["gen"]
		}
		if data["currency_list"] != "ALL" {
			// проверим, есть ли у нас обещанные суммы с такой валютой
			promisedAmount, err := c.Single("SELECT id FROM promised_amount WHERE currency_id IN (" + data["currency_list"] + ")").Int64()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			if promisedAmount > 0 {
				show = true
			}
		} else {
			show = true
		}
	}
	result := ""
	if show {
		result += `<script>
			$('#close_alert').bind('click', function () {
				$.post( 'ajax?controllerName=closeAlert', {
					'id' : '` + data["id"] + `'
				} );
			});
			</script>
			 <div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
			 <h4>Warning!</h4>
			    ` + adminMessage + `
			  </div>`
	}

	// сообщение о новой версии движка
	myVer, err := c.Single("SELECT current_version FROM info_block").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// возможны 2 сценария:
	// 1. информация о новой версии есть в блоках
	newVer, err := c.GetList("SELECT version FROM new_version WHERE alert  =  1").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	newMaxVer := "0"
	for i := 0; i < len(newVer); i++ {
		if utils.VersionOrdinal(newVer[i]) > utils.VersionOrdinal(myVer) && newMaxVer == "0" {
			newMaxVer = newVer[i]
		}
		if utils.VersionOrdinal(newVer[i]) > utils.VersionOrdinal(newMaxVer) && newMaxVer != "0" {
			newMaxVer = newVer[i]
		}
	}
	var newVersion string
	if newMaxVer != "0" {
		newVersion = strings.Replace(c.Lang["new_version"], "[ver]", newMaxVer, -1)
	}

	// для пулов и ограниченных юзеров выводим сообщение без кнопок
	if (c.Community || c.SessRestricted != 0) && newMaxVer != "0" {
		newVersion = strings.Replace(c.Lang["new_version_pulls"], "[ver]", newMaxVer, -1)
	}

	if newMaxVer != "0" && len(myVer) > 0 {
		result += `<script>
				$('#btn_install').bind('click', function () {
					$('#new_version_text').text('Please wait');
					$.post( 'ajax?controllerName=installNewVersion', {}, function(data) {
						$('#new_version_text').text(data);
					});
				});
				$('#btn_upgrade').bind('click', function () {
					$('#new_version_text').text('Please wait');
					$.post( 'ajax?controllerName=upgradeToNewVersion', {}, function(data) {
						$('#new_version_text').text(data);
					});
				});
			</script>

			<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
			    <h4>Warning!</h4>
			   <div id='new_version_text'>` + newVersion + `</div>
			 </div>`
	}

	if c.SessRestricted == 0 && (!c.Community || c.PoolAdmin) {
		myMinerId, err := c.GetMinerId(c.SessUserId)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		// если юзер уже майнер, то у него должно быть настроено точное время
		if myMinerId > 0 {
			networkTime, err := utils.GetNetworkTime()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			diff := int64(math.Abs(float64(utils.Time() - networkTime.Unix())))
			if diff > c.Variables.Int64["alert_error_time"] {
				alertTime := strings.Replace(c.Lang["alert_time"], "[sec]", utils.Int64ToStr(diff), -1)
				result += `<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
				     <h4>Warning!</h4>
				     <div>` + alertTime + `</div>
				     </div>`
			}
		}
	}

	if c.SessRestricted == 0 {
		// после обнуления таблиц my_node_key будет пуст
		// получим время из последнего блока
		myNodePrivateKey, err := c.GetNodePrivateKey(c.MyPrefix)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		minerId, err := c.GetMinerId(c.SessUserId)
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// возможно юзер новенький на пуле и у него разные нод-ключи
		nodePublicKey, err := c.GetNodePublicKey(c.SessUserId)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		myNodePublicKey, err := c.GetMyNodePublicKey(c.MyPrefix)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if (len(myNodePrivateKey) == 0 && minerId > 0) || (string(nodePublicKey) != myNodePublicKey && len(nodePublicKey) > 0) {
			result += `<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
				     <h4>Warning!</h4>
				     <div>` + c.Lang["alert_change_node_key"] + `</div>
				     </div>`
		}

	}

	// просто информируем, что в данном разделе у юзера нет прав
	skipCommunity := []string{"nodeConfig", "nulling", "startStop"}
	skipRestrictedUsers := []string{"nodeConfig", "changeNodeKey", "nulling", "startStop", "cashRequestIn", "cashRequestOut", "upgrade", "notifications", "interface"}
	if (!c.NodeAdmin && utils.InSliceString(c.TplName, skipCommunity)) || (c.SessRestricted != 0 && utils.InSliceString(c.TplName, skipRestrictedUsers)) {
		result += `<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
			  <h4>Warning!</h4>
			  <div>` + c.Lang["permission_denied"] + `</div>
			  </div>`
	}

	// информируем, что у юзера нет прав и нужно стать майнером
	minersOnly := []string{"myCfProjects", "newCfProject", "cashRequestIn", "cashRequestOut", "changeNodeKey", "voting", "geolocation", "promisedAmountList", "promisedAmountAdd", "holidaysList", "newHolidays", "points", "tasks", "changeHost", "newUser", "changeCommission"}
	if utils.InSliceString(c.TplName, minersOnly) {
		minerId, err := c.Single("SELECT miner_id FROM users LEFT JOIN miners_data ON users.user_id  =  miners_data.user_id WHERE users.user_id  =  ?", c.SessUserId).Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if minerId == 0 {
			result += `<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
				 <h4>Warning!</h4>
				 <div>` + c.Lang["only_for_miners"] + `</div>
				 </div>`
		}
	}

	// информируем, что необходимо вначале сменить праймари-ключ
	logId, err := c.Single("SELECT log_id FROM users WHERE user_id  =  ?", c.SessUserId).Int64()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	if logId == 0 {
		text := ""
		// проверим, есть ли запросы на смену в тр-ях
		lastTx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"ChangePrimaryKey"}), 1, c.TimeFormat)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if len(lastTx) == 0 { // юзер еще не начинал смену ключа
			text = c.Lang["alert_change_primary_key"]
		} else if len(lastTx[0]["error"]) > 0 || len(lastTx[0]["queue_tx"]) > 0 || len(lastTx[0]["tx"]) > 0 || utils.Time()-utils.StrToInt64(lastTx[0]["time_int"]) > 3600 {
			text = c.Lang["please_try_again_change_key"]
		} else {
			text = c.Lang["please_wait_changing_key"]
		}
		result += `<div class="alert alert-danger alert-dismissable" style='margin-top: 30px'><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
				  <h4>` + c.Lang["warning"] + `</h4>
				  <div>` + text + `</div>
				  </div>`
	}

	return result, nil
}