Start cleaning up linter errors. (#358)

* Start cleaning up linter errors. For #357

* Fix unmarshalling NullTime values

* More linter fixes

* Remove commented code

* Move defer up

* Consolidate error check lines

* Move error check to make sure row iteration was successful

* Cleaner error check + do not recreate pipe if it exists

* Consolidate hashing to generate client id
This commit is contained in:
Gabe Kangas 2020-11-14 18:39:53 -08:00 committed by GitHub
parent c76b7229a5
commit 4d2066a76d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 248 additions and 143 deletions

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/owncast/owncast/metrics" "github.com/owncast/owncast/metrics"
log "github.com/sirupsen/logrus"
) )
// GetHardwareStats will return hardware utilization over time. // GetHardwareStats will return hardware utilization over time.
@ -12,5 +13,8 @@ func GetHardwareStats(w http.ResponseWriter, r *http.Request) {
m := metrics.Metrics m := metrics.Metrics
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(m) err := json.NewEncoder(w).Encode(m)
if err != nil {
log.Errorln(err)
}
} }

View file

@ -27,7 +27,7 @@ func ServeAdmin(w http.ResponseWriter, r *http.Request) {
f, err := pkger.Open(path) f, err := pkger.Open(path)
if err != nil { if err != nil {
log.Warnln(err, path) log.Warnln(err, path)
errorHandler(w, r, http.StatusNotFound) errorHandler(w, http.StatusNotFound)
return return
} }
@ -39,9 +39,11 @@ func ServeAdmin(w http.ResponseWriter, r *http.Request) {
mimeType := mime.TypeByExtension(filepath.Ext(path)) mimeType := mime.TypeByExtension(filepath.Ext(path))
w.Header().Set("Content-Type", mimeType) w.Header().Set("Content-Type", mimeType)
w.Write(b) if _, err = w.Write(b); err != nil {
log.Errorln(err)
}
} }
func errorHandler(w http.ResponseWriter, r *http.Request, status int) { func errorHandler(w http.ResponseWriter, status int) {
w.WriteHeader(status) w.WriteHeader(status)
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/owncast/owncast/logging" "github.com/owncast/owncast/logging"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
) )
// GetLogs will return all logs. // GetLogs will return all logs.
@ -19,7 +20,10 @@ func GetLogs(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Errorln(err)
}
} }
// GetWarnings will return only warning and error logs. // GetWarnings will return only warning and error logs.
@ -32,7 +36,10 @@ func GetWarnings(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Errorln(err)
}
} }
type logsResponse struct { type logsResponse struct {

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/owncast/owncast/config" "github.com/owncast/owncast/config"
log "github.com/sirupsen/logrus"
) )
// GetServerConfig gets the config details of the server. // GetServerConfig gets the config details of the server.
@ -35,7 +36,10 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Errorln(err)
}
} }
type serverConfigAdminResponse struct { type serverConfigAdminResponse struct {

View file

@ -7,6 +7,7 @@ import (
"github.com/owncast/owncast/config" "github.com/owncast/owncast/config"
"github.com/owncast/owncast/core" "github.com/owncast/owncast/core"
"github.com/owncast/owncast/models" "github.com/owncast/owncast/models"
log "github.com/sirupsen/logrus"
) )
// Status gets the details of the inbound broadcaster. // Status gets the details of the inbound broadcaster.
@ -25,7 +26,10 @@ func Status(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Errorln(err)
}
} }
type adminStatusResponse struct { type adminStatusResponse struct {

View file

@ -5,11 +5,15 @@ import (
"net/http" "net/http"
"github.com/owncast/owncast/metrics" "github.com/owncast/owncast/metrics"
log "github.com/sirupsen/logrus"
) )
// GetViewersOverTime will return the number of viewers at points in time. // GetViewersOverTime will return the number of viewers at points in time.
func GetViewersOverTime(w http.ResponseWriter, r *http.Request) { func GetViewersOverTime(w http.ResponseWriter, r *http.Request) {
viewersOverTime := metrics.Metrics.Viewers viewersOverTime := metrics.Metrics.Viewers
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(viewersOverTime) err := json.NewEncoder(w).Encode(viewersOverTime)
if err != nil {
log.Errorln(err)
}
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/owncast/owncast/core" "github.com/owncast/owncast/core"
"github.com/owncast/owncast/models" "github.com/owncast/owncast/models"
"github.com/owncast/owncast/router/middleware" "github.com/owncast/owncast/router/middleware"
log "github.com/sirupsen/logrus"
) )
// GetChatMessages gets all of the chat messages. // GetChatMessages gets all of the chat messages.
@ -17,7 +18,10 @@ func GetChatMessages(w http.ResponseWriter, r *http.Request) {
case http.MethodGet: case http.MethodGet:
messages := core.GetAllChatMessages() messages := core.GetAllChatMessages()
json.NewEncoder(w).Encode(messages) err := json.NewEncoder(w).Encode(messages)
if err != nil {
log.Errorln(err)
}
case http.MethodPost: case http.MethodPost:
var message models.ChatMessage var message models.ChatMessage
if err := json.NewDecoder(r.Body).Decode(&message); err != nil { if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
@ -30,9 +34,14 @@ func GetChatMessages(w http.ResponseWriter, r *http.Request) {
return return
} }
json.NewEncoder(w).Encode(j{"success": true}) if err := json.NewEncoder(w).Encode(j{"success": true}); err != nil {
internalErrorHandler(w, err)
return
}
default: default:
w.WriteHeader(http.StatusNotImplemented) w.WriteHeader(http.StatusNotImplemented)
json.NewEncoder(w).Encode(j{"error": "method not implemented (PRs are accepted)"}) if err := json.NewEncoder(w).Encode(j{"error": "method not implemented (PRs are accepted)"}); err != nil {
internalErrorHandler(w, err)
}
} }
} }

