package wire import ( "bytes" "io" "runtime" "syscall" "smesh.lol/pkg/mediaproxy" ) // ProxyWorker is the spawn target for a media proxy domain. // Uses ChildPipeFd directly (bypassing the broken spawn channel binding) // to read Codec-encoded ProxyRequest frames and write ProxyResponse frames. // chanID=0 = requests (in direction), chanID=1 = responses (out direction). func ProxyWorker(in chan ProxyRequest, out chan ProxyResponse) { fd := int32(runtime.ChildPipeFd) if fd < 0 { return } for { var hdr [6]byte if !proxyReadAll(fd, hdr[:]) { return } chanID := uint16(hdr[0])<<8 | uint16(hdr[1]) l := uint32(hdr[2])<<24 | uint32(hdr[3])<<16 | uint32(hdr[4])<<8 | uint32(hdr[5]) if chanID != 0 || l == 0 || l > 8<<20 { proxyDrain(fd, l) continue } payload := []byte{:l} if !proxyReadAll(fd, payload) { return } var req ProxyRequest if err := req.DecodeFrom(bytes.NewReader(payload)); err != nil { continue } resp := ProxyResponse{ReqID: req.ReqID} maxBytes := int64(req.MaxBytes) if maxBytes <= 0 { maxBytes = 32 * 1024 * 1024 } status, upstream, body, err := mediaproxy.Fetch(string(req.URL), maxBytes) if err != nil { resp.Status = -1 resp.Err = []byte(err.Error()) } else { resp.Status = int32(status) if status >= 200 && status < 300 { ct := upstream["content-type"] if !proxyAllowedCT(ct) { resp.Status = 415 } else { resp.ContentType = []byte(ct) resp.Body = body } } } var buf bytes.Buffer resp.EncodeTo(&buf) data := buf.Bytes() lresp := uint32(len(data)) var rhdr [6]byte rhdr[0] = 0; rhdr[1] = 1 rhdr[2] = byte(lresp >> 24); rhdr[3] = byte(lresp >> 16) rhdr[4] = byte(lresp >> 8); rhdr[5] = byte(lresp) frame := []byte{:0:6 + int(lresp)} frame = append(frame, rhdr[:]...) frame = append(frame, data...) syscall.Write(int(fd), frame) } } func proxyAllowedCT(ct string) bool { if len(ct) >= 6 && (ct[:6] == "image/" || ct[:6] == "video/") { return true } return ct == "application/octet-stream" || ct == "application/octet-stream; charset=utf-8" } func proxyReadAll(fd int32, buf []byte) bool { got := 0 for got < len(buf) { n, err := syscall.Read(int(fd), buf[got:]) if n <= 0 || err != nil { return false } got += n } return true } func proxyDrain(fd int32, n uint32) { discard := []byte{:512} for n > 0 { chunk := int(n) if chunk > 512 { chunk = 512 } nr, err := syscall.Read(int(fd), discard[:chunk]) if err != nil || nr <= 0 { return } n -= uint32(nr) } } type proxyReader struct{ fd int32 } func (r *proxyReader) Read(b []byte) (int, error) { n, err := syscall.Read(int(r.fd), b) if n == 0 && err == nil { return 0, io.EOF } return n, err }