예제 #1
0
func main() {
	log.Printf("Server pid=%d started with processes: %d", os.Getpid(), runtime.GOMAXPROCS(runtime.NumCPU()))

	var configfile = flag.String("config", "./tinode.conf", "Path to config file.")
	// Path to static content.
	var staticPath = flag.String("static_data", "", "Path to /static data for the server.")
	var listenOn = flag.String("listen", "", "Override tinode.conf address and port to listen on.")
	flag.Parse()

	log.Printf("Using config from: '%s'", *configfile)

	var config configType
	if raw, err := ioutil.ReadFile(*configfile); err != nil {
		log.Fatal(err)
	} else if err = json.Unmarshal(raw, &config); err != nil {
		log.Fatal(err)
	}

	if *listenOn != "" {
		config.Listen = *listenOn
	}

	var err = store.Open(config.Adapter, string(config.AdapterConfig))
	if err != nil {
		log.Fatal("Failed to connect to DB: ", err)
	}
	defer func() {
		store.Close()
		log.Println("Closed database connection(s)")
	}()

	// Keep inactive LP sessions for 70 seconds
	globals.sessionStore = NewSessionStore(IDLETIMEOUT + 15*time.Second)
	globals.hub = newHub()

	// Serve static content from the directory in -static_data flag if that's
	// available, if not assume current dir.
	if *staticPath != "" {
		http.Handle("/x/", http.StripPrefix("/x/", http.FileServer(http.Dir(*staticPath))))
	} else {
		path, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}
		http.Handle("/x/", http.StripPrefix("/x/", http.FileServer(http.Dir(path+"/static"))))
	}

	// Streaming channels
	// Handle websocket clients. WS must come up first, so reconnecting clients won't fall back to LP
	http.HandleFunc("/v0/channels", serveWebSocket)
	// Handle long polling clients
	http.HandleFunc("/v0/channels/lp", serveLongPoll)

	log.Printf("Listening on [%s]", config.Listen)
	if err := listenAndServe(config.Listen, signalHandler()); err != nil {
		log.Fatal(err)
	}
	log.Println("All done, good bye")
}
예제 #2
0
func gen_rethink(reset bool, dbsource string, data *Data) {
	var err error

	log.Println("Opening DB...")

	err = store.Open("rethinkdb", dbsource)
	if err != nil {
		log.Fatal("Failed to connect to DB: ", err)
	}
	defer store.Close()

	log.Println("Initializing DB...")

	err = store.InitDb(reset)
	if err != nil {
		if strings.Contains(err.Error(), " already exists") {
			log.Println("DB already exists, NOT reinitializing")
		} else {
			log.Fatal("Failed to init DB: ", err)
		}
	} else {
		log.Println("DB successfully initialized")

	}
	if data.Users == nil {
		log.Println("No data provided, stopping")
		return
	}

	nameIndex := make(map[string]string, len(data.Users))

	log.Println("Generating users...")

	for _, uu := range data.Users {
		if uu["createdAt"] != nil {

		}
		user := types.User{
			State:    int(uu["state"].(float64)),
			Username: uu["username"].(string),
			Access: types.DefaultAccess{
				Auth: types.ModePublic,
				Anon: types.ModeNone,
			},
			Public: uu["public"],
		}
		user.CreatedAt = getCreatedTime(uu["createdAt"])

		// store.Users.Create will subscribe user to !me topic but won't create a !me topic
		if _, err := store.Users.Create(&user, "basic",
			uu["username"].(string)+":"+uu["passhash"].(string), uu["private"]); err != nil {
			log.Fatal(err)
		}

		nameIndex[user.Username] = user.Id

		log.Printf("Created user '%s' as %s (%d)", user.Username, user.Id, user.Uid())
	}

	log.Println("Generating group topics...")

	for _, gt := range data.Grouptopics {
		name := genTopicName()
		nameIndex[gt["name"].(string)] = name

		topic := &types.Topic{Name: name, Public: gt["public"]}
		var owner types.Uid
		if gt["owner"] != nil {
			owner = types.ParseUid(nameIndex[gt["owner"].(string)])
			topic.GiveAccess(owner, types.ModeFull, types.ModeFull)
		}
		topic.CreatedAt = getCreatedTime(gt["createdAt"])

		if err = store.Topics.Create(topic, owner, gt["private"]); err != nil {
			log.Fatal(err)
		}
		log.Printf("Created topic '%s' as %s", gt["name"].(string), name)
	}

	log.Println("Generating P2P subscriptions...")

	p2pIndex := map[string][]map[string]interface{}{}

	for _, ss := range data.Subscriptions {
		u1 := ss["user"].(string)
		u2 := ss["topic"].(string)

		if u2[0] == '*' {
			// skip group topics
			continue
		}

		var pair string
		var idx int
		if u1 < u2 {
			pair = u1 + ":" + u2
			idx = 0
		} else {
			pair = u2 + ":" + u1
			idx = 1
		}
		if _, ok := p2pIndex[pair]; !ok {
			p2pIndex[pair] = make([]map[string]interface{}, 2)
		}

		p2pIndex[pair][idx] = ss
	}

	log.Printf("Collected p2p pairs: %d\n", len(p2pIndex))

	for pair, subs := range p2pIndex {
		uid1 := types.ParseUid(nameIndex[subs[0]["user"].(string)])
		uid2 := types.ParseUid(nameIndex[subs[1]["user"].(string)])
		topic := uid1.P2PName(uid2)
		created0 := getCreatedTime(subs[0]["createdAt"])
		created1 := getCreatedTime(subs[1]["createdAt"])
		var s0want, s0given, s1want, s1given types.AccessMode
		if err := s0want.UnmarshalText([]byte(subs[0]["modeWant"].(string))); err != nil {
			log.Fatal(err)
		}
		if err := s0given.UnmarshalText([]byte(subs[0]["modeHave"].(string))); err != nil {
			log.Fatal(err)
		}

		if err := s1want.UnmarshalText([]byte(subs[1]["modeWant"].(string))); err != nil {
			log.Fatal(err)
		}
		if err := s1given.UnmarshalText([]byte(subs[1]["modeHave"].(string))); err != nil {
			log.Fatal(err)
		}

		log.Printf("Processing %s (%s), %s, %s", pair, topic, uid1.String(), uid2.String())
		err := store.Topics.CreateP2P(
			&types.Subscription{
				ObjHeader: types.ObjHeader{CreatedAt: created0},
				User:      uid1.String(),
				Topic:     topic,
				ModeWant:  s0want,
				ModeGiven: s0given,
				Private:   subs[0]["private"]},
			&types.Subscription{
				ObjHeader: types.ObjHeader{CreatedAt: created1},
				User:      uid2.String(),
				Topic:     topic,
				ModeWant:  s1want,
				ModeGiven: s1given,
				Private:   subs[1]["private"]})

		if err != nil {
			log.Fatal(err)
		}
	}

	log.Println("Generating group subscriptions...")

	for _, ss := range data.Subscriptions {

		u1 := nameIndex[ss["user"].(string)]
		u2 := nameIndex[ss["topic"].(string)]

		var want, given types.AccessMode
		if err := want.UnmarshalText([]byte(ss["modeWant"].(string))); err != nil {
			log.Fatal(err)
		}
		if err := given.UnmarshalText([]byte(ss["modeHave"].(string))); err != nil {
			log.Fatal(err)
		}

		// Define topic name
		name := u2
		if !types.ParseUid(u2).IsZero() {
			// skip p2p subscriptions
			continue
		}

		log.Printf("Sharing '%s' with '%s'", ss["topic"].(string), ss["user"].(string))

		if err = store.Subs.Create(&types.Subscription{
			ObjHeader: types.ObjHeader{CreatedAt: getCreatedTime(ss["createdAt"])},
			User:      u1,
			Topic:     name,
			ModeWant:  want,
			ModeGiven: given,
			Private:   ss["private"]}); err != nil {

			log.Fatal(err)
		}
	}

	log.Println("Generating messages...")

	rand.Seed(time.Now().UnixNano())
	seqIds := map[string]int{}
	var oldFrom types.Uid
	var oldTopic string
	toInsert := 80
	// Starting 4 days ago
	timestamp := time.Now().UTC().Round(time.Millisecond).Add(time.Second * time.Duration(-3600*24*4))
	for i := 0; i < toInsert; i++ {

		sub := data.Subscriptions[rand.Intn(len(data.Subscriptions))]
		topic := nameIndex[sub["topic"].(string)]
		from := types.ParseUid(nameIndex[sub["user"].(string)])
		if topic == oldTopic && from == oldFrom {
			toInsert++
			continue
		}
		oldTopic, oldFrom = topic, from

		if uid := types.ParseUid(topic); !uid.IsZero() {
			topic = uid.P2PName(from)
		}

		seqIds[topic]++
		seqId := seqIds[topic]
		str := data.Messages[rand.Intn(len(data.Messages))]
		// Max time between messages is 2 hours, averate - 1 hour, time is increasing as seqId increases
		timestamp = timestamp.Add(time.Second * time.Duration(rand.Intn(3600*2)))
		msg := types.Message{
			ObjHeader: types.ObjHeader{CreatedAt: timestamp},
			SeqId:     seqId,
			Topic:     topic,
			From:      from.String(),
			Content:   str}
		if err = store.Messages.Save(&msg); err != nil {
			log.Fatal(err)
		}
		log.Printf("Message %d at %v to '%s' '%s'", msg.SeqId, msg.CreatedAt, topic, str)
	}
}