View file

@ -14,5 +14,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) {
configuration := config.Config.InstanceDetails configuration := config.Config.InstanceDetails
configuration.Version = config.Config.VersionInfo configuration.Version = config.Config.VersionInfo
json.NewEncoder(w).Encode(configuration) if err := json.NewEncoder(w).Encode(configuration); err != nil {
badRequestHandler(w, err)
}
} }

View file

@ -12,5 +12,7 @@ func GetConnectedClients(w http.ResponseWriter, r *http.Request) {
clients := core.GetClients() clients := core.GetClients()
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(clients) if err := json.NewEncoder(w).Encode(clients); err != nil {
internalErrorHandler(w, err)
}
} }

View file

@ -15,7 +15,9 @@ func internalErrorHandler(w http.ResponseWriter, err error) {
} }
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(j{"error": err.Error()}) if err := json.NewEncoder(w).Encode(j{"error": err.Error()}); err != nil {
internalErrorHandler(w, err)
}
} }
func badRequestHandler(w http.ResponseWriter, err error) { func badRequestHandler(w http.ResponseWriter, err error) {
@ -24,7 +26,9 @@ func badRequestHandler(w http.ResponseWriter, err error) {
} }
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(j{"error": err.Error()}) if err := json.NewEncoder(w).Encode(j{"error": err.Error()}); err != nil {
internalErrorHandler(w, err)
}
} }
func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) { func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) {
@ -33,5 +37,7 @@ func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) {
Message: message, Message: message,
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response) if err := json.NewEncoder(w).Encode(response); err != nil {
internalErrorHandler(w, err)
}
} }

View file

@ -35,9 +35,11 @@ func GetCustomEmoji(w http.ResponseWriter, r *http.Request) {
for _, f := range files { for _, f := range files {
name := strings.TrimSuffix(f.Name(), path.Ext(f.Name())) name := strings.TrimSuffix(f.Name(), path.Ext(f.Name()))
emojiPath := filepath.Join(emojiDir, f.Name()) emojiPath := filepath.Join(emojiDir, f.Name())
singleEmoji := models.CustomEmoji{name, emojiPath} singleEmoji := models.CustomEmoji{Name: name, Emoji: emojiPath}
emojiList = append(emojiList, singleEmoji) emojiList = append(emojiList, singleEmoji)
} }
json.NewEncoder(w).Encode(emojiList) if err := json.NewEncoder(w).Encode(emojiList); err != nil {
internalErrorHandler(w, err)
}
} }

View file

@ -15,5 +15,7 @@ func GetStatus(w http.ResponseWriter, r *http.Request) {
status := core.GetStatus() status := core.GetStatus()
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(status) if err := json.NewEncoder(w).Encode(status); err != nil {
internalErrorHandler(w, err)
}
} }

View file

