diff --git a/hack/compare-hash.sh b/hack/compare-hash.sh index a8a4498d7..03806e4ac 100755 --- a/hack/compare-hash.sh +++ b/hack/compare-hash.sh @@ -2,14 +2,19 @@ set -euo pipefail -openssl sha256 "$1" "$2" - -xxd "$1" > "1.xxd" -xxd "$2" > "2.xxd" -(diff --color=always "1.xxd" "2.xxd" || true) | head -n 20 -ffmpeg -y -loglevel fatal -i "$1" -c copy -f framemd5 "1.md5" -ffmpeg -y -loglevel fatal -i "$2" -c copy -f framemd5 "2.md5" -(diff --color=always "1.md5" "2.md5" || true) +ONE="$(realpath "$1")" +TWO="$(realpath "$2")" + +cd "$(mktemp -d)" +openssl sha256 "$ONE" "$TWO" + +xxd "$ONE" > "1.xxd" +xxd "$TWO" > "2.xxd" +(diff --color=always "1.xxd" "2.xxd" || true) | head -n 50 + +ffmpeg -y -loglevel fatal -i "$ONE" -c copy -f framemd5 "1.md5" +ffmpeg -y -loglevel fatal -i "$TWO" -c copy -f framemd5 "2.md5" +(diff --color=always "1.md5" "2.md5" || true) | head -n 20 # ffprobe -loglevel fatal -show_frames "$1" > "1.frames" # ffprobe -loglevel fatal -show_frames "$2" > "2.frames" diff --git a/pkg/c2patypes/stream_adapter.go b/pkg/c2patypes/stream_adapter.go index 33017bea9..1e244752f 100644 --- a/pkg/c2patypes/stream_adapter.go +++ b/pkg/c2patypes/stream_adapter.go @@ -137,9 +137,9 @@ func (m *ManyStreams) AddStream(stream io.ReadSeeker) { m.Streams = append(m.Streams, stream) } -func (m *ManyStreams) Next() (*iroh_streamplace.Stream, error) { +func (m *ManyStreams) Next() *iroh_streamplace.Stream { if m.index >= len(m.Streams) { - return nil, nil + return nil } stream := m.Streams[m.index] m.index++ @@ -149,5 +149,5 @@ func (m *ManyStreams) Next() (*iroh_streamplace.Stream, error) { } else { r = NewReader(stream) } - return &r, nil + return &r } diff --git a/pkg/cmd/split.go b/pkg/cmd/split.go index 00c62cc15..987b7ae93 100644 --- a/pkg/cmd/split.go +++ b/pkg/cmd/split.go @@ -2,26 +2,59 @@ package cmd import ( "context" + "fmt" + "io" "os" "path/filepath" + "stream.place/streamplace/pkg/log" "stream.place/streamplace/pkg/media" ) func Split(ctx context.Context, inFile, outDir string) error { - bs, err := os.ReadFile(inFile) + inFD, err := os.Open(inFile) if err != nil { return err } - outFiles, err := media.SplitSegments(ctx, bs) + defer inFD.Close() + err = os.MkdirAll(outDir, 0755) if err != nil { return err } - for _, outFile := range outFiles { - err = os.WriteFile(filepath.Join(outDir, outFile.Filename), outFile.Data, 0644) + + names := []string{} + + err = media.SplitSegments(ctx, inFD, func(fname string) media.ReadWriteSeekCloser { + fullPath := filepath.Join(outDir, fname) + names = append(names, fullPath) + log.Log(ctx, "creating segment file", "path", fullPath) + fd, err := os.Create(fullPath) + if err != nil { + log.Error(ctx, "failed to open segment file", "error", err) + return nil + } + return fd + }) + if err != nil { + return fmt.Errorf("failed to split segments: %w", err) + } + + for _, name := range names { + fd, err := os.Open(name) + if err != nil { + return fmt.Errorf("failed to open segment file: %w", err) + } + defer fd.Close() + bs, err := io.ReadAll(fd) if err != nil { - return err + return fmt.Errorf("failed to read segment file: %w", err) } + _, err = media.ValidateMP4Media(ctx, bs) + if err != nil { + return fmt.Errorf("failed to validate segment file: %w", err) + } + log.Log(ctx, "validated segment file", "path", name) } + return nil } diff --git a/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.go b/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.go index e1e9adf5f..bb584adcf 100644 --- a/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.go +++ b/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.go @@ -338,7 +338,9 @@ func init() { FfiConverterDataHandlerINSTANCE.register() FfiConverterGoSignerINSTANCE.register() + FfiConverterManySegmentsToSignINSTANCE.register() FfiConverterManyStreamsINSTANCE.register() + FfiConverterSegmentToSignINSTANCE.register() FfiConverterStreamINSTANCE.register() uniffiCheckChecksums() } @@ -403,7 +405,7 @@ func uniffiCheckChecksums() { checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { return C.uniffi_iroh_streamplace_checksum_func_resign() }) - if checksum != 33602 { + if checksum != 34597 { // If this happens try cleaning and rebuilding your project panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_func_resign: UniFFI API checksum mismatch") } @@ -561,11 +563,20 @@ func uniffiCheckChecksums() { panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_gosigner_sign: UniFFI API checksum mismatch") } } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_manysegmentstosign_next() + }) + if checksum != 53885 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_manysegmentstosign_next: UniFFI API checksum mismatch") + } + } { checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { return C.uniffi_iroh_streamplace_checksum_method_manystreams_next() }) - if checksum != 46617 { + if checksum != 50757 { // If this happens try cleaning and rebuilding your project panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_manystreams_next: UniFFI API checksum mismatch") } @@ -723,6 +734,51 @@ func uniffiCheckChecksums() { panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_publickey_fmt_short: UniFFI API checksum mismatch") } } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_segmenttosign_unsigned_seg_stream() + }) + if checksum != 25252 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_segmenttosign_unsigned_seg_stream: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_segmenttosign_manifest_id() + }) + if checksum != 60736 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_segmenttosign_manifest_id: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_segmenttosign_cert() + }) + if checksum != 51060 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_segmenttosign_cert: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_segmenttosign_output_seg_stream() + }) + if checksum != 6113 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_segmenttosign_output_seg_stream: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_iroh_streamplace_checksum_method_segmenttosign_close() + }) + if checksum != 39185 { + // If this happens try cleaning and rebuilding your project + panic("iroh_streamplace: uniffi_iroh_streamplace_checksum_method_segmenttosign_close: UniFFI API checksum mismatch") + } + } { checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t { return C.uniffi_iroh_streamplace_checksum_method_stream_read_stream() @@ -1744,30 +1800,126 @@ func (c FfiConverterGoSigner) register() { C.uniffi_iroh_streamplace_fn_init_callback_vtable_gosigner(&UniffiVTableCallbackInterfaceGoSignerINSTANCE) } +type ManySegmentsToSign interface { + Next() *SegmentToSign +} +type ManySegmentsToSignImpl struct { + ffiObject FfiObject +} + +func (_self *ManySegmentsToSignImpl) Next() *SegmentToSign { + _pointer := _self.ffiObject.incrementPointer("ManySegmentsToSign") + defer _self.ffiObject.decrementPointer() + return FfiConverterOptionalSegmentToSignINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI { + return GoRustBuffer{ + inner: C.uniffi_iroh_streamplace_fn_method_manysegmentstosign_next( + _pointer, _uniffiStatus), + } + })) +} +func (object *ManySegmentsToSignImpl) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterManySegmentsToSign struct { + handleMap *concurrentHandleMap[ManySegmentsToSign] +} + +var FfiConverterManySegmentsToSignINSTANCE = FfiConverterManySegmentsToSign{ + handleMap: newConcurrentHandleMap[ManySegmentsToSign](), +} + +func (c FfiConverterManySegmentsToSign) Lift(pointer unsafe.Pointer) ManySegmentsToSign { + result := &ManySegmentsToSignImpl{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_iroh_streamplace_fn_clone_manysegmentstosign(pointer, status) + }, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_iroh_streamplace_fn_free_manysegmentstosign(pointer, status) + }, + ), + } + runtime.SetFinalizer(result, (*ManySegmentsToSignImpl).Destroy) + return result +} + +func (c FfiConverterManySegmentsToSign) Read(reader io.Reader) ManySegmentsToSign { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterManySegmentsToSign) Lower(value ManySegmentsToSign) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := unsafe.Pointer(uintptr(c.handleMap.insert(value))) + return pointer + +} + +func (c FfiConverterManySegmentsToSign) Write(writer io.Writer, value ManySegmentsToSign) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerManySegmentsToSign struct{} + +func (_ FfiDestroyerManySegmentsToSign) Destroy(value ManySegmentsToSign) { + if val, ok := value.(*ManySegmentsToSignImpl); ok { + val.Destroy() + } else { + panic("Expected *ManySegmentsToSignImpl") + } +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignMethod0 +func iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignMethod0(uniffiHandle C.uint64_t, uniffiOutReturn *C.RustBuffer, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterManySegmentsToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + res := + uniffiObj.Next() + + *uniffiOutReturn = FfiConverterOptionalSegmentToSignINSTANCE.Lower(res) +} + +var UniffiVTableCallbackInterfaceManySegmentsToSignINSTANCE = C.UniffiVTableCallbackInterfaceManySegmentsToSign{ + next: (C.UniffiCallbackInterfaceManySegmentsToSignMethod0)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignMethod0), + + uniffiFree: (C.UniffiCallbackInterfaceFree)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignFree), +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignFree +func iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignFree(handle C.uint64_t) { + FfiConverterManySegmentsToSignINSTANCE.handleMap.remove(uint64(handle)) +} + +func (c FfiConverterManySegmentsToSign) register() { + C.uniffi_iroh_streamplace_fn_init_callback_vtable_manysegmentstosign(&UniffiVTableCallbackInterfaceManySegmentsToSignINSTANCE) +} + type ManyStreams interface { // Get the next stream from the many streams - Next() (*Stream, error) + Next() *Stream } type ManyStreamsImpl struct { ffiObject FfiObject } // Get the next stream from the many streams -func (_self *ManyStreamsImpl) Next() (*Stream, error) { +func (_self *ManyStreamsImpl) Next() *Stream { _pointer := _self.ffiObject.incrementPointer("ManyStreams") defer _self.ffiObject.decrementPointer() - _uniffiRV, _uniffiErr := rustCallWithError[SpError](FfiConverterSpError{}, func(_uniffiStatus *C.RustCallStatus) RustBufferI { + return FfiConverterOptionalStreamINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI { return GoRustBuffer{ inner: C.uniffi_iroh_streamplace_fn_method_manystreams_next( _pointer, _uniffiStatus), } - }) - if _uniffiErr != nil { - var _uniffiDefaultValue *Stream - return _uniffiDefaultValue, _uniffiErr - } else { - return FfiConverterOptionalStreamINSTANCE.Lift(_uniffiRV), nil - } + })) } func (object *ManyStreamsImpl) Destroy() { runtime.SetFinalizer(object, nil) @@ -1833,24 +1985,9 @@ func iroh_streamplace_cgo_dispatchCallbackInterfaceManyStreamsMethod0(uniffiHand panic(fmt.Errorf("no callback in handle map: %d", handle)) } - res, err := + res := uniffiObj.Next() - if err != nil { - var actualError *SpError - if errors.As(err, &actualError) { - *callStatus = C.RustCallStatus{ - code: C.int8_t(uniffiCallbackResultError), - errorBuf: FfiConverterSpErrorINSTANCE.Lower(actualError), - } - } else { - *callStatus = C.RustCallStatus{ - code: C.int8_t(uniffiCallbackUnexpectedResultError), - } - } - return - } - *uniffiOutReturn = FfiConverterOptionalStreamINSTANCE.Lower(res) } @@ -2580,6 +2717,209 @@ func (_ FfiDestroyerPublicKey) Destroy(value *PublicKey) { value.Destroy() } +type SegmentToSign interface { + UnsignedSegStream() Stream + ManifestId() string + Cert() []byte + OutputSegStream() Stream + Close() +} +type SegmentToSignImpl struct { + ffiObject FfiObject +} + +func (_self *SegmentToSignImpl) UnsignedSegStream() Stream { + _pointer := _self.ffiObject.incrementPointer("SegmentToSign") + defer _self.ffiObject.decrementPointer() + return FfiConverterStreamINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_iroh_streamplace_fn_method_segmenttosign_unsigned_seg_stream( + _pointer, _uniffiStatus) + })) +} + +func (_self *SegmentToSignImpl) ManifestId() string { + _pointer := _self.ffiObject.incrementPointer("SegmentToSign") + defer _self.ffiObject.decrementPointer() + return FfiConverterStringINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI { + return GoRustBuffer{ + inner: C.uniffi_iroh_streamplace_fn_method_segmenttosign_manifest_id( + _pointer, _uniffiStatus), + } + })) +} + +func (_self *SegmentToSignImpl) Cert() []byte { + _pointer := _self.ffiObject.incrementPointer("SegmentToSign") + defer _self.ffiObject.decrementPointer() + return FfiConverterBytesINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI { + return GoRustBuffer{ + inner: C.uniffi_iroh_streamplace_fn_method_segmenttosign_cert( + _pointer, _uniffiStatus), + } + })) +} + +func (_self *SegmentToSignImpl) OutputSegStream() Stream { + _pointer := _self.ffiObject.incrementPointer("SegmentToSign") + defer _self.ffiObject.decrementPointer() + return FfiConverterStreamINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_iroh_streamplace_fn_method_segmenttosign_output_seg_stream( + _pointer, _uniffiStatus) + })) +} + +func (_self *SegmentToSignImpl) Close() { + _pointer := _self.ffiObject.incrementPointer("SegmentToSign") + defer _self.ffiObject.decrementPointer() + rustCall(func(_uniffiStatus *C.RustCallStatus) bool { + C.uniffi_iroh_streamplace_fn_method_segmenttosign_close( + _pointer, _uniffiStatus) + return false + }) +} +func (object *SegmentToSignImpl) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterSegmentToSign struct { + handleMap *concurrentHandleMap[SegmentToSign] +} + +var FfiConverterSegmentToSignINSTANCE = FfiConverterSegmentToSign{ + handleMap: newConcurrentHandleMap[SegmentToSign](), +} + +func (c FfiConverterSegmentToSign) Lift(pointer unsafe.Pointer) SegmentToSign { + result := &SegmentToSignImpl{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_iroh_streamplace_fn_clone_segmenttosign(pointer, status) + }, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_iroh_streamplace_fn_free_segmenttosign(pointer, status) + }, + ), + } + runtime.SetFinalizer(result, (*SegmentToSignImpl).Destroy) + return result +} + +func (c FfiConverterSegmentToSign) Read(reader io.Reader) SegmentToSign { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterSegmentToSign) Lower(value SegmentToSign) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := unsafe.Pointer(uintptr(c.handleMap.insert(value))) + return pointer + +} + +func (c FfiConverterSegmentToSign) Write(writer io.Writer, value SegmentToSign) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerSegmentToSign struct{} + +func (_ FfiDestroyerSegmentToSign) Destroy(value SegmentToSign) { + if val, ok := value.(*SegmentToSignImpl); ok { + val.Destroy() + } else { + panic("Expected *SegmentToSignImpl") + } +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod0 +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod0(uniffiHandle C.uint64_t, uniffiOutReturn *unsafe.Pointer, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterSegmentToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + res := + uniffiObj.UnsignedSegStream() + + *uniffiOutReturn = FfiConverterStreamINSTANCE.Lower(res) +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod1 +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod1(uniffiHandle C.uint64_t, uniffiOutReturn *C.RustBuffer, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterSegmentToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + res := + uniffiObj.ManifestId() + + *uniffiOutReturn = FfiConverterStringINSTANCE.Lower(res) +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod2 +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod2(uniffiHandle C.uint64_t, uniffiOutReturn *C.RustBuffer, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterSegmentToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + res := + uniffiObj.Cert() + + *uniffiOutReturn = FfiConverterBytesINSTANCE.Lower(res) +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod3 +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod3(uniffiHandle C.uint64_t, uniffiOutReturn *unsafe.Pointer, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterSegmentToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + res := + uniffiObj.OutputSegStream() + + *uniffiOutReturn = FfiConverterStreamINSTANCE.Lower(res) +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod4 +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod4(uniffiHandle C.uint64_t, uniffiOutReturn *C.void, callStatus *C.RustCallStatus) { + handle := uint64(uniffiHandle) + uniffiObj, ok := FfiConverterSegmentToSignINSTANCE.handleMap.tryGet(handle) + if !ok { + panic(fmt.Errorf("no callback in handle map: %d", handle)) + } + + uniffiObj.Close() + +} + +var UniffiVTableCallbackInterfaceSegmentToSignINSTANCE = C.UniffiVTableCallbackInterfaceSegmentToSign{ + unsignedSegStream: (C.UniffiCallbackInterfaceSegmentToSignMethod0)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod0), + manifestId: (C.UniffiCallbackInterfaceSegmentToSignMethod1)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod1), + cert: (C.UniffiCallbackInterfaceSegmentToSignMethod2)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod2), + outputSegStream: (C.UniffiCallbackInterfaceSegmentToSignMethod3)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod3), + close: (C.UniffiCallbackInterfaceSegmentToSignMethod4)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod4), + + uniffiFree: (C.UniffiCallbackInterfaceFree)(C.iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignFree), +} + +//export iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignFree +func iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignFree(handle C.uint64_t) { + FfiConverterSegmentToSignINSTANCE.handleMap.remove(uint64(handle)) +} + +func (c FfiConverterSegmentToSign) register() { + C.uniffi_iroh_streamplace_fn_init_callback_vtable_segmenttosign(&UniffiVTableCallbackInterfaceSegmentToSignINSTANCE) +} + // This allows for a callback stream over the Uniffi interface. // Implement these stream functions in the foreign language // and this will provide Rust Stream trait implementations @@ -4941,6 +5281,43 @@ func (_ FfiDestroyerOptionalBytes) Destroy(value *[]byte) { } } +type FfiConverterOptionalSegmentToSign struct{} + +var FfiConverterOptionalSegmentToSignINSTANCE = FfiConverterOptionalSegmentToSign{} + +func (c FfiConverterOptionalSegmentToSign) Lift(rb RustBufferI) *SegmentToSign { + return LiftFromRustBuffer[*SegmentToSign](c, rb) +} + +func (_ FfiConverterOptionalSegmentToSign) Read(reader io.Reader) *SegmentToSign { + if readInt8(reader) == 0 { + return nil + } + temp := FfiConverterSegmentToSignINSTANCE.Read(reader) + return &temp +} + +func (c FfiConverterOptionalSegmentToSign) Lower(value *SegmentToSign) C.RustBuffer { + return LowerIntoRustBuffer[*SegmentToSign](c, value) +} + +func (_ FfiConverterOptionalSegmentToSign) Write(writer io.Writer, value *SegmentToSign) { + if value == nil { + writeInt8(writer, 0) + } else { + writeInt8(writer, 1) + FfiConverterSegmentToSignINSTANCE.Write(writer, *value) + } +} + +type FfiDestroyerOptionalSegmentToSign struct{} + +func (_ FfiDestroyerOptionalSegmentToSign) Destroy(value *SegmentToSign) { + if value != nil { + FfiDestroyerSegmentToSign{}.Destroy(*value) + } +} + type FfiConverterOptionalStream struct{} var FfiConverterOptionalStreamINSTANCE = FfiConverterOptionalStream{} @@ -5058,49 +5435,6 @@ func (FfiDestroyerSequenceString) Destroy(sequence []string) { } } -type FfiConverterSequenceBytes struct{} - -var FfiConverterSequenceBytesINSTANCE = FfiConverterSequenceBytes{} - -func (c FfiConverterSequenceBytes) Lift(rb RustBufferI) [][]byte { - return LiftFromRustBuffer[[][]byte](c, rb) -} - -func (c FfiConverterSequenceBytes) Read(reader io.Reader) [][]byte { - length := readInt32(reader) - if length == 0 { - return nil - } - result := make([][]byte, 0, length) - for i := int32(0); i < length; i++ { - result = append(result, FfiConverterBytesINSTANCE.Read(reader)) - } - return result -} - -func (c FfiConverterSequenceBytes) Lower(value [][]byte) C.RustBuffer { - return LowerIntoRustBuffer[[][]byte](c, value) -} - -func (c FfiConverterSequenceBytes) Write(writer io.Writer, value [][]byte) { - if len(value) > math.MaxInt32 { - panic("[][]byte is too large to fit into Int32") - } - - writeInt32(writer, int32(len(value))) - for _, item := range value { - FfiConverterBytesINSTANCE.Write(writer, item) - } -} - -type FfiDestroyerSequenceBytes struct{} - -func (FfiDestroyerSequenceBytes) Destroy(sequence [][]byte) { - for _, value := range sequence { - FfiDestroyerBytes{}.Destroy(value) - } -} - type FfiConverterSequencePublicKey struct{} var FfiConverterSequencePublicKeyINSTANCE = FfiConverterSequencePublicKey{} @@ -5312,9 +5646,9 @@ func NodeIdFromTicket(ticketStr string) (*PublicKey, error) { } } -func Resign(unsignedSegData ManyStreams, signedConcatData Stream, manifestList []string, certs [][]byte, output ManyStreams) error { +func Resign(segsToSign ManySegmentsToSign, signedConcatData Stream) error { _, _uniffiErr := rustCallWithError[SpError](FfiConverterSpError{}, func(_uniffiStatus *C.RustCallStatus) bool { - C.uniffi_iroh_streamplace_fn_func_resign(FfiConverterManyStreamsINSTANCE.Lower(unsignedSegData), FfiConverterStreamINSTANCE.Lower(signedConcatData), FfiConverterSequenceStringINSTANCE.Lower(manifestList), FfiConverterSequenceBytesINSTANCE.Lower(certs), FfiConverterManyStreamsINSTANCE.Lower(output), _uniffiStatus) + C.uniffi_iroh_streamplace_fn_func_resign(FfiConverterManySegmentsToSignINSTANCE.Lower(segsToSign), FfiConverterStreamINSTANCE.Lower(signedConcatData), _uniffiStatus) return false }) return _uniffiErr.AsError() diff --git a/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.h b/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.h index 4bdb73af7..8e7eaf97e 100644 --- a/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.h +++ b/pkg/iroh/generated/iroh_streamplace/iroh_streamplace.h @@ -405,6 +405,20 @@ static void call_UniffiCallbackInterfaceGoSignerMethod0( } +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_MANY_SEGMENTS_TO_SIGN_METHOD0 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_MANY_SEGMENTS_TO_SIGN_METHOD0 +typedef void (*UniffiCallbackInterfaceManySegmentsToSignMethod0)(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceManySegmentsToSignMethod0( + UniffiCallbackInterfaceManySegmentsToSignMethod0 cb, uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + #endif #ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_MANY_STREAMS_METHOD0 #define UNIFFI_FFIDEF_CALLBACK_INTERFACE_MANY_STREAMS_METHOD0 @@ -419,6 +433,76 @@ static void call_UniffiCallbackInterfaceManyStreamsMethod0( } +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD0 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD0 +typedef void (*UniffiCallbackInterfaceSegmentToSignMethod0)(uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceSegmentToSignMethod0( + UniffiCallbackInterfaceSegmentToSignMethod0 cb, uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD1 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD1 +typedef void (*UniffiCallbackInterfaceSegmentToSignMethod1)(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceSegmentToSignMethod1( + UniffiCallbackInterfaceSegmentToSignMethod1 cb, uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD2 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD2 +typedef void (*UniffiCallbackInterfaceSegmentToSignMethod2)(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceSegmentToSignMethod2( + UniffiCallbackInterfaceSegmentToSignMethod2 cb, uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD3 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD3 +typedef void (*UniffiCallbackInterfaceSegmentToSignMethod3)(uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceSegmentToSignMethod3( + UniffiCallbackInterfaceSegmentToSignMethod3 cb, uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD4 +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_SEGMENT_TO_SIGN_METHOD4 +typedef void (*UniffiCallbackInterfaceSegmentToSignMethod4)(uint64_t uniffi_handle, void* uniffi_out_return, RustCallStatus* callStatus ); + +// Making function static works arround: +// https://github.com/golang/go/issues/11263 +static void call_UniffiCallbackInterfaceSegmentToSignMethod4( + UniffiCallbackInterfaceSegmentToSignMethod4 cb, uint64_t uniffi_handle, void* uniffi_out_return, RustCallStatus* callStatus ) +{ + return cb(uniffi_handle, uniffi_out_return, callStatus ); +} + + #endif #ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_STREAM_METHOD0 #define UNIFFI_FFIDEF_CALLBACK_INTERFACE_STREAM_METHOD0 @@ -477,6 +561,14 @@ typedef struct UniffiVTableCallbackInterfaceGoSigner { UniffiCallbackInterfaceFree uniffiFree; } UniffiVTableCallbackInterfaceGoSigner; +#endif +#ifndef UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_MANY_SEGMENTS_TO_SIGN +#define UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_MANY_SEGMENTS_TO_SIGN +typedef struct UniffiVTableCallbackInterfaceManySegmentsToSign { + UniffiCallbackInterfaceManySegmentsToSignMethod0 next; + UniffiCallbackInterfaceFree uniffiFree; +} UniffiVTableCallbackInterfaceManySegmentsToSign; + #endif #ifndef UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_MANY_STREAMS #define UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_MANY_STREAMS @@ -485,6 +577,18 @@ typedef struct UniffiVTableCallbackInterfaceManyStreams { UniffiCallbackInterfaceFree uniffiFree; } UniffiVTableCallbackInterfaceManyStreams; +#endif +#ifndef UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_SEGMENT_TO_SIGN +#define UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_SEGMENT_TO_SIGN +typedef struct UniffiVTableCallbackInterfaceSegmentToSign { + UniffiCallbackInterfaceSegmentToSignMethod0 unsignedSegStream; + UniffiCallbackInterfaceSegmentToSignMethod1 manifestId; + UniffiCallbackInterfaceSegmentToSignMethod2 cert; + UniffiCallbackInterfaceSegmentToSignMethod3 outputSegStream; + UniffiCallbackInterfaceSegmentToSignMethod4 close; + UniffiCallbackInterfaceFree uniffiFree; +} UniffiVTableCallbackInterfaceSegmentToSign; + #endif #ifndef UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_STREAM #define UNIFFI_FFIDEF_V_TABLE_CALLBACK_INTERFACE_STREAM @@ -622,6 +726,26 @@ void uniffi_iroh_streamplace_fn_init_callback_vtable_gosigner(UniffiVTableCallba RustBuffer uniffi_iroh_streamplace_fn_method_gosigner_sign(void* ptr, RustBuffer data, RustCallStatus *out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_MANYSEGMENTSTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_MANYSEGMENTSTOSIGN +void* uniffi_iroh_streamplace_fn_clone_manysegmentstosign(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FREE_MANYSEGMENTSTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FREE_MANYSEGMENTSTOSIGN +void uniffi_iroh_streamplace_fn_free_manysegmentstosign(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_INIT_CALLBACK_VTABLE_MANYSEGMENTSTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_INIT_CALLBACK_VTABLE_MANYSEGMENTSTOSIGN +void uniffi_iroh_streamplace_fn_init_callback_vtable_manysegmentstosign(UniffiVTableCallbackInterfaceManySegmentsToSign* vtable +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_MANYSEGMENTSTOSIGN_NEXT +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_MANYSEGMENTSTOSIGN_NEXT +RustBuffer uniffi_iroh_streamplace_fn_method_manysegmentstosign_next(void* ptr, RustCallStatus *out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_MANYSTREAMS #define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_MANYSTREAMS void* uniffi_iroh_streamplace_fn_clone_manystreams(void* ptr, RustCallStatus *out_status @@ -792,6 +916,46 @@ RustBuffer uniffi_iroh_streamplace_fn_method_publickey_fmt_short(void* ptr, Rust RustBuffer uniffi_iroh_streamplace_fn_method_publickey_uniffi_trait_display(void* ptr, RustCallStatus *out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_SEGMENTTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_SEGMENTTOSIGN +void* uniffi_iroh_streamplace_fn_clone_segmenttosign(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FREE_SEGMENTTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FREE_SEGMENTTOSIGN +void uniffi_iroh_streamplace_fn_free_segmenttosign(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_INIT_CALLBACK_VTABLE_SEGMENTTOSIGN +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_INIT_CALLBACK_VTABLE_SEGMENTTOSIGN +void uniffi_iroh_streamplace_fn_init_callback_vtable_segmenttosign(UniffiVTableCallbackInterfaceSegmentToSign* vtable +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_UNSIGNED_SEG_STREAM +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_UNSIGNED_SEG_STREAM +void* uniffi_iroh_streamplace_fn_method_segmenttosign_unsigned_seg_stream(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_MANIFEST_ID +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_MANIFEST_ID +RustBuffer uniffi_iroh_streamplace_fn_method_segmenttosign_manifest_id(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_CERT +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_CERT +RustBuffer uniffi_iroh_streamplace_fn_method_segmenttosign_cert(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_OUTPUT_SEG_STREAM +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_OUTPUT_SEG_STREAM +void* uniffi_iroh_streamplace_fn_method_segmenttosign_output_seg_stream(void* ptr, RustCallStatus *out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_CLOSE +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_METHOD_SEGMENTTOSIGN_CLOSE +void uniffi_iroh_streamplace_fn_method_segmenttosign_close(void* ptr, RustCallStatus *out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_STREAM #define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_CLONE_STREAM void* uniffi_iroh_streamplace_fn_clone_stream(void* ptr, RustCallStatus *out_status @@ -885,7 +1049,7 @@ void* uniffi_iroh_streamplace_fn_func_node_id_from_ticket(RustBuffer ticket_str, #endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FUNC_RESIGN #define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FUNC_RESIGN -void uniffi_iroh_streamplace_fn_func_resign(void* unsigned_seg_data, void* signed_concat_data, RustBuffer manifest_list, RustBuffer certs, void* output, RustCallStatus *out_status +void uniffi_iroh_streamplace_fn_func_resign(void* segs_to_sign, void* signed_concat_data, RustCallStatus *out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_FN_FUNC_SIGN @@ -1319,6 +1483,12 @@ uint16_t uniffi_iroh_streamplace_checksum_method_filter_timestamps(void #define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_GOSIGNER_SIGN uint16_t uniffi_iroh_streamplace_checksum_method_gosigner_sign(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_MANYSEGMENTSTOSIGN_NEXT +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_MANYSEGMENTSTOSIGN_NEXT +uint16_t uniffi_iroh_streamplace_checksum_method_manysegmentstosign_next(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_MANYSTREAMS_NEXT @@ -1427,6 +1597,36 @@ uint16_t uniffi_iroh_streamplace_checksum_method_publickey_equal(void #define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_PUBLICKEY_FMT_SHORT uint16_t uniffi_iroh_streamplace_checksum_method_publickey_fmt_short(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_UNSIGNED_SEG_STREAM +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_UNSIGNED_SEG_STREAM +uint16_t uniffi_iroh_streamplace_checksum_method_segmenttosign_unsigned_seg_stream(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_MANIFEST_ID +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_MANIFEST_ID +uint16_t uniffi_iroh_streamplace_checksum_method_segmenttosign_manifest_id(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_CERT +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_CERT +uint16_t uniffi_iroh_streamplace_checksum_method_segmenttosign_cert(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_OUTPUT_SEG_STREAM +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_OUTPUT_SEG_STREAM +uint16_t uniffi_iroh_streamplace_checksum_method_segmenttosign_output_seg_stream(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_CLOSE +#define UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_SEGMENTTOSIGN_CLOSE +uint16_t uniffi_iroh_streamplace_checksum_method_segmenttosign_close(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_IROH_STREAMPLACE_CHECKSUM_METHOD_STREAM_READ_STREAM @@ -1512,8 +1712,16 @@ uint32_t ffi_iroh_streamplace_uniffi_contract_version(void void iroh_streamplace_cgo_dispatchCallbackInterfaceDataHandlerFree(uint64_t handle); void iroh_streamplace_cgo_dispatchCallbackInterfaceGoSignerMethod0(uint64_t uniffi_handle, RustBuffer data, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); void iroh_streamplace_cgo_dispatchCallbackInterfaceGoSignerFree(uint64_t handle); + void iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignMethod0(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceManySegmentsToSignFree(uint64_t handle); void iroh_streamplace_cgo_dispatchCallbackInterfaceManyStreamsMethod0(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); void iroh_streamplace_cgo_dispatchCallbackInterfaceManyStreamsFree(uint64_t handle); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod0(uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod1(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod2(uint64_t uniffi_handle, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod3(uint64_t uniffi_handle, void** uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignMethod4(uint64_t uniffi_handle, void* uniffi_out_return, RustCallStatus* callStatus ); + void iroh_streamplace_cgo_dispatchCallbackInterfaceSegmentToSignFree(uint64_t handle); void iroh_streamplace_cgo_dispatchCallbackInterfaceStreamMethod0(uint64_t uniffi_handle, uint64_t length, RustBuffer* uniffi_out_return, RustCallStatus* callStatus ); void iroh_streamplace_cgo_dispatchCallbackInterfaceStreamMethod1(uint64_t uniffi_handle, int64_t pos, uint64_t mode, uint64_t* uniffi_out_return, RustCallStatus* callStatus ); void iroh_streamplace_cgo_dispatchCallbackInterfaceStreamMethod2(uint64_t uniffi_handle, RustBuffer data, uint64_t* uniffi_out_return, RustCallStatus* callStatus ); diff --git a/pkg/media/deterministic_muxing_test.go b/pkg/media/deterministic_muxing_test.go index c844bd9fb..4da1cddd4 100644 --- a/pkg/media/deterministic_muxing_test.go +++ b/pkg/media/deterministic_muxing_test.go @@ -64,10 +64,19 @@ func splitAndCombineTest(t *testing.T, tempDir string, inputDir string) string { for i := 0; i < muxTestCount; i++ { segDir, err := os.MkdirTemp(tempDir, "segs") require.NoError(t, err) - splitSegs, err := SegmentFileUnsigned(context.Background(), combinedFiles[0]) + splitSegsCh := make(chan *SplitSegment) + go func() { + err := SegmentFileUnsigned(context.Background(), combinedFiles[0], splitSegsCh) + require.NoError(t, err) + close(splitSegsCh) + }() + splitSegs := []*SplitSegment{} + for seg := range splitSegsCh { + splitSegs = append(splitSegs, seg) + } require.NoError(t, err) for i, unsignedSeg := range splitSegs { - err = os.WriteFile(filepath.Join(segDir, fmt.Sprintf("unsigned_%06d.mp4", i)), unsignedSeg, 0644) + err = os.WriteFile(filepath.Join(segDir, fmt.Sprintf("unsigned_%06d.mp4", i)), unsignedSeg.Data, 0644) require.NoError(t, err) } report, err := makeSegDirReport(t, segDir) diff --git a/pkg/media/ingredient_test.go b/pkg/media/ingredient_test.go index 12072c6e6..4ce9e5d06 100644 --- a/pkg/media/ingredient_test.go +++ b/pkg/media/ingredient_test.go @@ -25,6 +25,7 @@ func TestIngredientConcat(t *testing.T) { require.NoError(t, err) // defer os.RemoveAll(tempDir) segments := remote.RemoteArchive("14ba49843a56c0510e2b5059123abd2f98a502b1f4c7d706b0ae1066d438468c/BigBuckBunny_1sGOP_4kp60_NoBframes.1min.tar.gz") + // segments := "/Users/iameli/testvids/hour-of-silksong/unsigned-minute" // segments := "/Users/iameli/testvids/three" testVids := []string{} segEntries, err := os.ReadDir(segments) @@ -72,23 +73,32 @@ func TestIngredientConcat(t *testing.T) { concatSegment := filepath.Join(tempDir, "ingredient-concat.mp4") err = os.WriteFile(concatSegment, signedConcatBS, 0644) require.NoError(t, err) - splitSegs, err := SegmentFileUnsigned(context.Background(), concatSegment) + splitSegsCh := make(chan *SplitSegment) + go func() { + err := SegmentFileUnsigned(context.Background(), concatSegment, splitSegsCh) + require.NoError(t, err) + close(splitSegsCh) + }() + splitSegs := []*SplitSegment{} + for seg := range splitSegsCh { + splitSegs = append(splitSegs, seg) + } require.NoError(t, err) splitSegDir := makeTestSubdir(t, tempDir, "split-segments") for i, unsignedSeg := range splitSegs { - err = os.WriteFile(filepath.Join(splitSegDir, fmt.Sprintf("unsigned_%06d.mp4", i)), unsignedSeg, 0644) + err = os.WriteFile(filepath.Join(splitSegDir, fmt.Sprintf("unsigned_%06d.mp4", i)), unsignedSeg.Data, 0644) require.NoError(t, err) } splitReport, err := makeSegDirReport(t, splitSegDir) require.NoError(t, err) require.NoError(t, splitReport.CheckEquals(firstReport), "split segments are not equal to original segments") signedSplitSegDir := makeTestSubdir(t, tempDir, "signed-split-segments") - resignedSegs, err := SplitSegments(context.Background(), signedConcatBS) - require.NoError(t, err) - for _, resignedSeg := range resignedSegs { - err = os.WriteFile(filepath.Join(signedSplitSegDir, resignedSeg.Filename), resignedSeg.Data, 0644) + err = SplitSegments(context.Background(), bytes.NewReader(signedConcatBS), func(fname string) ReadWriteSeekCloser { + fd, err := os.Create(filepath.Join(signedSplitSegDir, fname)) require.NoError(t, err) - } + return fd + }) + require.NoError(t, err) signedSplitReport, err := makeSegDirReport(t, signedSplitSegDir) require.NoError(t, err) require.NoError(t, signedSplitReport.CheckEquals(signedReport), "split signed segments are not equal to signed segments") diff --git a/pkg/media/segment_split.go b/pkg/media/segment_split.go index 026065b3e..080b8c8ea 100644 --- a/pkg/media/segment_split.go +++ b/pkg/media/segment_split.go @@ -1,12 +1,14 @@ package media import ( - "bytes" "context" "encoding/json" + "errors" "fmt" + "io" "sort" + "golang.org/x/sync/errgroup" "stream.place/streamplace/pkg/aqio" c2patypes "stream.place/streamplace/pkg/c2patypes" "stream.place/streamplace/pkg/iroh/generated/iroh_streamplace" @@ -28,26 +30,94 @@ type ManifestAndMetadata struct { SegmentMetadata *SegmentMetadata } +type ReadWriteSeekCloser interface { + io.ReadWriteSeeker + io.Closer +} + +type SegmentToSign struct { + unsignedSeg io.ReadSeeker + manifestId string + cert []byte + outputSeg io.ReadWriteSeeker + closeCh chan struct{} +} + +func NewSegmentToSign(unsignedSeg io.ReadSeeker, manifestId string, cert []byte, outputSeg io.ReadWriteSeeker) *SegmentToSign { + return &SegmentToSign{ + unsignedSeg: unsignedSeg, + manifestId: manifestId, + cert: cert, + outputSeg: outputSeg, + closeCh: make(chan struct{}), + } +} + +func (s *SegmentToSign) UnsignedSegStream() iroh_streamplace.Stream { + return c2patypes.NewReader(s.unsignedSeg) +} + +func (s *SegmentToSign) ManifestId() string { + return s.manifestId +} + +func (s *SegmentToSign) Cert() []byte { + return s.cert +} + +func (s *SegmentToSign) OutputSegStream() iroh_streamplace.Stream { + return c2patypes.NewWriter(s.outputSeg) +} + +func (s *SegmentToSign) Close() { + close(s.closeCh) +} + +func (s *SegmentToSign) Done() { + <-s.closeCh +} + +type ManySegmentsToSign struct { + segmentCh chan iroh_streamplace.SegmentToSign + readyCh chan struct{} +} + +func (m *ManySegmentsToSign) Next() *iroh_streamplace.SegmentToSign { + if m.readyCh != nil { + close(m.readyCh) + m.readyCh = nil + } + seg := <-m.segmentCh + if seg == nil { + return nil + } + return &seg +} + // split a signed concatenated mp4 into its constituent signed segments -func SplitSegments(ctx context.Context, input []byte) ([]SplitSegment, error) { - manifestsStr, err := iroh_streamplace.GetManifests(c2patypes.NewReader(aqio.NewReadWriteSeeker(input))) +func SplitSegments(ctx context.Context, input io.ReadSeeker, cb func(fname string) ReadWriteSeekCloser) error { + manifestsStr, err := iroh_streamplace.GetManifests(c2patypes.NewReader(input)) + if err != nil { + return fmt.Errorf("failed to get manifests: %w", err) + } + _, err = input.Seek(0, io.SeekStart) if err != nil { - return nil, fmt.Errorf("failed to get manifests: %w", err) + return fmt.Errorf("failed to seek to start: %w", err) } var manifests ManifestResult err = json.Unmarshal([]byte(manifestsStr), &manifests) if err != nil { - return nil, fmt.Errorf("failed to unmarshal manifests: %w", err) + return fmt.Errorf("failed to unmarshal manifests: %w", err) } manifestList := []ManifestAndMetadata{} for _, manifest := range manifests.Manifests { metadata, err := ParseSegmentAssertions(context.Background(), &manifest) - if err == ErrMissingMetadata { + if errors.Is(err, ErrMissingMetadata) { log.Error(ctx, "missing metadata", "manifest", manifest.Label) continue } if err != nil { - return nil, fmt.Errorf("failed to parse segment assertions: %w", err) + return fmt.Errorf("failed to parse segment assertions: %w", err) } manifestList = append(manifestList, ManifestAndMetadata{ Manifest: manifest, @@ -59,39 +129,87 @@ func SplitSegments(ctx context.Context, input []byte) ([]SplitSegment, error) { m2 := manifestList[j] return m1.SegmentMetadata.StartTime.Time().Before(m2.SegmentMetadata.StartTime.Time()) }) - manifestStrs := []string{} certList := [][]byte{} for _, manifest := range manifestList { - manifestStrs = append(manifestStrs, *manifest.Manifest.Label) certList = append(certList, []byte(manifests.Certs[*manifest.Manifest.Label])) } - unsignedSegs, err := SegmentUnsigned(ctx, bytes.NewReader(input)) - if err != nil { - return nil, fmt.Errorf("failed to segment file: %w", err) - } - inputStreams := c2patypes.NewManyStreams() - outputStreams := c2patypes.NewManyStreams() - for _, unsignedSeg := range unsignedSegs { - inputStreams.AddStream(aqio.NewReadWriteSeeker(unsignedSeg)) - outputStreams.AddStream(aqio.NewReadWriteSeeker([]byte{})) - } - err = iroh_streamplace.Resign(inputStreams, c2patypes.NewReader(aqio.NewReadWriteSeeker(input)), manifestStrs, certList, outputStreams) - if err != nil { - return nil, fmt.Errorf("failed to resign segments: %w", err) + + segmentCh := make(chan iroh_streamplace.SegmentToSign) + readyCh := make(chan struct{}) + mss := &ManySegmentsToSign{ + segmentCh: segmentCh, + readyCh: readyCh, } - splitSegments := []SplitSegment{} - for i, resignedSeg := range outputStreams.Streams { - aqrws := resignedSeg.(*aqio.ReadWriteSeeker) - data, err := aqrws.Bytes() + g, ctx := errgroup.WithContext(ctx) + unsignedCh := make(chan *SplitSegment) + + // note: we're passing the input to two places here and need to make sure + // they're not running into problems with concurrent seeking. so we use + // this readyCh as a hack - it only fires after Rust is done with the input + + g.Go(func() error { + err := iroh_streamplace.Resign(mss, c2patypes.NewReader(input)) if err != nil { - return nil, fmt.Errorf("failed to read resigned segment: %w", err) + return fmt.Errorf("failed to resign segments: %w", err) } - meta := manifestList[i].SegmentMetadata - fname := fmt.Sprintf("%s.mp4", meta.StartTime.FileSafeString()) - splitSegments = append(splitSegments, SplitSegment{ - Filename: fname, - Data: data, - }) + return nil + }) + g.Go(func() error { + defer close(unsignedCh) + <-readyCh + // rust is done with the input, rewind and start segmenting + _, err := input.Seek(0, io.SeekStart) + if err != nil { + return fmt.Errorf("failed to seek to start: %w", err) + } + err = SegmentUnsigned(ctx, input, unsignedCh) + if err != nil { + return fmt.Errorf("failed to segment file: %w", err) + } + return nil + }) + g.Go(func() error { + defer close(segmentCh) + i := 0 + for unsignedSeg := range unsignedCh { + meta := manifestList[i].SegmentMetadata + fname := fmt.Sprintf("%s.mp4", meta.StartTime.FileSafeString()) + rwsc := cb(fname) + rws := aqio.NewReadWriteSeeker(unsignedSeg.Data) + ss := NewSegmentToSign(c2patypes.NewReader(rws), *manifestList[i].Manifest.Label, certList[i], rwsc) + i += 1 + segmentCh <- ss + ss.Done() + err := rwsc.Close() + if err != nil { + return fmt.Errorf("failed to close segment file: %w", err) + } + } + return nil + }) + + err = g.Wait() + if err != nil { + return fmt.Errorf("failed to split segments: %w", err) } - return splitSegments, nil + + // err = iroh_streamplace.Resign(inputStreams, c2patypes.NewReader(aqio.NewReadWriteSeeker(input)), manifestStrs, certList, outputStreams) + // if err != nil { + // fmt.Errorf("failed to resign segments: %w", err) + // } + // splitSegments := []SplitSegment{} + // for i, resignedSeg := range outputStreams.Streams { + // aqrws := resignedSeg.(*aqio.ReadWriteSeeker) + // data, err := aqrws.Bytes() + // if err != nil { + // fmt.Errorf("failed to read resigned segment: %w", err) + // } + // meta := manifestList[i].SegmentMetadata + // fname := fmt.Sprintf("%s.mp4", meta.StartTime.FileSafeString()) + // splitSegments = append(splitSegments, SplitSegment{ + // Filename: fname, + // Data: data, + // }) + // } + return nil } diff --git a/pkg/media/segmenter.go b/pkg/media/segmenter.go index d9697e522..70526f3cf 100644 --- a/pkg/media/segmenter.go +++ b/pkg/media/segmenter.go @@ -133,17 +133,17 @@ func (mm *MediaManager) SegmentAndSignElem(ctx context.Context, ms MediaSigner) }) } -func SegmentFileUnsigned(ctx context.Context, input string) ([][]byte, error) { +func SegmentFileUnsigned(ctx context.Context, input string, ch chan *SplitSegment) error { fd, err := os.OpenFile(input, os.O_RDONLY, 0644) log.Log(ctx, "reading file", "file", input) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return fmt.Errorf("failed to read file: %w", err) } defer fd.Close() - return SegmentUnsigned(ctx, fd) + return SegmentUnsigned(ctx, fd, ch) } -func SegmentUnsigned(ctx context.Context, input io.Reader) ([][]byte, error) { +func SegmentUnsigned(ctx context.Context, input io.Reader, ch chan *SplitSegment) error { ctx, cancel := context.WithCancel(ctx) defer cancel() pipelineSlice := []string{ @@ -153,12 +153,12 @@ func SegmentUnsigned(ctx context.Context, input io.Reader) ([][]byte, error) { } pipeline, err := gst.NewPipelineFromString(strings.Join(pipelineSlice, "\n")) if err != nil { - return nil, fmt.Errorf("error creating MKVIngest pipeline: %w", err) + return fmt.Errorf("error creating MKVIngest pipeline: %w", err) } srcele, err := pipeline.GetElementByName("appsrc") if err != nil { - return nil, err + return err } src := app.SrcFromElement(srcele) src.SetCallbacks(&app.SourceCallbacks{ @@ -166,33 +166,35 @@ func SegmentUnsigned(ctx context.Context, input io.Reader) ([][]byte, error) { }) videoParseEle, err := pipeline.GetElementByName("videoparse") if err != nil { - return nil, err + return err } - segs := [][]byte{} segmenter, err := SegmentElem(ctx, func(ctx context.Context, buf []byte, now int64) error { - segs = append(segs, buf) + ch <- &SplitSegment{ + Filename: fmt.Sprintf("%d.mp4", now), + Data: buf, + } return nil }) if err != nil { - return nil, err + return err } err = pipeline.Add(segmenter) if err != nil { - return nil, err + return err } err = videoParseEle.Link(segmenter) if err != nil { - return nil, err + return err } audioparse, err := pipeline.GetElementByName("audioparse") if err != nil { - return nil, err + return err } err = audioparse.Link(segmenter) if err != nil { - return nil, err + return err } busErr := make(chan error) @@ -204,7 +206,7 @@ func SegmentUnsigned(ctx context.Context, input io.Reader) ([][]byte, error) { err = pipeline.SetState(gst.StatePlaying) if err != nil { - return nil, err + return err } defer func() { @@ -216,8 +218,8 @@ func SegmentUnsigned(ctx context.Context, input io.Reader) ([][]byte, error) { err = <-busErr if err != nil { - return nil, err + return err } - return segs, nil + return nil } diff --git a/pkg/media/validate.go b/pkg/media/validate.go index 03303df78..c6acaa761 100644 --- a/pkg/media/validate.go +++ b/pkg/media/validate.go @@ -23,8 +23,9 @@ import ( ) type ManifestAndCert struct { - Manifest c2patypes.Manifest `json:"manifest"` - Cert string `json:"cert"` + Manifest c2patypes.Manifest `json:"manifest"` + Cert string `json:"cert"` + ValidationResults c2patypes.ValidationResults `json:"validation_results"` } func (mm *MediaManager) ValidateMP4(ctx context.Context, input io.Reader, local bool) error { @@ -218,6 +219,17 @@ func ValidateMP4Media(ctx context.Context, buf []byte) (*ValidationResult, error if err != nil { return nil, err } + activeManifest := maniCert.ValidationResults.ActiveManifest + if activeManifest == nil { + return nil, fmt.Errorf("no active manifest found") + } + if activeManifest.Failure == nil { + return nil, fmt.Errorf("active manifest failure array not found?!") + } + if len(activeManifest.Failure) > 0 { + bs, _ := json.Marshal(activeManifest.Failure) + return nil, fmt.Errorf("active manifest has failures: %s", string(bs)) + } pub, err := signers.ParseES256KCert([]byte(maniCert.Cert)) if err != nil { return nil, err diff --git a/rust/iroh-streamplace/src/c2pa.rs b/rust/iroh-streamplace/src/c2pa.rs index 90b950cd5..57b614b24 100644 --- a/rust/iroh-streamplace/src/c2pa.rs +++ b/rust/iroh-streamplace/src/c2pa.rs @@ -30,7 +30,8 @@ pub fn get_manifest_and_cert(data: &dyn Stream) -> Result { let result = serde_json::json!({ "manifest": manifest, - "cert": cert_chain + "cert": cert_chain, + "validation_results": reader.validation_results(), }); return Ok(result.to_string()); @@ -161,13 +162,24 @@ pub fn get_manifests(data: &dyn Stream) -> Result { Ok(result.to_string()) } +#[uniffi::export(with_foreign)] +pub trait SegmentToSign: Send + Sync { + fn unsigned_seg_stream(&self) -> Arc; + fn manifest_id(&self) -> String; + fn cert(&self) -> Vec; + fn output_seg_stream(&self) -> Arc; + fn close(&self); +} + +#[uniffi::export(with_foreign)] +pub trait ManySegmentsToSign: Send + Sync { + fn next(&self) -> Option>; +} + #[uniffi::export] pub fn resign( - unsigned_seg_data: &dyn ManyStreams, + segs_to_sign: &dyn ManySegmentsToSign, signed_concat_data: &dyn Stream, - manifest_list: Vec, - certs: Vec>, - output: &dyn ManyStreams, ) -> Result<(), SPError> { let mut validation_log = StatusTracker::default(); @@ -179,27 +191,11 @@ pub fn resign( ) .map_err(|e| SPError::C2paError(format!("from_stream failed: {}", e)))?; - for (i, manifest_id) in manifest_list.iter().enumerate() { - let unsigned_seg_data_stream = match unsigned_seg_data.next() { - Ok(Some(stream)) => stream, - Ok(None) => return Err(SPError::C2paError("Input stream not found".to_string())), - Err(e) => { - return Err(SPError::C2paError(format!( - "Error getting input stream: {}", - e - ))); - } - }; - let output_stream = match output.next() { - Ok(Some(stream)) => stream, - Ok(None) => return Err(SPError::C2paError("Output stream not found".to_string())), - Err(e) => { - return Err(SPError::C2paError(format!( - "Error getting output stream: {}", - e - ))); - } - }; + while let Some(seg) = segs_to_sign.next() { + let unsigned_seg_data_stream = seg.unsigned_seg_stream(); + let manifest_id = seg.manifest_id(); + let cert = seg.cert(); + let output_stream = seg.output_seg_stream(); let mut input_cursor = StreamAdapter::from(&*unsigned_seg_data_stream); let mut output_cursor = StreamAdapter::from(&*output_stream); @@ -216,7 +212,7 @@ pub fn resign( let callback_signer = CallbackSigner::new( move |_context: *const (), _data: &[u8]| Ok(signature_val.clone()), c2pa::SigningAlg::Es256K, - certs[i].clone(), + cert, ); let mut seg_store = Store::new(); @@ -235,6 +231,7 @@ pub fn resign( &jumbf_bytes, ) .map_err(|e| SPError::C2paError(format!("save_jumbf_to_stream failed: {}", e)))?; + seg.close(); } Ok(()) @@ -261,7 +258,7 @@ pub fn sign_with_ingredients( ); let mut builder = Builder::from_json(&manifest).map_err(|e| SPError::C2paError(e.to_string()))?; - while let Ok(Some(ingredient)) = ingredients.next() { + while let Some(ingredient) = ingredients.next() { let mut cursor = StreamAdapter::from(&*ingredient); let ingredient = Ingredient::from_stream("video/mp4", &mut cursor) .map_err(|e| SPError::C2paError(e.to_string()))?; diff --git a/rust/iroh-streamplace/src/streams.rs b/rust/iroh-streamplace/src/streams.rs index d3dd536f5..df80818db 100644 --- a/rust/iroh-streamplace/src/streams.rs +++ b/rust/iroh-streamplace/src/streams.rs @@ -127,7 +127,7 @@ impl<'a> Write for StreamAdapter<'a> { #[uniffi::export(with_foreign)] pub trait ManyStreams: Send + Sync { /// Get the next stream from the many streams - fn next(&self) -> Result>, SPError>; + fn next(&self) -> Option>; } #[cfg(test)]