Ejemplo n.º 1
0
/*
sourceHandler is the handler for icecast source clients. It acknowledges the
client before sending it over to the icecast manager.
*/
func sourceHandler(w http.ResponseWriter, r *http.Request, clientID *ClientID) {
	/* Handler for icecast source requests. This can only be called by
	   authenticated requests */

	// Icecast clients expect a 200 OK response before sending data.
	w.WriteHeader(http.StatusOK)
	// Make sure to send the extra newline to signify end of headers
	io.WriteString(w, "\r\n")
	// And flush the data because buffering is FUN!
	if flush, ok := w.(http.Flusher); ok {
		flush.Flush()
	}

	// We can now start hijacking the connection
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "Webserver doesn't support hijacking.",
			http.StatusInternalServerError)
		return
	}

	conn, bufrw, err := hj.Hijack()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Create a client struct, this is defined in client.go
	client := NewClient(conn, bufrw, clientID)

	ClientManager.Receiver <- client

	// The manager will handle everything from this point on
	return
}
Ejemplo n.º 2
0
func listclientsHandler(w http.ResponseWriter, r *http.Request,
	clientID *ClientID) {

	response := []byte("<?xml version=\"1.0\"?>\n<icestats><source mount=\"" + clientID.Mount + "\"><Listeners>0</Listeners></source></icestats>\n")

	w.Header().Set("Content-Length", strconv.Itoa(len(response)))
	w.Write(response)
}
Ejemplo n.º 3
0
/*
adminHandler is called whenever the /admin URL is requested. The two URLs
special cased for metadata and listener listing respectively are not included
and are handled by different handlers.
*/
func adminHandler(w http.ResponseWriter, r *http.Request, clientID *ClientID) {
	HandlerLock.Lock()
	if r.URL.Path == "/admin" {
		Body := ""
		for mount, clients := range HandlerMounts {
			MountBody := ""
			for i, c := range clients {
				name := c.ClientID.Name
				if i == 0 {
					name = fmt.Sprintf("<b>%s</b>", c.ClientID.Name)
				}
				ClientBody := fmt.Sprintf(ClientHTML, name, c.Metadata, c.ClientID.Agent, mount, i, "")
				MountBody = MountBody + ClientBody
			}
			Body = Body + fmt.Sprintf(MountHTML, mount, MountBody)
		}
		w.Write([]byte(fmt.Sprintf(AdminHTML, Body)))
	} else if r.URL.Path == "/admin/kick" {
		MountName := r.URL.Query().Get("mount")
		Id, err := strconv.Atoi(r.URL.Query().Get("num"))
		if err == nil {
			clients, ok := HandlerMounts[MountName]
			if ok {
				clients[Id].Conn.Close()
			}
		}
		w.Header().Set("Location", "/admin")
		w.WriteHeader(301)
	}
	HandlerLock.Unlock()
}
Ejemplo n.º 4
0
func metadataHandler(w http.ResponseWriter, r *http.Request,
	clientID *ClientID) {
	/* Handles a metadata request from a source. This should make sure
	   an user cannot set the metadata of another users stream and even save
	   metadata of inactive users */
	var meta string

	parsed := r.URL.Query()

	meta = parsed.Get("song")
	if meta == "" {
		// Someone is trying to not update the metadata?
		// Ignore the f****r
		return
	}

	var charset string
	if e := parsed.Get("charset"); e != "" {
		// TODO: Check if user specified encodings are not vulnerable to exploits
		charset = e
	} else {
		charset = "latin1"
	}

	// This isn't so much a parser as it is a encoding handler.
	meta = ParseMetadata(charset, meta)

	// Sending empty metadata is useless, so we don't
	if meta != "" {
		// And we are done here, send the data we have so far along
		ClientManager.MetaChan <- &MetaPack{Data: meta, ID: clientID, Seen: false}
	}

	response := []byte("<?xml version=\"1.0\"?>\n<iceresponse><message>Metadata update successful</message><return>1</return></iceresponse>\n")

	w.Header().Set("Content-Length", strconv.Itoa(len(response)))
	w.Write(response)
}
Ejemplo n.º 5
0
func AuthenticationError(w http.ResponseWriter, r *http.Request, err error) {
	/* Returns an authentication icecast error page when called. */
	w.Header().Set("WWW-Authenticate", `Basic realm="`+realm+`"`)
	w.WriteHeader(401)

	response := "401 Unauthorized\n"
	if err != nil {
		response += err.Error()
	}
	w.Write([]byte(response))
}