@ -40,11 +40,8 @@ func Start() error {
ticker := time.NewTicker(30 * time.Second) ticker := time.NewTicker(30 * time.Second)
go func() { go func() {
for { for range ticker.C {
select { _server.ping()
case <-ticker.C:
_server.ping()
}
} }
}() }()

View file

@ -94,13 +94,21 @@ func (c *Client) listenWrite() {
select { select {
// Send a PING keepalive // Send a PING keepalive
case msg := <-c.pingch: case msg := <-c.pingch:
websocket.JSON.Send(c.ws, msg) err := websocket.JSON.Send(c.ws, msg)
if err != nil {
log.Errorln(err)
}
// send message to the client // send message to the client
case msg := <-c.ch: case msg := <-c.ch:
// log.Println("Send:", msg) err := websocket.JSON.Send(c.ws, msg)
websocket.JSON.Send(c.ws, msg) if err != nil {
log.Errorln(err)
}
case msg := <-c.usernameChangeChannel: case msg := <-c.usernameChangeChannel:
websocket.JSON.Send(c.ws, msg) err := websocket.JSON.Send(c.ws, msg)
if err != nil {
log.Errorln(err)
}
// receive done request // receive done request
case <-c.doneCh: case <-c.doneCh:
_server.remove(c) _server.remove(c)
@ -114,7 +122,6 @@ func (c *Client) listenWrite() {
func (c *Client) listenRead() { func (c *Client) listenRead() {
for { for {
select { select {
// receive done request // receive done request
case <-c.doneCh: case <-c.doneCh:
_server.remove(c) _server.remove(c)

View file

@ -32,7 +32,10 @@ func createTable() {
log.Fatal(err) log.Fatal(err)
} }
defer stmt.Close() defer stmt.Close()
stmt.Exec() _, err = stmt.Exec()
if err != nil {
log.Warnln(err)
}
} }
func addMessage(message models.ChatMessage) { func addMessage(message models.ChatMessage) {
@ -41,16 +44,20 @@ func addMessage(message models.ChatMessage) {
log.Fatal(err) log.Fatal(err)
} }
stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?)") stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?)")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer stmt.Close()
_, err = stmt.Exec(message.ID, message.Author, message.Body, message.MessageType, 1, message.Timestamp) _, err = stmt.Exec(message.ID, message.Author, message.Body, message.MessageType, 1, message.Timestamp)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
tx.Commit() err = tx.Commit()
if err != nil {
defer stmt.Close() log.Fatal(err)
}
} }
func getChatHistory() []models.ChatMessage { func getChatHistory() []models.ChatMessage {
@ -89,5 +96,9 @@ func getChatHistory() []models.ChatMessage {
history = append(history, message) history = append(history, message)
} }
if err := rows.Err(); err != nil {
log.Fatal(err)
}
return history return history
} }

View file

@ -46,11 +46,6 @@ func (s *server) SendToAll(msg models.ChatMessage) {
s.sendAllCh <- msg s.sendAllCh <- msg
} }
// Done marks the server as done.
func (s *server) done() {
s.doneCh <- true
}
// Err handles an error. // Err handles an error.
func (s *server) err(err error) { func (s *server) err(err error) {
s.errCh <- err s.errCh <- err
@ -140,18 +135,7 @@ func (s *server) sendWelcomeMessageToClient(c *Client) {
time.Sleep(7 * time.Second) time.Sleep(7 * time.Second)
initialChatMessageText := fmt.Sprintf("Welcome to %s! %s", config.Config.InstanceDetails.Title, config.Config.InstanceDetails.Summary) initialChatMessageText := fmt.Sprintf("Welcome to %s! %s", config.Config.InstanceDetails.Title, config.Config.InstanceDetails.Summary)
initialMessage := models.ChatMessage{"owncast-server", config.Config.InstanceDetails.Name, initialChatMessageText, "initial-message-1", "SYSTEM", true, time.Now()} initialMessage := models.ChatMessage{ClientID: "owncast-server", Author: config.Config.InstanceDetails.Name, Body: initialChatMessageText, ID: "initial-message-1", MessageType: "SYSTEM", Visible: true, Timestamp: time.Now()}
c.Write(initialMessage) c.Write(initialMessage)
}() }()
}
func (s *server) getClientForClientID(clientID string) *Client {
for _, client := range s.Clients {
if client.ClientID == clientID {
return client
}
}
return nil
} }

View file

@ -99,7 +99,10 @@ func transitionToOfflineVideoStreamContent() {
_transcoder.Start() _transcoder.Start()
// Copy the logo to be the thumbnail // Copy the logo to be the thumbnail
utils.Copy(filepath.Join("webroot", config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg") err := utils.Copy(filepath.Join("webroot", config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg")
if err != nil {
log.Warnln(err)
}
// Delete the preview Gif // Delete the preview Gif
os.Remove(path.Join(config.WebRoot, "preview.gif")) os.Remove(path.Join(config.WebRoot, "preview.gif"))
@ -111,8 +114,15 @@ func resetDirectories() {
// Wipe the public, web-accessible hls data directory // Wipe the public, web-accessible hls data directory
os.RemoveAll(config.PublicHLSStoragePath) os.RemoveAll(config.PublicHLSStoragePath)
os.RemoveAll(config.PrivateHLSStoragePath) os.RemoveAll(config.PrivateHLSStoragePath)
os.MkdirAll(config.PublicHLSStoragePath, 0777) err := os.MkdirAll(config.PublicHLSStoragePath, 0777)
os.MkdirAll(config.PrivateHLSStoragePath, 0777) if err != nil {
log.Fatalln(err)
}
err = os.MkdirAll(config.PrivateHLSStoragePath, 0777)
if err != nil {
log.Fatalln(err)
}
// Remove the previous thumbnail // Remove the previous thumbnail
os.Remove(filepath.Join(config.WebRoot, "thumbnail.jpg")) os.Remove(filepath.Join(config.WebRoot, "thumbnail.jpg"))
@ -120,14 +130,31 @@ func resetDirectories() {
// Create private hls data dirs // Create private hls data dirs
if len(config.Config.VideoSettings.StreamQualities) != 0 { if len(config.Config.VideoSettings.StreamQualities) != 0 {
for index := range config.Config.VideoSettings.StreamQualities { for index := range config.Config.VideoSettings.StreamQualities {
os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(index)), 0777) err = os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(index)), 0777)
os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(index)), 0777) if err != nil {
log.Fatalln(err)
}
err = os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(index)), 0777)
if err != nil {
log.Fatalln(err)
}
} }
} else { } else {
os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(0)), 0777) err = os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(0)), 0777)
os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(0)), 0777) if err != nil {
log.Fatalln(err)
}
err = os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(0)), 0777)
if err != nil {
log.Fatalln(err)
}
} }
// Remove the previous thumbnail // Remove the previous thumbnail
utils.Copy(config.Config.InstanceDetails.Logo.Large, "webroot/thumbnail.jpg") err = utils.Copy(path.Join(config.WebRoot, config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg")
if err != nil {
log.Warnln(err)
}
} }

