Skip to content

PR: Gap fill 4 - IProcessInfoProvider + IUpdateEventListener#341

Merged
JusterZhu merged 1 commit into
masterfrom
feat/ipc-event-bridge
May 24, 2026
Merged

PR: Gap fill 4 - IProcessInfoProvider + IUpdateEventListener#341
JusterZhu merged 1 commit into
masterfrom
feat/ipc-event-bridge

Conversation

@JusterZhu
Copy link
Copy Markdown
Collaborator

Summary

Closes #340

Changes

  • \IProcessInfoProvider\ interface + \NamedPipeProcessInfoProvider\ (preferred)
  • \EncryptedFileProcessInfoProvider\ (AES fallback)
  • \IUpdateEventListener\ — batch event registration (7 callbacks)
  • \ProgressEventArgs\ — for AddListenerProgress

Build

✅ 0 errors

Copilot AI review requested due to automatic review settings May 24, 2026 00:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes #340 by introducing new abstractions to bridge client↔upgrader communication and to simplify event registration in GeneralUpdate.Core.

Changes:

  • Added IProcessInfoProvider plus a named-pipe implementation and an encrypted-file fallback implementation.
  • Added IUpdateEventListener for batching 7 event callbacks, plus ProgressEventArgs for progress registration.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs Introduces IPC abstraction and two concrete providers (named pipe + encrypted file fallback).
src/c#/GeneralUpdate.Core/Event/IUpdateEventListener.cs Adds batch event-listener interface and a progress EventArgs type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +21
/// <summary>Progress event args for AddListenerProgress.</summary>
public class ProgressEventArgs : EventArgs
{
Comment on lines +61 to +66
public EncryptedFileProcessInfoProvider(string? basePath = null)
{
var dir = basePath ?? Path.Combine(Path.GetTempPath(), "GeneralUpdate", "ipc");
Directory.CreateDirectory(dir);
_filePath = Path.Combine(dir, $"{Guid.NewGuid():N}.enc");
}
Comment on lines +55 to +58
private static readonly byte[] Key = SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes("GeneralUpdate.ProcessInfo.IPC.v1"));
private static readonly byte[] IV = new byte[16] { 0x47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

Comment on lines +55 to +58
private static readonly byte[] Key = SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes("GeneralUpdate.ProcessInfo.IPC.v1"));
private static readonly byte[] IV = new byte[16] { 0x47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

Comment on lines +68 to +92
public Task SendAsync(ProcessInfo info, CancellationToken token = default)
{
var json = JsonSerializer.Serialize(info, ProcessInfoJsonContext.Default.ProcessInfo);
var plainBytes = Encoding.UTF8.GetBytes(json);
using var aes = Aes.Create();
aes.Key = Key; aes.IV = IV;
using var enc = aes.CreateEncryptor();
var cipher = enc.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
File.WriteAllBytes(_filePath, cipher);
return Task.CompletedTask;
}

public Task<ProcessInfo?> ReceiveAsync(CancellationToken token = default)
{
if (!File.Exists(_filePath)) return Task.FromResult<ProcessInfo?>(null);
try
{
var cipher = File.ReadAllBytes(_filePath);
using var aes = Aes.Create();
aes.Key = Key; aes.IV = IV;
using var dec = aes.CreateDecryptor();
var plain = dec.TransformFinalBlock(cipher, 0, cipher.Length);
var json = Encoding.UTF8.GetString(plain);
return Task.FromResult<ProcessInfo?>(
JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo));
Comment on lines +31 to +41
using var server = new NamedPipeServerStream(_pipeName, PipeDirection.Out);
await server.WaitForConnectionAsync(token).ConfigureAwait(false);
var json = JsonSerializer.Serialize(info, ProcessInfoJsonContext.Default.ProcessInfo);
var bytes = Encoding.UTF8.GetBytes(json);
await server.WriteAsync(bytes, 0, bytes.Length, token).ConfigureAwait(false);
}

public async Task<ProcessInfo?> ReceiveAsync(CancellationToken token = default)
{
using var client = new NamedPipeClientStream(".", _pipeName, PipeDirection.In);
await client.ConnectAsync(5000, token).ConfigureAwait(false);
@JusterZhu JusterZhu force-pushed the feat/ipc-event-bridge branch from 2bc6977 to 1c9f850 Compare May 24, 2026 00:56
…idge

- IProcessInfoProvider interface for Client-to-Upgrade IPC
- NamedPipeProcessInfoProvider — preferred, no file residue
- EncryptedFileProcessInfoProvider — AES fallback
- IUpdateEventListener — batch event registration interface
- ProgressEventArgs — AddListenerProgress event type

Closes #340
@JusterZhu JusterZhu force-pushed the feat/ipc-event-bridge branch from 1c9f850 to 6f26345 Compare May 24, 2026 01:00
@JusterZhu JusterZhu merged commit 38bc209 into master May 24, 2026
@JusterZhu JusterZhu deleted the feat/ipc-event-bridge branch May 24, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gap fill 4: IProcessInfoProvider + IUpdateEventListener + event bridge

2 participants