tgstation-server
The /tg/station 13 server suite
CommContext.cs
Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Host.IO;
10 
11 namespace Tgstation.Server.Host.Components.Interop
12 {
14  sealed class CommContext : ICommContext
15  {
20 
24  readonly ILogger<CommContext> logger;
25 
29  readonly FileSystemWatcher fileSystemWatcher;
30 
34  readonly CancellationTokenSource cancellationTokenSource;
35 
39  readonly CancellationToken cancellationToken;
40 
45 
49  bool disposed;
50 
58  public CommContext(IIOManager ioManager, ILogger<CommContext> logger, string directory, string filter)
59  {
60  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
61  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
62 
63  directory = ioManager.ResolvePath(directory) ?? throw new ArgumentNullException(nameof(directory));
64  if (filter == null)
65  throw new ArgumentNullException(nameof(filter));
66 
67  fileSystemWatcher = new FileSystemWatcher(directory, filter)
68  {
69  EnableRaisingEvents = true,
70  IncludeSubdirectories = false,
71  NotifyFilter = NotifyFilters.LastWrite
72  };
73 
74  fileSystemWatcher.Created += HandleWrite;
75  fileSystemWatcher.Changed += HandleWrite;
76 
77  cancellationTokenSource = new CancellationTokenSource();
78  cancellationToken = cancellationTokenSource.Token;
79  disposed = false;
80  }
81 
83  public void Dispose()
84  {
85  if (disposed)
86  return;
87  disposed = true;
88  fileSystemWatcher.Dispose();
89  cancellationTokenSource.Cancel();
90  cancellationTokenSource.Dispose();
91  }
92 
98  async void HandleWrite(object sender, FileSystemEventArgs e) //this is what async void was made for
99  {
100  try
101  {
102  var fileBytes = await ioManager.ReadAllBytes(e.FullPath, cancellationToken).ConfigureAwait(false);
103  var file = Encoding.UTF8.GetString(fileBytes);
104 
105  logger.LogTrace("Read interop command json: {0}", file);
106 
107  CommCommand command;
108  try
109  {
110  command = new CommCommand
111  {
112  Parameters = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, object>>(file),
113  RawJson = file
114  };
115  }
116  catch (JsonException ex)
117  {
118  //file not fully written yet
119  logger.LogDebug("Suppressing json convert exception for command file write: {0}", ex);
120  return;
121  }
122 
123  await (handler?.HandleInterop(command, cancellationToken) ?? Task.CompletedTask).ConfigureAwait(false);
124  }
125  catch (OperationCanceledException) { }
126  catch (Exception ex)
127  {
128  logger.LogDebug("Exception while trying to handle command json write: {0}", ex);
129  }
130  }
131 
133  public void RegisterHandler(ICommHandler handler)
134  {
135  if (this.handler != null)
136  throw new InvalidOperationException("RegisterHandler already called!");
137  this.handler = handler ?? throw new ArgumentNullException(nameof(handler));
138  }
139  }
140 }
readonly CancellationToken cancellationToken
The CancellationToken for the CommContext
Definition: CommContext.cs:39
Represents a registration of an interop session
Definition: ICommContext.cs:8
readonly FileSystemWatcher fileSystemWatcher
The FileSystemWatcher for the CommContext
Definition: CommContext.cs:29
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
readonly ILogger< CommContext > logger
The ILogger for the CommContext
Definition: CommContext.cs:24
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
Definition: CommContext.cs:133
ICommHandler handler
The ICommHandler for the CommContext
Definition: CommContext.cs:44
CommContext(IIOManager ioManager, ILogger< CommContext > logger, string directory, string filter)
Construct an CommContext
Definition: CommContext.cs:58
readonly IIOManager ioManager
The IIOManager for the CommContext
Definition: CommContext.cs:19
bool disposed
If the CommContext has been disposed
Definition: CommContext.cs:49
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for the CommContext
Definition: CommContext.cs:34
async void HandleWrite(object sender, FileSystemEventArgs e)
Runs when the fileSystemWatcher triggers
Definition: CommContext.cs:98
Interface for using filesystems
Definition: IIOManager.cs:11