package notify import ( itransfer "b612.me/notify/internal/transfer" "errors" ) type transferControlRuntimeAccessor interface { getTransferRuntime() *transferRuntime } func transferControlRuntimeFromClient(c Client) *transferRuntime { if c == nil { return nil } accessor, ok := any(c).(transferControlRuntimeAccessor) if !ok { return nil } return accessor.getTransferRuntime() } func transferControlRuntimeFromServer(s Server) *transferRuntime { if s == nil { return nil } accessor, ok := any(s).(transferControlRuntimeAccessor) if !ok { return nil } return accessor.getTransferRuntime() } func transferControlPrepareBegin(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, publicScope string, transportGeneration uint64, req TransferBeginRequest) { if runtime == nil || req.TransferID == "" { return } runtime.ensureTransferDescriptor(direction, runtimeScope, publicScope, transportGeneration, itransfer.Descriptor{ ID: req.TransferID, Channel: itransfer.Channel(req.Channel), Size: req.Size, Checksum: req.Checksum, Metadata: itransfer.Metadata(cloneTransferMetadata(req.Metadata)), }) runtime.recordStage(direction, runtimeScope, req.TransferID, "begin") } func transferControlFinishBegin(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, transferID string, resp TransferBeginResponse, err error) { if runtime == nil { return } transferID = transferControlTransferID(transferID, resp.TransferID) if transferID == "" { return } if err != nil { runtime.recordFailureStage(direction, runtimeScope, transferID, "begin") runtime.fail(direction, runtimeScope, transferID, err) return } runtime.resume(direction, runtimeScope, transferID, transferControlOffset(resp.NextOffset)) } func transferControlPrepareResume(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, publicScope string, transportGeneration uint64, req TransferResumeRequest) { if runtime == nil || req.TransferID == "" { return } runtime.ensureTransferDescriptor(direction, runtimeScope, publicScope, transportGeneration, itransfer.Descriptor{ ID: req.TransferID, Channel: itransfer.DataChannel, }) runtime.recordStage(direction, runtimeScope, req.TransferID, "resume") } func transferControlFinishResume(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, transferID string, resp TransferResumeResponse, err error) { if runtime == nil { return } transferID = transferControlTransferID(transferID, resp.TransferID) if transferID == "" { return } if err != nil { runtime.recordFailureStage(direction, runtimeScope, transferID, "resume") runtime.fail(direction, runtimeScope, transferID, err) return } runtime.resume(direction, runtimeScope, transferID, transferControlOffset(resp.NextOffset)) } func transferControlPrepareCommit(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, publicScope string, transportGeneration uint64, req TransferCommitRequest) { if runtime == nil || req.TransferID == "" { return } runtime.ensureTransferDescriptor(direction, runtimeScope, publicScope, transportGeneration, itransfer.Descriptor{ ID: req.TransferID, Channel: itransfer.DataChannel, Size: req.Size, Checksum: req.Checksum, }) runtime.recordStage(direction, runtimeScope, req.TransferID, "commit") if direction == fileTransferDirectionSend { runtime.beginCommit(direction, runtimeScope, req.TransferID) } } func transferControlFinishCommit(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, transferID string, resp TransferCommitResponse, err error) { if runtime == nil { return } transferID = transferControlTransferID(transferID, resp.TransferID) if transferID == "" { return } if err != nil { runtime.recordFailureStage(direction, runtimeScope, transferID, "commit") runtime.fail(direction, runtimeScope, transferID, err) return } if direction == fileTransferDirectionReceive { runtime.beginVerify(direction, runtimeScope, transferID) } runtime.complete(direction, runtimeScope, transferID) } func transferControlPrepareAbort(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, publicScope string, transportGeneration uint64, req TransferAbortRequest) { if runtime == nil || req.TransferID == "" { return } stage := transferControlAbortStage(req.Stage) runtime.ensureTransferDescriptor(direction, runtimeScope, publicScope, transportGeneration, itransfer.Descriptor{ ID: req.TransferID, Channel: itransfer.DataChannel, }) runtime.recordStage(direction, runtimeScope, req.TransferID, stage) runtime.recordFailureStage(direction, runtimeScope, req.TransferID, stage) runtime.abort(direction, runtimeScope, req.TransferID, transferControlAbortError(req.Error)) } func transferControlFinishAbort(runtime *transferRuntime, direction fileTransferDirection, runtimeScope string, transferID string, req TransferAbortRequest, resp TransferAbortResponse, err error) { if runtime == nil { return } transferID = transferControlTransferID(transferID, resp.TransferID) if transferID == "" { return } if err == nil { return } stage := transferControlAbortStage(req.Stage) runtime.recordStage(direction, runtimeScope, transferID, stage) runtime.recordFailureStage(direction, runtimeScope, transferID, stage) runtime.abort(direction, runtimeScope, transferID, err) } func transferControlAbortStage(stage string) string { if stage == "" { return "abort" } return stage } func transferControlAbortError(message string) error { if message == "" { return nil } return errors.New(message) } func transferControlTransferID(primary string, fallback string) string { if primary != "" { return primary } return fallback } func transferControlOffset(offset int64) int64 { if offset < 0 { return 0 } return offset }