Skip to content

Commit

Permalink
icecast: implement the icecast Source connection without net/http
Browse files Browse the repository at this point in the history
net/http seems to really want to read the whole response if you use
the functions provided to read a response from an arbitrary reader.
But because we don't actually send any body from the proxy it just
hangs instead. This is probably a fault in the proxy but haven't
figured out how to fix that yet.
  • Loading branch information
Wessie committed Mar 8, 2024
1 parent 315e031 commit 344b5ec
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
12 changes: 6 additions & 6 deletions streamer/icecast/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type MetadataFunc func(ctx context.Context, metadata string) error

// MetadataURL takes an URL as passed to DialURL and creates a function
// that can be called to send metadata to icecast for that DialURL
func MetadataURL(u *url.URL, opts ...Option) (MetadataFunc, error) {
func MetadataURL(u *url.URL, opts ...Option) MetadataFunc {
uc, _ := url.Parse(u.String())
mount := uc.Path

Expand All @@ -30,7 +30,7 @@ func MetadataURL(u *url.URL, opts ...Option) (MetadataFunc, error) {

req, err := http.NewRequestWithContext(ctx, http.MethodGet, uc.String(), nil)
if err != nil {
return fmt.Errorf("MetadataURL: failed to create request: %w", err)
return fmt.Errorf("MetadataFunc: failed to create request: %w", err)
}
for _, opt := range opts {
opt(req)
Expand All @@ -39,21 +39,21 @@ func MetadataURL(u *url.URL, opts ...Option) (MetadataFunc, error) {

resp, err := DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("MetadataURL: failed Do: %w", err)
return fmt.Errorf("MetadataFunc: failed Do: %w", err)
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("MetadataURL: status not ok: %w", errors.New(resp.Status))
return fmt.Errorf("MetadataFunc: status not ok: %w", errors.New(resp.Status))
}

return nil
}, nil
}
}

func Metadata(u string, opts ...Option) (MetadataFunc, error) {
uri, err := url.Parse(u)
if err != nil {
return nil, err
}
return MetadataURL(uri)
return MetadataURL(uri), nil
}
23 changes: 18 additions & 5 deletions streamer/icecast/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"fmt"
"net"
"net/http"
"net/textproto"
"net/url"
"strings"
)

var Dialer net.Dialer
Expand Down Expand Up @@ -141,14 +143,25 @@ func dial(ctx context.Context, u *url.URL, opts ...Option) (net.Conn, error) {
}

rdr := bufio.NewReader(conn)
resp, err := http.ReadResponse(rdr, req)
line, err := textproto.NewReader(rdr).ReadLine()
if err != nil {
return conn, fmt.Errorf("failed to read request: %w", err)
return conn, fmt.Errorf("failed to read response: %w", err)
}
resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return conn, fmt.Errorf("status not ok: %w", errors.New(resp.Status))
_, status, ok := strings.Cut(line, " ")
if !ok {
return conn, fmt.Errorf("malformed HTTP response: %s", line)
}

status = strings.TrimLeft(status, " ")

statusCode, _, _ := strings.Cut(status, " ")
if len(statusCode) != 3 {
return conn, fmt.Errorf("malformed HTTP status code: %s", statusCode)
}

if statusCode != "200" {
return conn, fmt.Errorf("status not ok: %w", errors.New(status))
}

return conn, nil
Expand Down

0 comments on commit 344b5ec

Please sign in to comment.