diff --git a/pkg/common/types.go b/pkg/common/types.go index 36de84a..ef543cd 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -28,7 +28,6 @@ type RequestHandler struct { AllowMode byte AllowedList [][]byte } - type InterfaceMode byte type InterfaceType byte diff --git a/pkg/link/link.go b/pkg/link/link.go index dcb23eb..8149561 100644 --- a/pkg/link/link.go +++ b/pkg/link/link.go @@ -7,6 +7,7 @@ import ( "crypto/rand" "crypto/sha256" "errors" + "fmt" "io" "sync" "time" @@ -14,6 +15,7 @@ import ( "github.com/Sudo-Ivan/reticulum-go/pkg/destination" "github.com/Sudo-Ivan/reticulum-go/pkg/identity" "github.com/Sudo-Ivan/reticulum-go/pkg/packet" + "github.com/Sudo-Ivan/reticulum-go/pkg/resource" "github.com/Sudo-Ivan/reticulum-go/pkg/transport" ) @@ -554,3 +556,36 @@ func (l *Link) GetStatus() byte { func (l *Link) IsActive() bool { return l.GetStatus() == STATUS_ACTIVE } + +func (l *Link) SendResource(res *resource.Resource) error { + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.status != STATUS_ACTIVE { + l.teardownReason = STATUS_FAILED + return errors.New("link not active") + } + + // Activate the resource + res.Activate() + + // Send the resource data as packets + buffer := make([]byte, resource.DEFAULT_SEGMENT_SIZE) + for { + n, err := res.Read(buffer) + if err == io.EOF { + break + } + if err != nil { + l.teardownReason = STATUS_FAILED + return fmt.Errorf("error reading resource: %v", err) + } + + if err := l.SendPacket(buffer[:n]); err != nil { + l.teardownReason = STATUS_FAILED + return fmt.Errorf("error sending resource packet: %v", err) + } + } + + return nil +} diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 7e373e3..af5bf64 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -91,6 +91,7 @@ type Resource struct { completedAt time.Time callback func(*Resource) progressCallback func(*Resource) + readOffset int64 } func New(data interface{}, autoCompress bool) (*Resource, error) { @@ -388,3 +389,35 @@ func estimateFileCompression(size int64, extension string) int64 { return int64(float64(size) * ratio) } + +func (r *Resource) Read(p []byte) (n int, err error) { + r.mutex.Lock() + defer r.mutex.Unlock() + + if r.data != nil { + if r.readOffset >= int64(len(r.data)) { + return 0, io.EOF + } + n = copy(p, r.data[r.readOffset:]) + r.readOffset += int64(n) + return n, nil + } + + if r.fileHandle != nil { + return r.fileHandle.Read(p) + } + + return 0, errors.New("no data source available") +} + +func (r *Resource) GetName() string { + r.mutex.RLock() + defer r.mutex.RUnlock() + return r.fileName +} + +func (r *Resource) GetSize() int64 { + r.mutex.RLock() + defer r.mutex.RUnlock() + return r.dataSize +}