View file

@ -60,14 +60,14 @@ func (s *FileWriterReceiverService) uploadHandler(w http.ResponseWriter, r *http
f, err := os.Create(writePath) f, err := os.Create(writePath)
if err != nil { if err != nil {
returnError(err, w, r) returnError(err, w)
return return
} }
defer f.Close() defer f.Close()
_, err = f.Write(data) _, err = f.Write(data)
if err != nil { if err != nil {
returnError(err, w, r) returnError(err, w)
return return
} }
@ -82,7 +82,6 @@ func (s *FileWriterReceiverService) fileWritten(path string) {
if utils.GetRelativePathFromAbsolutePath(path) == "hls/stream.m3u8" { if utils.GetRelativePathFromAbsolutePath(path) == "hls/stream.m3u8" {
s.callbacks.MasterPlaylistWritten(path) s.callbacks.MasterPlaylistWritten(path)
} else if strings.HasSuffix(path, ".ts") { } else if strings.HasSuffix(path, ".ts") {
performanceMonitorKey := "segmentWritten-" + index performanceMonitorKey := "segmentWritten-" + index
averagePerformance := utils.GetAveragePerformance(performanceMonitorKey) averagePerformance := utils.GetAveragePerformance(performanceMonitorKey)
@ -98,13 +97,12 @@ func (s *FileWriterReceiverService) fileWritten(path string) {
} else { } else {
_inWarningState = false _inWarningState = false
} }
} else if strings.HasSuffix(path, ".m3u8") { } else if strings.HasSuffix(path, ".m3u8") {
s.callbacks.VariantPlaylistWritten(path) s.callbacks.VariantPlaylistWritten(path)
} }
} }
func returnError(err error, w http.ResponseWriter, r *http.Request) { func returnError(err error, w http.ResponseWriter) {
log.Errorln(err) log.Errorln(err)
http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError) http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError)
} }

View file

