tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
FileUploadProvider.cs
Go to the documentation of this file.
1using System;
2using System.IO;
3using System.Threading;
4using System.Threading.Tasks;
5
6using Microsoft.AspNetCore.WebUtilities;
7
12
14{
17 {
19 public FileTicketResponse Ticket { get; }
20
24 readonly CancellationTokenSource ticketExpiryCts;
25
29 readonly TaskCompletionSource<Stream> streamTcs;
30
34 readonly TaskCompletionSource completionTcs;
35
40
45
52 {
53 Ticket = ticket ?? throw new ArgumentNullException(nameof(ticket));
54
55 ticketExpiryCts = new CancellationTokenSource();
56 streamTcs = new TaskCompletionSource<Stream>();
57 completionTcs = new TaskCompletionSource();
58 this.streamKind = streamKind;
59 }
60
62 public ValueTask DisposeAsync()
63 {
64 ticketExpiryCts.Dispose();
65 completionTcs.TrySetResult();
66 return ValueTask.CompletedTask;
67 }
68
70 public async Task<Stream> GetResult(CancellationToken cancellationToken)
71 {
72 using (cancellationToken.Register(() => streamTcs.TrySetCanceled(cancellationToken)))
73 using (ticketExpiryCts.Token.Register(() => streamTcs.TrySetResult(null)))
74 return await streamTcs.Task;
75 }
76
80 public void Expire()
81 {
82 if (!completionTcs.Task.IsCompleted)
83 ticketExpiryCts.Cancel();
84 }
85
92 public async Task<ErrorMessageResponse> Completion(Stream stream, CancellationToken cancellationToken)
93 {
94 ArgumentNullException.ThrowIfNull(stream);
95
96 if (ticketExpiryCts.IsCancellationRequested)
97 return new ErrorMessageResponse(ErrorCode.ResourceNotPresent);
98
99 Stream bufferedStream = null;
100 try
101 {
102 switch (streamKind)
103 {
104 case FileUploadStreamKind.ForSynchronousIO:
105 // big reads, we should buffer to disk
106 // NOTE: We do this here ONLY because we can't use async methods in a synchronous context
107 // Ideally we should be doing 0 buffering here, but this is a compromise
108 bufferedStream = new FileBufferingReadStream(stream, DefaultIOManager.DefaultBufferSize);
109 await bufferedStream.DrainAsync(cancellationToken);
110 break;
111 case FileUploadStreamKind.None:
112 break;
113 default:
114 throw new InvalidOperationException($"Invalid FileUploadStreamKind: {streamKind}");
115 }
116 }
117 catch
118 {
119 if (bufferedStream != null)
120 await bufferedStream.DisposeAsync();
121
122 throw;
123 }
124
125 await using (bufferedStream)
126 {
127 streamTcs.TrySetResult(bufferedStream ?? stream);
128
129 await completionTcs.Task.WithToken(cancellationToken);
130 return errorMessage;
131 }
132 }
133
135 public void SetError(ErrorCode errorCode, string additionalData)
136 {
137 if (errorMessage != null)
138 throw new InvalidOperationException("Error already set!");
139
140 errorMessage = new ErrorMessageResponse(errorCode)
141 {
142 AdditionalData = additionalData,
143 };
144 completionTcs.TrySetResult();
145 }
146 }
147}
Represents an error message returned by the server.
Response for when file transfers are necessary.
IIOManager that resolves paths to Environment.CurrentDirectory.
const int DefaultBufferSize
Default FileStream buffer size used by .NET.
FileTicketResponse Ticket
The FileTicketResponse.
FileUploadProvider(FileTicketResponse ticket, FileUploadStreamKind streamKind)
Initializes a new instance of the FileUploadProvider class.
readonly FileUploadStreamKind streamKind
Determines the backing for the Stream returned from GetResult(CancellationToken).
async Task< ErrorMessageResponse > Completion(Stream stream, CancellationToken cancellationToken)
Resolve the stream for the FileUploadProvider and awaits the upload.
readonly CancellationTokenSource ticketExpiryCts
The CancellationTokenSource for the ticket duration.
ErrorMessageResponse errorMessage
The ErrorMessageResponse that occurred while processing the upload if any.
readonly TaskCompletionSource completionTcs
The TaskCompletionSource that completes in IDisposable.Dispose or when SetError(ErrorCode,...
void SetError(ErrorCode errorCode, string additionalData)
Sets an errorCode that indicates why the consuming operation could not complete. May only be called ...
async Task< Stream > GetResult(CancellationToken cancellationToken)
Gets the provided Stream. May be called multiple times, though cancelling any may cause all calls to ...
readonly TaskCompletionSource< Stream > streamTcs
The TaskCompletionSource<TResult> for the Stream.
void Expire()
Expire the FileUploadProvider.
A FileTicketResponse that waits for a pending upload.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition: ErrorCode.cs:11
FileUploadStreamKind
Determines the type of global::System.IO.Stream returned from IFileUploadTicket's created from IFileT...