Beispiel #1
0
func deleteStationHandler(sdb *db.StationDB,
	w http.ResponseWriter, r *http.Request, user userView) {

	id := r.URL.Query().Get("id")
	if id == "" {
		http.Error(w, "'id' param missing", http.StatusBadRequest)
		return
	}

	s, err := sdb.Lookup(id)
	if err != nil {
		log.Printf("Station DB lookup error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	if s == nil || *s.Userid != user.Id {
		http.NotFound(w, r)
		return
	}

	err = sdb.Delete(id)
	if err != nil {
		log.Printf("Station DB delete error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	// Success
	http.Redirect(w, r, "/home", http.StatusFound)
}
Beispiel #2
0
func editStationHandler(sdb *db.StationDB,
	w http.ResponseWriter, r *http.Request, user userView) {

	log.Printf("method: %s", r.Method)

	id := r.URL.Query().Get("id")
	if id == "" {
		http.Error(w, "'id' param missing", http.StatusBadRequest)
		return
	}

	s, err := sdb.Lookup(id)
	if err != nil {
		log.Printf("Station DB lookup error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
	if s == nil || *s.Userid != user.Id {
		http.NotFound(w, r)
		return
	}

	if s.Capabilities == nil {
		s.Capabilities = &pb.Capabilities{}
	}

	if r.Method == "POST" {
		editStationPOST(sdb, s, w, r, user)
	} else {
		editStationGET(s, w, r, user)
	}
}
Beispiel #3
0
func stationViewHandler(sdb *db.StationDB, m *rpc.Client, userdb *db.UserDB,
	contactdb *db.ContactDB,
	w http.ResponseWriter, r *http.Request, user userView) {

	id := r.URL.Query().Get("id")
	if id == "" {
		http.Error(w, "'id' param missing", http.StatusBadRequest)
		return
	}

	s, err := sdb.Lookup(id)
	if err != nil {
		log.Printf("Sation DB lookup error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
	if s == nil {
		http.NotFound(w, r)
		return
	}

	if s.Capabilities == nil {
		s.Capabilities = &pb.Capabilities{}
	}

	sc := GetStationContext(s, user.Id, m, userdb, contactdb)

	c := NewRenderContext(user, sc)
	err = stationViewTemplate.Get().ExecuteTemplate(w, "station.html", c)
	if err != nil {
		log.Printf("Error rendering station view: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
}
Beispiel #4
0
func consolePageHandler(sdb *db.StationDB, contactdb *db.ContactDB,
	mux *rpc.Client,
	w http.ResponseWriter, r *http.Request, user userView) {

	id := r.URL.Query().Get("id")
	if id == "" {
		http.Error(w, "'id' param missing", http.StatusBadRequest)
		return
	}

	station, err := sdb.Lookup(id)
	if err != nil {
		log.Printf("Error looking up station: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	auth, _ := canOperateStation(sdb, id, user.Id)
	if !auth {
		http.Error(w, "Not authorized", http.StatusUnauthorized)
		return
	}

	var cv consoleViewContext
	cv.S = *station
	cv.Satellites = fillSatOptions()
	c := NewRenderContext(user, cv)
	err = consoleTemplate.Get().ExecuteTemplate(
		w, "station_console.html", c)
	if err != nil {
		log.Printf("Error rendering station console: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
}
Beispiel #5
0
func AuthenticateStation(sdb *db.StationDB, id, secret string) (bool, error) {
	s, err := sdb.Lookup(id)
	if err != nil {
		return false, err
	}
	if s == nil {
		return false, nil
	}
	return *s.Id == id && *s.Secret == secret, nil
}
Beispiel #6
0
func stationContactsHandler(
	cdb *db.ContactDB, sdb *db.StationDB,
	w http.ResponseWriter, r *http.Request, user userView) {

	id := r.URL.Query().Get("id")
	if id == "" {
		http.Error(w, "'id' param missing", http.StatusBadRequest)
		return
	}

	s, err := sdb.Lookup(id)
	if err != nil {
		log.Printf("Sation DB lookup error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
	if s == nil {
		http.NotFound(w, r)
		return
	}

	if s.Userid == nil || user.Id != *s.Userid {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	contacts, err := cdb.SearchByStationId(id, 100)
	if err != nil {
		log.Printf("SearchByStationId error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	var cv contactsView
	cv.Title = *s.Name
	cv.C = contacts

	c := NewRenderContext(user, cv)
	err = contactsTemplate.Get().ExecuteTemplate(w, "contacts.html", c)
	if err != nil {
		log.Printf("Error rendering contacts view: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
}
Beispiel #7
0
// satellite_id can be empty if unknown
func StartNewConsoleContact(stationdb *db.StationDB, contactdb *db.ContactDB,
	station_id, user_id, satellite_id string) (
	id string, err error) {

	station, err := stationdb.Lookup(station_id)
	if err != nil {
		return "", err
	}
	if station == nil {
		return "", errors.New(
			fmt.Sprintf("Unknown station: %s", station_id))
	}

	s, err := NewContact(station, user_id, &satellite_id)
	if err != nil {
		return "", err
	}

	if err = contactdb.Store(s); err != nil {
		return "", err
	}

	return *s.Id, nil
}
Beispiel #8
0
func postPacketHandler(
	sdb *db.StationDB, cdb *db.ContactDB,
	w http.ResponseWriter, r *http.Request) {
	data, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		log.Printf("postPacketHandler: Error reading post body: %s",
			err.Error())
		http.Error(w, "Error reading post body",
			http.StatusInternalServerError)
		return
	}

	var req PostPacketRequest
	if err := json.Unmarshal(data, &req); err != nil {
		log.Printf("postPacketHandler: JSON decode error: %s",
			err.Error())
		http.Error(w, "Error decoding JSON data.",
			http.StatusBadRequest)
		return
	}

	log.Printf("request: %v", req)

	frame, err := base64.StdEncoding.DecodeString(req.FrameBase64)
	if err != nil {
		log.Printf("postPacketHandler: base64 decode error: %s",
			err.Error())
		http.Error(w, "Error decoding base64 frame.",
			http.StatusBadRequest)
		return
	}

	if req.StationId == "" {
		http.Error(w, "Missing station_id", http.StatusBadRequest)
		return
	}
	station, err := sdb.Lookup(req.StationId)
	if err != nil {
		log.Printf("Error looking up station: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	contact, poperr := contacts.PopulateContact(
		req.SatelliteId,
		req.Timestamp,
		req.Format,
		frame,
		"",
		req.StationSecret,
		station)
	if poperr != nil {
		poperr.HttpError(w)
		return
	}

	log.Printf("Storing contact: %s", contact)

	err = cdb.Store(contact)
	if err != nil {
		log.Printf("Error storing contact: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	// Do we need to set content-length?
}
Beispiel #9
0
func getLatestIQDataHandler(
	sdb *db.StationDB, cdb *db.ContactDB,
	w http.ResponseWriter, r *http.Request) {

	log.Printf("Request: %s", r.URL.String())

	req, err := parseGetLatestIQDataRequest(r.URL.Query())
	if err != nil {
		log.Printf("getLatestIQDataHandler: "+
			"parse request error: %s", err.Error())
		http.Error(w, "Error parsing request.",
			http.StatusBadRequest)
		return
	}

	sat := db.GlobalSatelliteDB().Map[req.SatelliteId]
	if sat == nil {
		http.Error(w, "Unknown satellite_id.", http.StatusBadRequest)
		return
	}

	station, err := sdb.Lookup(req.StationId)
	if err != nil {
		log.Printf("Error looking up station: %s", err.Error())
		http.Error(w, "", http.StatusUnauthorized)
		return
	}
	if station == nil {
		log.Printf("Error looking up station.")
		http.Error(w, "", http.StatusUnauthorized)
		return
	}
	// Authenticate the station.
	if station.Secret == nil || *station.Secret != req.StationSecret {
		log.Printf("Authentication failed.")
		http.Error(w, "", http.StatusUnauthorized)
		return
	}

	// Make sure that the user is authorized for the satellite.
	found_good_id := false
	for _, station_id := range sat.AuthorizedStationId {
		if station_id == *station.Id {
			found_good_id = true
		}
	}
	if !found_good_id {
		log.Printf("Authentication failed.")
		http.Error(w, "", http.StatusUnauthorized)
		return
	}

	contacts, err := cdb.SearchBySatelliteId(req.SatelliteId, req.Limit)
	if err != nil {
		log.Printf("getLatestIQDataHandler: "+
			"SearchBySatelliteId error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	packets := make(GetLatestIQDataResponse, 0)

	for _, c := range contacts {
		if c.StartTimestamp == nil {
			continue
		}
		timestamp := *c.StartTimestamp
		for _, b := range c.Blob {
			if len(packets) >= req.Limit {
				continue
			}

			if b.Format == nil ||
				*b.Format != pb.Contact_Blob_IQ {
				continue
			}

			var p IQLink
			p.Timestamp = timestamp
			p.URL = scheduler.GetStreamURL(*c.Id)

			if b.IqParams != nil {
				if b.IqParams.Type != nil {
					p.Type = b.IqParams.Type.String()
				}
				if b.IqParams.SampleRate != nil {
					p.SampleRate = int(
						*b.IqParams.SampleRate)
				}
			}

			packets = append(packets, p)
		}
	}

	json_body, err := json.Marshal(packets)
	if err != nil {
		log.Printf("json Marshal error: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
	}

	w.Header().Add("Content-Length", fmt.Sprintf("%d", len(json_body)))
	w.Header().Add("Content-Type", "application/json")
	_, err = w.Write(json_body)
	if err != nil {
		log.Printf("Error writing response: %s", err.Error())
	}
}
Beispiel #10
0
// blocking
// FIXME: handle disconnections
func scheduleStation(stationdb *db.StationDB,
	contactdb *db.ContactDB,
	mux_client *rpc.Client,
	station_id string,
	shutdown_chan chan string) {

	defer func() { shutdown_chan <- station_id }()

	log_label := station_id
	log.Printf("%s: Scheduling starting.", log_label)

	for {
		// Lookup the station in the loop since the owner might
		// edit the parameters.
		station, err := stationdb.Lookup(station_id)
		if err != nil {
			log.Printf("%s: Station lookup error: %s",
				log_label, err.Error())
			continue
		}
		if station == nil {
			log.Printf("%s: Station doesn't exist.", log_label)
			return
		}

		next_pass, err := getNextPass(station)
		if err != nil {
			log.Printf("%s: Error getting pass predictions: %s",
				log_label, err.Error())
		}

		var delay time.Duration
		if next_pass.Satellite == nil {
			// No passes coming up soon. Just wait a bit and try
			// again.
			log.Printf("%s: no upcoming passes", log_label)
			delay = maxPredictionDuration
		} else if station.SchedulerEnabled == nil ||
			*station.SchedulerEnabled == false {
			//log.Printf("%s: scheduler disabled", station_id)
			// TODO: We are effectively polling the SchedulerEnabled
			// bit. We really should instead have the frontend
			// send a notification to reschedule the station.
			delay = controlDisabledDuration
		} else {
			log.Printf("%s: next pass: %s",
				log_label, *next_pass.Satellite.Id)
			delay = timestamp.TimestampFloatToTime(
				next_pass.StartTimestamp).Sub(time.Now())
		}

		log.Printf("%s: waiting for %s", log_label, delay)

		// wait {timer, disconnect}
		// FIXME: handle disconnections during the sleep
		time.Sleep(delay)

		if next_pass.Satellite == nil {
			continue
		}

		// Check that station has enabled scheduling.
		// We have to look up the station again since it might have
		// changed while we were sleeping.
		station, err = stationdb.Lookup(station_id)
		if err != nil {
			log.Printf("%s: Station lookup error: %s",
				log_label, err.Error())
			continue
		}
		if station == nil {
			log.Printf("%s: Station doesn't exist.", log_label)
			return
		}
		if station.SchedulerEnabled == nil ||
			*station.SchedulerEnabled == false {
			continue
		}

		err = capturePass(contactdb, mux_client, *station, next_pass)
		if err != nil {
			// There was an error of some sort.
			// Wait a bit before trying again.
			time.Sleep(errorWaitDuration)
		}
	}
}
Beispiel #11
0
func satellitePostContactHandler(
	sdb *db.StationDB, cdb *db.ContactDB,
	w http.ResponseWriter, r *http.Request,
	user userView) {

	if r.Method != "POST" {
		http.Redirect(w, r, satelliteListUrl, http.StatusFound)
		return
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	log.Printf("satellitePostContactHandler form: %v\n\n", r.Form)

	satellite_id := r.Form.Get("satellite_id")
	if satellite_id == "" {
		http.Error(w, "Missing satellite id", http.StatusBadRequest)
		return
	}
	sat := db.GlobalSatelliteDB().Map[satellite_id]
	if sat == nil {
		http.Error(w, "Unknown satellite id", http.StatusBadRequest)
		return
	}

	timestamp, err := strconv.ParseInt(r.Form.Get("timestamp"), 10, 64)
	if err != nil {
		http.Error(w, "Can't parse timestamp.", http.StatusBadRequest)
		return
	}

	data := r.Form.Get("data")
	frame := ([]byte)(data)

	var station *pb.Station

	// There are two options: logged-in or anonymous.
	if user.Id == "" {
		// Anonymous
		station = nil
	} else {
		// Logged-in user

		station_id := r.Form.Get("station_id")
		if station_id == "" {
			http.Error(
				w, "Missing station id", http.StatusBadRequest)
			return
		}

		station, err = sdb.Lookup(station_id)
		if err != nil {
			log.Printf("Error looking up station: %s", err.Error())
			http.Error(w, "", http.StatusInternalServerError)
			return
		}
	}

	contact, poperr := contacts.PopulateContact(
		satellite_id,
		timestamp,
		"FREEFORM",
		frame,
		user.Id,
		"",
		station)

	if poperr != nil {
		poperr.HttpError(w)
		return
	}

	log.Printf("Contact: %s", contact)

	err = cdb.Store(contact)
	if err != nil {
		log.Printf("Error storing contact: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	var cc contactConfirmContext
	cc.SatelliteUrl = satelliteViewURL(*sat.Id)
	cc.SatelliteName = RenderSatelliteName(sat.Name)
	cc.Data = data

	if sat.Schema != nil {
		t := make([]pb.TelemetryDatum, 0)
		for _, b := range contact.Blob {
			if b.Format != nil &&
				*b.Format == pb.Contact_Blob_DATUM {
				t = append(t, *b.Datum)
			}
		}

		cc.Telemetry = fe_telemetry.RenderTelemetry(
			*sat.Schema, t, "en")
	}

	err = contactConfirmTemplate.Get().ExecuteTemplate(
		w, "contact_confirm.html", NewRenderContext(user, cc))
	if err != nil {
		log.Printf(
			"Error rendering contact_confirm view: %s", err.Error())
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
}