1
0
mirror of https://gitlab.crans.org/nounous/ghostream.git synced 2025-07-04 11:42:15 +02:00

8 Commits

6 changed files with 21 additions and 11 deletions

View File

@ -11,6 +11,13 @@
This project was developped at [Cr@ns](https://crans.org/) to stream events. This project was developped at [Cr@ns](https://crans.org/) to stream events.
> **Note**
> *This project is no longer maintained!*
>
> As an alternative, you should try [Galène](https://galene.org/) which supports [WebRTC-HTTP ingestion protocol (WHIP)](https://datatracker.ietf.org/doc/draft-ietf-wish-whip/) for low-latency streaming.
> OBS Studio introduced WHIP output in version 30.0.
> Galène supports WHIP since Galène 0.8.
Features: Features:
- WebRTC playback with a lightweight web interface. - WebRTC playback with a lightweight web interface.

View File

@ -10,19 +10,19 @@ func TestBasicLogin(t *testing.T) {
// Test good credentials // Test good credentials
backend, _ := New(&Options{Credentials: basicCredentials}) backend, _ := New(&Options{Credentials: basicCredentials})
ok, err := backend.Login("demo", "demo") ok, _, err := backend.Login("demo", "demo")
if !ok { if !ok {
t.Error("Error while logging with the basic authentication:", err) t.Error("Error while logging with the basic authentication:", err)
} }
// Test bad username // Test bad username
ok, err = backend.Login("baduser", "demo") ok, _, err = backend.Login("baduser", "demo")
if ok { if ok {
t.Error("Authentification failed to fail:", err) t.Error("Authentification failed to fail:", err)
} }
// Test bad password // Test bad password
ok, err = backend.Login("demo", "badpass") ok, _, err = backend.Login("demo", "badpass")
if ok { if ok {
t.Error("Authentification failed to fail:", err) t.Error("Authentification failed to fail:", err)
} }

View File

@ -42,6 +42,7 @@ func (a LDAP) Login(username string, password string) (bool, string, error) {
for _, username := range potentialUsernames { for _, username := range potentialUsernames {
// Try to bind as user // Try to bind as user
bindDn := "cn=" + username + "," + a.Cfg.UserDn bindDn := "cn=" + username + "," + a.Cfg.UserDn
log.Printf("[LDAP] Logging to %s...", bindDn)
err = a.Conn.Bind(bindDn, password) err = a.Conn.Bind(bindDn, password)
if err == nil { if err == nil {
// Login succeeded if no error // Login succeeded if no error
@ -49,6 +50,7 @@ func (a LDAP) Login(username string, password string) (bool, string, error) {
} }
} }
log.Printf("[LDAP] Logging failed: %s", err)
// Unable to log in // Unable to log in
return err == nil, "", err return err == nil, "", err
} }

View File

@ -79,22 +79,22 @@ func Serve(streams *messaging.Streams, authBackend auth.Backend, cfg *Options) {
if len(split) > 1 { if len(split) > 1 {
// password was provided so it is a streamer // password was provided so it is a streamer
name, password := split[0], split[1] name, password := strings.ToLower(split[0]), split[1]
if authBackend != nil { if authBackend != nil {
// check password // check password
ok, username, err := authBackend.Login(name, password) ok, username, err := authBackend.Login(name, password)
name = username if !ok || err != nil {
if ok || err != nil {
log.Printf("Failed to authenticate for stream %s", name) log.Printf("Failed to authenticate for stream %s", name)
s.Close() s.Close()
continue continue
} }
name = username
} }
go handleStreamer(s, streams, name) go handleStreamer(s, streams, name)
} else { } else {
// password was not provided so it is a viewer // password was not provided so it is a viewer
name := split[0] name := strings.ToLower(split[0])
// Send stream // Send stream
go handleViewer(s, streams, name) go handleViewer(s, streams, name)

View File

@ -21,7 +21,7 @@ import (
var ( var (
// Precompile regex // Precompile regex
validPath = regexp.MustCompile("^/[a-z0-9@_-]*$") validPath = regexp.MustCompile("^/[a-zA-Z0-9@_-]*$")
counterMutex = new(sync.Mutex) counterMutex = new(sync.Mutex)
connectedClients = make(map[string]map[string]int64) connectedClients = make(map[string]map[string]int64)
@ -42,7 +42,7 @@ func viewerHandler(w http.ResponseWriter, r *http.Request) {
} }
// Get stream ID from URL, or from domain name // Get stream ID from URL, or from domain name
path := r.URL.Path[1:] path := strings.ToLower(r.URL.Path[1:])
host := r.Host host := r.Host
if strings.Contains(host, ":") { if strings.Contains(host, ":") {
realHost, _, err := net.SplitHostPort(r.Host) realHost, _, err := net.SplitHostPort(r.Host)
@ -58,7 +58,7 @@ func viewerHandler(w http.ResponseWriter, r *http.Request) {
if path == "about" { if path == "about" {
path = "" path = ""
} else { } else {
path = streamID path = strings.ToLower(streamID)
} }
} }
@ -97,6 +97,7 @@ func staticHandler() http.Handler {
func statisticsHandler(w http.ResponseWriter, r *http.Request) { func statisticsHandler(w http.ResponseWriter, r *http.Request) {
// Retrieve stream name from URL // Retrieve stream name from URL
name := strings.SplitN(strings.Replace(r.URL.Path[7:], "/", "", -1), "@", 2)[0] name := strings.SplitN(strings.Replace(r.URL.Path[7:], "/", "", -1), "@", 2)[0]
name = strings.ToLower(name)
userCount := 0 userCount := 0
// Clients have a unique generated identifier per session, that expires in 40 seconds. // Clients have a unique generated identifier per session, that expires in 40 seconds.

View File

@ -25,7 +25,7 @@
<ul> <ul>
<li> <li>
<b>Serveur :</b> <b>Serveur :</b>
<code>srt://{{.Cfg.Hostname}}:{{.Cfg.SRTServerPort}}?IDENTIFIANT:MOT_DE_PASSE</code>, <code>srt://{{.Cfg.Hostname}}:{{.Cfg.SRTServerPort}}?streamid=IDENTIFIANT:MOT_DE_PASSE</code>,
avec <code>IDENTIFIANT</code> et <code>MOT_DE_PASSE</code> avec <code>IDENTIFIANT</code> et <code>MOT_DE_PASSE</code>
vos identifiants. vos identifiants.
</li> </li>