@ -90,7 +90,12 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
log.Infoln("Incoming RTMP connected.") log.Infoln("Incoming RTMP connected.")
pipePath := utils.GetTemporaryPipePath() pipePath := utils.GetTemporaryPipePath()
syscall.Mkfifo(pipePath, 0666) if !utils.DoesFileExists(pipePath) {
err := syscall.Mkfifo(pipePath, 0666)
if err != nil {
log.Fatalln(err)
}
}
_hasInboundRTMPConnection = true _hasInboundRTMPConnection = true
_setStreamAsConnected() _setStreamAsConnected()
@ -119,7 +124,6 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
panic(err) panic(err)
} }
} }
} }
func handleDisconnect(conn net.Conn) { func handleDisconnect(conn net.Conn) {

View file

@ -6,8 +6,8 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"github.com/owncast/owncast/models"
"github.com/nareix/joy5/format/flv/flvio" "github.com/nareix/joy5/format/flv/flvio"
"github.com/owncast/owncast/models"
) )
func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMetadata, error) { func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMetadata, error) {
@ -21,8 +21,8 @@ func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMet
metadataJSONString := submatchall[0] metadataJSONString := submatchall[0]
var details models.RTMPStreamMetadata var details models.RTMPStreamMetadata
json.Unmarshal([]byte(metadataJSONString), &details) err := json.Unmarshal([]byte(metadataJSONString), &details)
return details, nil return details, err
} }
func getAudioCodec(codec interface{}) string { func getAudioCodec(codec interface{}) string {

View file

@ -29,12 +29,9 @@ func setupStats() error {
statsSaveTimer := time.NewTicker(1 * time.Minute) statsSaveTimer := time.NewTicker(1 * time.Minute)
go func() { go func() {
for { for range statsSaveTimer.C {
select { if err := saveStatsToFile(); err != nil {
case <-statsSaveTimer.C: panic(err)
if err := saveStatsToFile(); err != nil {
panic(err)
}
} }
} }
}() }()
@ -137,12 +134,12 @@ func getSavedStats() (models.Stats, error) {
jsonFile, err := ioutil.ReadFile(config.StatsFile) jsonFile, err := ioutil.ReadFile(config.StatsFile)
if err != nil { if err != nil {
return result, nil return result, err
} }
if err := json.Unmarshal(jsonFile, &result); err != nil { if err := json.Unmarshal(jsonFile, &result); err != nil {
return result, nil return result, err
} }
return result, nil return result, err
} }

View file

@ -5,10 +5,6 @@ import (
"github.com/owncast/owncast/core/storageproviders" "github.com/owncast/owncast/core/storageproviders"
) )
var (
usingExternalStorage = false
)
func setupStorage() error { func setupStorage() error {
handler.Storage = _storage handler.Storage = _storage

View file

@ -23,11 +23,8 @@ func (s *LocalStorage) Setup() error {
// as all HLS segments have to be publicly available on disk to keep a recording of them. // as all HLS segments have to be publicly available on disk to keep a recording of them.
_onlineCleanupTicker = time.NewTicker(1 * time.Minute) _onlineCleanupTicker = time.NewTicker(1 * time.Minute)
go func() { go func() {
for { for range _onlineCleanupTicker.C {
select { ffmpeg.CleanupOldContent(config.PublicHLSStoragePath)
case <-_onlineCleanupTicker.C:
ffmpeg.CleanupOldContent(config.PublicHLSStoragePath)
}
} }
}() }()
return nil return nil
@ -35,7 +32,10 @@ func (s *LocalStorage) Setup() error {
// SegmentWritten is called when a single segment of video is written. // SegmentWritten is called when a single segment of video is written.
func (s *LocalStorage) SegmentWritten(localFilePath string) { func (s *LocalStorage) SegmentWritten(localFilePath string) {
s.Save(localFilePath, 0) _, err := s.Save(localFilePath, 0)
if err != nil {
log.Warnln(err)
}
} }
// VariantPlaylistWritten is called when a variant hls playlist is written. // VariantPlaylistWritten is called when a variant hls playlist is written.
@ -49,7 +49,10 @@ func (s *LocalStorage) VariantPlaylistWritten(localFilePath string) {
// MasterPlaylistWritten is called when the master hls playlist is written. // MasterPlaylistWritten is called when the master hls playlist is written.
func (s *LocalStorage) MasterPlaylistWritten(localFilePath string) { func (s *LocalStorage) MasterPlaylistWritten(localFilePath string) {
s.Save(localFilePath, 0) _, err := s.Save(localFilePath, 0)
if err != nil {
log.Warnln(err)
}
} }
// Save will save a local filepath using the storage provider. // Save will save a local filepath using the storage provider.
@ -63,7 +66,6 @@ func (s *LocalStorage) Save(filePath string, retryCount int) (string, error) {
newPath = filepath.Join(config.WebRoot, filePath) newPath = filepath.Join(config.WebRoot, filePath)
} }
utils.Copy(filePath, newPath) err := utils.Copy(filePath, newPath)
return newPath, err
return newPath, nil
} }

View file

@ -22,7 +22,7 @@ import (
// If we try to upload a playlist but it is not yet on disk // If we try to upload a playlist but it is not yet on disk
// then keep a reference to it here. // then keep a reference to it here.
var _queuedPlaylistUpdates = make(map[string]string, 0) var _queuedPlaylistUpdates = make(map[string]string)
// S3Storage is the s3 implementation of the ChunkStorageProvider. // S3Storage is the s3 implementation of the ChunkStorageProvider.
type S3Storage struct { type S3Storage struct {
@ -118,7 +118,10 @@ func (s *S3Storage) VariantPlaylistWritten(localFilePath string) {
// MasterPlaylistWritten is called when the master hls playlist is written. // MasterPlaylistWritten is called when the master hls playlist is written.
func (s *S3Storage) MasterPlaylistWritten(localFilePath string) { func (s *S3Storage) MasterPlaylistWritten(localFilePath string) {
// Rewrite the playlist to use absolute remote S3 URLs // Rewrite the playlist to use absolute remote S3 URLs
s.rewriteRemotePlaylist(localFilePath) err := s.rewriteRemotePlaylist(localFilePath)
if err != nil {
log.Warnln(err)
}
} }
// Save saves the file to the s3 bucket. // Save saves the file to the s3 bucket.
@ -192,6 +195,9 @@ func (s *S3Storage) rewriteRemotePlaylist(filePath string) error {
p := m3u8.NewMasterPlaylist() p := m3u8.NewMasterPlaylist()
err = p.DecodeFrom(bufio.NewReader(f), false) err = p.DecodeFrom(bufio.NewReader(f), false)
if err != nil {
log.Warnln(err)
}
for _, item := range p.Variants { for _, item := range p.Variants {
item.URI = s.host + filepath.Join("/hls", item.URI) item.URI = s.host + filepath.Join("/hls", item.URI)

View file

@ -26,8 +26,8 @@ var _onlineCleanupTicker *time.Ticker
// setStreamAsConnected sets the stream as connected. // setStreamAsConnected sets the stream as connected.
func setStreamAsConnected() { func setStreamAsConnected() {
_stats.StreamConnected = true _stats.StreamConnected = true
_stats.LastConnectTime = utils.NullTime{time.Now(), true} _stats.LastConnectTime = utils.NullTime{Time: time.Now(), Valid: true}
_stats.LastDisconnectTime = utils.NullTime{time.Now(), false} _stats.LastDisconnectTime = utils.NullTime{Time: time.Now(), Valid: false}
StopOfflineCleanupTimer() StopOfflineCleanupTimer()
startOnlineCleanupTimer() startOnlineCleanupTimer()
@ -44,7 +44,6 @@ func setStreamAsConnected() {
go func() { go func() {
_transcoder = ffmpeg.NewTranscoder() _transcoder = ffmpeg.NewTranscoder()
_transcoder.TranscoderCompleted = func(error) { _transcoder.TranscoderCompleted = func(error) {
SetStreamAsDisconnected() SetStreamAsDisconnected()
} }
_transcoder.Start() _transcoder.Start()
@ -56,7 +55,7 @@ func setStreamAsConnected() {
// SetStreamAsDisconnected sets the stream as disconnected. // SetStreamAsDisconnected sets the stream as disconnected.
func SetStreamAsDisconnected() { func SetStreamAsDisconnected() {
_stats.StreamConnected = false _stats.StreamConnected = false
_stats.LastDisconnectTime = utils.NullTime{time.Now(), true} _stats.LastDisconnectTime = utils.NullTime{Time: time.Now(), Valid: true}
_broadcaster = nil _broadcaster = nil
offlineFilename := "offline.ts" offlineFilename := "offline.ts"
@ -73,9 +72,14 @@ func SetStreamAsDisconnected() {
playlistFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/stream.m3u8"), index) playlistFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/stream.m3u8"), index)
segmentFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/%s"), index, offlineFilename) segmentFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/%s"), index, offlineFilename)
utils.Copy(offlineFilePath, segmentFilePath) err := utils.Copy(offlineFilePath, segmentFilePath)
_storage.Save(segmentFilePath, 0) if err != nil {
log.Warnln(err)
}
_, err = _storage.Save(segmentFilePath, 0)
if err != nil {
log.Warnln(err)
}
if utils.DoesFileExists(playlistFilePath) { if utils.DoesFileExists(playlistFilePath) {
f, err := os.OpenFile(playlistFilePath, os.O_CREATE|os.O_RDWR, os.ModePerm) f, err := os.OpenFile(playlistFilePath, os.O_CREATE|os.O_RDWR, os.ModePerm)
if err != nil { if err != nil {
@ -84,13 +88,23 @@ func SetStreamAsDisconnected() {
defer f.Close() defer f.Close()
playlist, _, err := m3u8.DecodeFrom(bufio.NewReader(f), true) playlist, _, err := m3u8.DecodeFrom(bufio.NewReader(f), true)
if err != nil {
log.Fatalln(err)
}
variantPlaylist := playlist.(*m3u8.MediaPlaylist) variantPlaylist := playlist.(*m3u8.MediaPlaylist)
if len(variantPlaylist.Segments) > config.Config.GetMaxNumberOfReferencedSegmentsInPlaylist() { if len(variantPlaylist.Segments) > config.Config.GetMaxNumberOfReferencedSegmentsInPlaylist() {
variantPlaylist.Segments = variantPlaylist.Segments[:len(variantPlaylist.Segments)] variantPlaylist.Segments = variantPlaylist.Segments[:len(variantPlaylist.Segments)]
} }
err = variantPlaylist.Append(offlineFilename, 8.0, "") err = variantPlaylist.Append(offlineFilename, 8.0, "")
variantPlaylist.SetDiscontinuity() if err != nil {
log.Fatalln(err)
}
err = variantPlaylist.SetDiscontinuity()
if err != nil {
log.Fatalln(err)
}
_, err = f.WriteAt(variantPlaylist.Encode().Bytes(), 0) _, err = f.WriteAt(variantPlaylist.Encode().Bytes(), 0)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
@ -118,7 +132,10 @@ func SetStreamAsDisconnected() {
log.Errorln(err) log.Errorln(err)
} }
} }
_storage.Save(playlistFilePath, 0) _, err = _storage.Save(playlistFilePath, 0)
if err != nil {
log.Warnln(err)
}
} }
StartOfflineCleanupTimer() StartOfflineCleanupTimer()
@ -129,14 +146,11 @@ func SetStreamAsDisconnected() {
func StartOfflineCleanupTimer() { func StartOfflineCleanupTimer() {
_offlineCleanupTimer = time.NewTimer(5 * time.Minute) _offlineCleanupTimer = time.NewTimer(5 * time.Minute)
go func() { go func() {
for { for range _offlineCleanupTimer.C {
select { // Reset the session count since the session is over
case <-_offlineCleanupTimer.C: _stats.SessionMaxViewerCount = 0
// Reset the session count since the session is over resetDirectories()
_stats.SessionMaxViewerCount = 0 transitionToOfflineVideoStreamContent()
resetDirectories()
transitionToOfflineVideoStreamContent()
}
} }
}() }()
} }
@ -151,11 +165,8 @@ func StopOfflineCleanupTimer() {
func startOnlineCleanupTimer() { func startOnlineCleanupTimer() {
_onlineCleanupTicker = time.NewTicker(1 * time.Minute) _onlineCleanupTicker = time.NewTicker(1 * time.Minute)
go func() { go func() {
for { for range _onlineCleanupTicker.C {
select { ffmpeg.CleanupOldContent(config.PrivateHLSStoragePath)
case <-_onlineCleanupTicker.C:
ffmpeg.CleanupOldContent(config.PrivateHLSStoragePath)
}
} }
}() }()
} }

View file

@ -80,5 +80,4 @@ func FetchGeoForIP(ip string) {
_geoIPCache[ip] = response _geoIPCache[ip] = response
}() }()
} }

View file

@ -31,7 +31,7 @@ func main() {
log.Infoln(getReleaseString()) log.Infoln(getReleaseString())
// Enable bundling of admin assets // Enable bundling of admin assets
pkger.Include("/admin") _ = pkger.Include("/admin")
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder") configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
dbFile := flag.String("database", "", "Path to the database file.") dbFile := flag.String("database", "", "Path to the database file.")
@ -67,13 +67,11 @@ func main() {
// starts the core // starts the core
if err := core.Start(); err != nil { if err := core.Start(); err != nil {
log.Error("failed to start the core package") log.Fatalln("failed to start the core package", err)
panic(err)
} }
if err := router.Start(); err != nil { if err := router.Start(); err != nil {
log.Error("failed to start/run the router") log.Fatalln("failed to start/run the router", err)
panic(err)
} }
} }

View file

@ -51,5 +51,5 @@ func handleDiskAlerting() {
} }
func recentAverage(values []timestampedValue) int { func recentAverage(values []timestampedValue) int {
return int((values[len(values)-1].Value + values[len(values)-2].Value) / 2) return (values[len(values)-1].Value + values[len(values)-2].Value) / 2
} }

View file

@ -29,7 +29,12 @@ func Start() error {
http.HandleFunc("/api/emoji", controllers.GetCustomEmoji) http.HandleFunc("/api/emoji", controllers.GetCustomEmoji)
// websocket chat server // websocket chat server
go chat.Start() go func() {
err := chat.Start()
if err != nil {
log.Fatalln(err)
}
}()
// chat rest api // chat rest api
http.HandleFunc("/api/chat", controllers.GetChatMessages) http.HandleFunc("/api/chat", controllers.GetChatMessages)

View file

@ -1,7 +1,7 @@
package utils package utils
import ( import (
"crypto/md5" "crypto/md5" //nolint
"encoding/hex" "encoding/hex"
"net" "net"
"net/http" "net/http"
@ -18,9 +18,8 @@ func GenerateClientIDFromRequest(req *http.Request) string {
clientID := strings.Join(ipAddressComponents, ":") + req.UserAgent() clientID := strings.Join(ipAddressComponents, ":") + req.UserAgent()
// Create a MD5 hash of this ip + useragent // Create a MD5 hash of this ip + useragent
hasher := md5.New() b := md5.Sum([]byte(clientID)) // nolint
hasher.Write([]byte(clientID)) return hex.EncodeToString(b[:])
return hex.EncodeToString(hasher.Sum(nil))
} }
// GetIPAddressFromRequest returns the IP address from a http request. // GetIPAddressFromRequest returns the IP address from a http request.

View file

@ -17,7 +17,7 @@ func (nt *NullTime) Scan(value interface{}) error {
return nil return nil
} }
// Value implements the driver Valuer interface. // Value implements the driver Value interface.
func (nt NullTime) Value() (driver.Value, error) { func (nt NullTime) Value() (driver.Value, error) {
if !nt.Valid { if !nt.Valid {
return nil, nil return nil, nil
@ -32,3 +32,19 @@ func (nt NullTime) MarshalJSON() ([]byte, error) {
val := fmt.Sprintf("\"%s\"", nt.Time.Format(time.RFC3339)) val := fmt.Sprintf("\"%s\"", nt.Time.Format(time.RFC3339))
return []byte(val), nil return []byte(val), nil
} }
func (nt NullTime) UnmarshalJSON(data []byte) error {
dateString := string(data)
if dateString == "null" {
return nil
}
dateStringWithoutQuotes := dateString[1 : len(dateString)-1]
parsedDateTime, err := time.Parse(time.RFC3339, dateStringWithoutQuotes)
if err != nil {
return err
}
nt.Time = parsedDateTime
return nil
}

View file

@ -54,7 +54,7 @@ func Copy(source, destination string) error {
return err return err
} }
return ioutil.WriteFile(destination, input, 0644) return ioutil.WriteFile(destination, input, 0600)
} }
// Move moves the file to destination. // Move moves the file to destination.

View file

@ -6,6 +6,7 @@ import (
"github.com/owncast/owncast/config" "github.com/owncast/owncast/config"
"github.com/owncast/owncast/utils" "github.com/owncast/owncast/utils"
log "github.com/sirupsen/logrus"
) )
type ypDetailsResponse struct { type ypDetailsResponse struct {
@ -41,6 +42,8 @@ func GetYPResponse(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Errorln(err)
}
} }

View file

@ -47,15 +47,9 @@ func NewYP(getStatusFunc func() models.Status) *YP {
// Start is run when a live stream begins to start pinging YP. // Start is run when a live stream begins to start pinging YP.
func (yp *YP) Start() { func (yp *YP) Start() {
yp.timer = time.NewTicker(pingInterval) yp.timer = time.NewTicker(pingInterval)
for range yp.timer.C {
go func() { yp.ping()
for { }
select {
case <-yp.timer.C:
yp.ping()
}
}
}()
yp.ping() yp.ping()
} }
@ -92,7 +86,7 @@ func (yp *YP) ping() {
} }
pingURL := config.Config.GetYPServiceHost() + "/ping" pingURL := config.Config.GetYPServiceHost() + "/ping"
resp, err := http.Post(pingURL, "application/json", bytes.NewBuffer(req)) resp, err := http.Post(pingURL, "application/json", bytes.NewBuffer(req)) //nolint
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return return
@ -105,7 +99,10 @@ func (yp *YP) ping() {
} }
pingResponse := ypPingResponse{} pingResponse := ypPingResponse{}
json.Unmarshal(body, &pingResponse) err = json.Unmarshal(body, &pingResponse)
if err != nil {
log.Errorln(err)
}
if !pingResponse.Success { if !pingResponse.Success {
if !_inErrorState { if !_inErrorState {