mirror of
https://github.com/Cernobor/oko-server.git
synced 2025-02-24 08:27:17 +00:00
dual offline/online, map info
* Server provides map info with zoom, default center and paths to both downloadable pack and tile url template.
This commit is contained in:
parent
caeb5c9198
commit
08a203e4a6
16
main.go
16
main.go
@ -8,6 +8,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"cernobor.cz/oko-server/models"
|
||||
"cernobor.cz/oko-server/server"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -17,6 +18,9 @@ func main() {
|
||||
tilepackFileArg := flag.String("tilepack", "", "File that will be sent to clients when they request a tile pack. Required.")
|
||||
apkFileArg := flag.String("apk", "", "APK file with the client app. If not specified, no APK will be available (404).")
|
||||
reinitDBArg := flag.Bool("reinit-db", false, "Reinitializes the DB, which means all the tables will be recreated, deleting all data.")
|
||||
minZoomArg := flag.Int("min-zoom", 1, "Minimum zoom that will be sent to clients.")
|
||||
defaultCenterLatArg := flag.Float64("default-center-lat", 0, "Latitude of the default map center.")
|
||||
defaultCenterLngArg := flag.Float64("default-center-lng", 0, "Longitude of the default map center.")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@ -26,7 +30,17 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
s := server.New(*dbFileArg, *tilepackFileArg, *apkFileArg, *reinitDBArg)
|
||||
s := server.New(server.ServerConfig{
|
||||
DbPath: *dbFileArg,
|
||||
TilepackPath: *tilepackFileArg,
|
||||
ApkPath: *apkFileArg,
|
||||
ReinitDB: *reinitDBArg,
|
||||
MinZoom: *minZoomArg,
|
||||
DefaultCenter: models.Coords{
|
||||
Lat: *defaultCenterLatArg,
|
||||
Lng: *defaultCenterLngArg,
|
||||
},
|
||||
})
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)
|
||||
|
@ -33,6 +33,19 @@ type Feature struct {
|
||||
|
||||
// transport objects
|
||||
|
||||
type Coords struct {
|
||||
Lat float64 `json:"lat"`
|
||||
Lng float64 `json:"lng"`
|
||||
}
|
||||
|
||||
type MapInfo struct {
|
||||
MapPackPath string `json:"map_pack_path"`
|
||||
MapPackSize int64 `json:"map_pack_size"`
|
||||
TilePathTemplate string `json:"tile_path_template"`
|
||||
MinZoom int `json:"min_zoom"`
|
||||
DefaultCenter Coords `json:"default_center"`
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
Create []Feature `json:"create"`
|
||||
CreatedPhotos map[FeatureID][]string `json:"created_photos"`
|
||||
@ -50,7 +63,7 @@ type HandshakeChallenge struct {
|
||||
type HandshakeResponse struct {
|
||||
ID UserID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TilePackPath string `json:"tile_pack_path"`
|
||||
MapInfo MapInfo `json:"map_info"`
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
|
@ -4,13 +4,13 @@ const (
|
||||
URIPing = "/ping"
|
||||
URIHardFail = "/hard-fail"
|
||||
URISoftFail = "/soft-fail"
|
||||
URITilepack = "/tilepack"
|
||||
URIMapPack = "/mappack"
|
||||
URIHandshake = "/handshake"
|
||||
URIData = "/data"
|
||||
URIDataPeople = "/data/people"
|
||||
URIDataExtra = "/data/extra"
|
||||
URIDataFeatures = "/data/features"
|
||||
URIDataFeaturesPhoto = "/data/features/:feature/photos/:photo"
|
||||
URITileserverRoot = "/tileserver"
|
||||
URITileserver = URITileserverRoot + "/*x"
|
||||
URITileTemplate = URITileserverRoot + "/map/tiles/{z}/{x}/{y}.pbf"
|
||||
)
|
@ -86,7 +86,7 @@ func (s *Server) setupRouter() *gin.Engine {
|
||||
})
|
||||
|
||||
// resources
|
||||
router.GET(URITilepack, s.handleGETTilepack)
|
||||
router.GET(URIMapPack, s.handleGETTilepack)
|
||||
|
||||
// API
|
||||
router.POST(URIHandshake, s.handlePOSTHandshake)
|
||||
@ -131,7 +131,13 @@ func (s *Server) handlePOSTHandshake(gc *gin.Context) {
|
||||
gc.JSON(http.StatusOK, models.HandshakeResponse{
|
||||
ID: id,
|
||||
Name: hs.Name,
|
||||
TilePackPath: URITilepack,
|
||||
MapInfo: models.MapInfo{
|
||||
MapPackPath: URIMapPack,
|
||||
MapPackSize: s.mapPackSize,
|
||||
TilePathTemplate: URITileTemplate,
|
||||
MinZoom: s.config.MinZoom,
|
||||
DefaultCenter: s.config.DefaultCenter,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "embed"
|
||||
@ -29,6 +30,7 @@ type Server struct {
|
||||
log *logrus.Logger
|
||||
ctx context.Context
|
||||
tileserverSvSet *mbsh.ServiceSet
|
||||
mapPackSize int64
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@ -36,16 +38,13 @@ type ServerConfig struct {
|
||||
TilepackPath string
|
||||
ApkPath string
|
||||
ReinitDB bool
|
||||
MinZoom int
|
||||
DefaultCenter models.Coords
|
||||
}
|
||||
|
||||
func New(dbPath, tilepackPath, apkPath string, reinitDB bool) *Server {
|
||||
func New(config ServerConfig) *Server {
|
||||
return &Server{
|
||||
config: ServerConfig{
|
||||
DbPath: dbPath,
|
||||
TilepackPath: tilepackPath,
|
||||
ApkPath: apkPath,
|
||||
ReinitDB: reinitDB,
|
||||
},
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +62,7 @@ func (s *Server) Run(ctx context.Context) {
|
||||
Addr: fmt.Sprintf(":%d", 8080),
|
||||
Handler: router,
|
||||
}
|
||||
s.log.Infof("Running on %s", server.Addr)
|
||||
go func() {
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
s.log.Infof("listen: %s\n", err)
|
||||
@ -99,6 +99,7 @@ func (s *Server) setupDB() {
|
||||
s.dbpool = dbpool
|
||||
|
||||
if s.config.ReinitDB {
|
||||
s.log.Info("Reinitializing DB.")
|
||||
conn := s.getDbConn()
|
||||
defer s.dbpool.Put(conn)
|
||||
|
||||
@ -124,24 +125,30 @@ func (s *Server) setupTiles() {
|
||||
if err != nil {
|
||||
s.log.WithError(err).Fatal("Failed to create tileserver service set.")
|
||||
}
|
||||
err = svs.AddTileset(s.config.TilepackPath, "main")
|
||||
err = svs.AddTileset(s.config.TilepackPath, "map")
|
||||
if err != nil {
|
||||
s.log.WithError(err).Fatal("Failed to register main tileset.")
|
||||
s.log.WithError(err).Fatal("Failed to register tileset.")
|
||||
}
|
||||
s.tileserverSvSet = svs
|
||||
|
||||
info, err := os.Stat(s.config.TilepackPath)
|
||||
if err != nil {
|
||||
s.log.WithError(err).Fatal("Failed to get info about tile pack file.")
|
||||
}
|
||||
s.mapPackSize = info.Size()
|
||||
}
|
||||
|
||||
func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error) {
|
||||
conn := s.getDbConn()
|
||||
defer s.dbpool.Put(conn)
|
||||
|
||||
userID, err := func() (uid int, err error) {
|
||||
userID, err := func() (uid int64, err error) {
|
||||
defer sqlitex.Save(conn)(&err)
|
||||
|
||||
var id *int
|
||||
var id *int64
|
||||
if hc.Exists {
|
||||
err = sqlitex.Exec(conn, "select id from users where name = ?", func(stmt *sqlite.Stmt) error {
|
||||
id = ptrInt(stmt.ColumnInt(0))
|
||||
id = ptrInt64(stmt.ColumnInt64(0))
|
||||
return nil
|
||||
}, hc.Name)
|
||||
if sqlite.ErrCode(err) != sqlite.SQLITE_OK {
|
||||
@ -154,8 +161,8 @@ func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error)
|
||||
return 0, errs.ErrAttemptedSystemUser
|
||||
}
|
||||
} else {
|
||||
err = sqlitex.Exec(conn, "insert into users(name) values(?) returning id", func(stmt *sqlite.Stmt) error {
|
||||
id = ptrInt(stmt.ColumnInt(0))
|
||||
err = sqlitex.Exec(conn, "insert into users(name) values(?)", func(stmt *sqlite.Stmt) error {
|
||||
id = ptrInt64(stmt.ColumnInt64(0))
|
||||
return nil
|
||||
}, hc.Name)
|
||||
if sqlite.ErrCode(err) == sqlite.SQLITE_CONSTRAINT_UNIQUE {
|
||||
@ -164,6 +171,7 @@ func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error)
|
||||
if sqlite.ErrCode(err) != sqlite.SQLITE_OK {
|
||||
return 0, err
|
||||
}
|
||||
id = ptrInt64(conn.LastInsertRowID())
|
||||
}
|
||||
return *id, nil
|
||||
}()
|
||||
|
Loading…
Reference in New Issue
Block a user