Initial commit

This commit is contained in:
Trevor Hall 2026-03-03 23:53:04 -05:00
commit 5584446828
37 changed files with 7962 additions and 0 deletions

187
TLS/TlsStream.cs Normal file
View file

@ -0,0 +1,187 @@
/*
* Secucore
*
* Copyright (C) 2023 Trevor Hall
* All rights reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license.
*
*/
using SecuCore.Shared;
using SecuCore.TLS;
using SecuCore.TLS.Exceptions;
using System.Threading;
using System.Threading.Tasks;
using System;
namespace SecuCore.Sockets
{
public class TlsStream
{
ApplicationDataController applicationDataController;
TLSNetworkController networkController;
TLSRecordLayer recordLayer;
private int availablebytes = 0;
private byte[] availabledat = null;
public TlsStream(TCPSocket tcps)
{
networkController = new TLSNetworkController(tcps);
recordLayer = new TLSRecordLayer(networkController);
applicationDataController = new ApplicationDataController(recordLayer, 8192);
}
public TlsStream(TCPSocket tcps, TLSVersion version, int applicationReadBufferSize = 8192)
{
networkController = new TLSNetworkController(tcps);
recordLayer = new TLSRecordLayer(networkController, version);
applicationDataController = new ApplicationDataController(recordLayer, applicationReadBufferSize);
}
public Task<bool> AuthenticateAsClientAsync(string target, TLSRecordLayer.ValidateServerCertificate validateServerCertificateCallback, TLSRecordLayer.ClientCertificateRequest clientCertificateRequestCallback)
{
return recordLayer.EstablishTLSConnection(target, validateServerCertificateCallback, clientCertificateRequestCallback).AsTask();
}
private Task<byte[]> AskForDataAsync(int len)
{
TaskCompletionSource<byte[]> dtcs = new TaskCompletionSource<byte[]>();
DataRequest dr = new DataRequest()
{
length = len,
tcs = dtcs
};
applicationDataController.RequestData(dr);
return dtcs.Task;
}
public static async Task<T> TimeoutAfter<T>(Task<T> task, int millisecondsTimeout)
{
using(CancellationTokenSource cts = new CancellationTokenSource())
{
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout, cts.Token)).ConfigureAwait(false))
{
cts.Cancel();
return await task;
}
else
{
cts.Cancel();
throw new TLSNetworkException("operation timed out");
}
}
}
private async ValueTask WriteInternalAsync(byte[] buffer)
{
TaskCompletionSource dtcs = null;
dtcs = new TaskCompletionSource();
DataDispatch datd = new DataDispatch()
{
data = buffer,
tcs = dtcs
};
applicationDataController.QueueData(datd);
applicationDataController.FlushData();
await dtcs.Task.ConfigureAwait(false);
}
private async ValueTask<int> ReadInternal(byte[] buffer, int offset, int len)
{
try
{
int read = 0;
if (availablebytes == 0)
{
byte[] recieve = null;
try
{
recieve = await AskForDataAsync(-1).ConfigureAwait(false);
}
catch (Exception ex) { }
if (recieve != null)
{
if (recieve.Length > 0)
{
availabledat = recieve;
availablebytes = recieve.Length;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
if (availablebytes > len)
{
//we have more than needed
Buffer.BlockCopy(availabledat, 0, buffer, offset, len);
read += len;
byte[] remain = new byte[availablebytes - len];
Buffer.BlockCopy(availabledat, len, remain, 0, remain.Length);
availabledat = remain;
availablebytes -= len;
return read;
}
else
{
//we can exhaust our buffer
int copylen = availablebytes;
Buffer.BlockCopy(availabledat, 0, buffer, offset, copylen);
read += copylen;
availabledat = null;
availablebytes = 0;
offset += copylen;
len -= copylen;
}
return read;
}
catch(Exception ex)
{
return -1;
}
}
public ValueTask<int> ReadAsync(byte[] buffer, int offset, int count)
{
return ReadInternal(buffer, offset, count);
}
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default(CancellationToken))
{
if (offset == 0 && count == buffer.Length)
{
return WriteInternalAsync(buffer).AsTask();
}
byte[] localBuffer = new byte[count];
Buffer.BlockCopy(buffer, offset, localBuffer, 0, count);
return WriteInternalAsync(localBuffer).AsTask();
}
public Task WriteAsync(byte[] buffer, CancellationToken cancellationToken)
{
return WriteInternalAsync(buffer).AsTask();
}
public Task WriteAsync(byte[] buffer)
{
return WriteInternalAsync(buffer).AsTask();
}
public async ValueTask DisposeAsync()
{
recordLayer.Dispose();
networkController.Dispose();
applicationDataController.Shutdown(false);
recordLayer = null;
networkController = null;
applicationDataController = null;
}
}
}