tesses.http/Tesses.Http/Streams.cs

210 lines
5.9 KiB
C#

using System.Net;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System;
using System.Threading.Tasks;
namespace Tesses.Http
{
public class PrependStream : Stream
{
int offsetInSpecialInfo=0;
byte[] specialInfo;
Stream actualStream;
public PrependStream(byte[] specialInfo,Stream outerStrm)
{
this.specialInfo=specialInfo;
actualStream=outerStrm;
}
public override bool CanRead => actualStream.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => actualStream.CanWrite;
public override long Length => throw new NotImplementedException();
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override void Flush()
{
actualStream.Flush();
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if(offsetInSpecialInfo < specialInfo.Length)
{
//we are in special info header
int read=Math.Min(count,specialInfo.Length-offsetInSpecialInfo);
Array.Copy(specialInfo,offsetInSpecialInfo,buffer,offset,read);
offsetInSpecialInfo += read;
return read;
}
else
{
return await actualStream.ReadAsync(buffer,offset,count,cancellationToken);
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if(offsetInSpecialInfo < specialInfo.Length)
{
//we are in special info header
int read=Math.Min(count,specialInfo.Length-offsetInSpecialInfo);
Array.Copy(specialInfo,offsetInSpecialInfo,buffer,offset,read);
offsetInSpecialInfo += read;
return read;
}
else
{
return actualStream.Read(buffer,offset,count);
}
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
actualStream.Write(buffer,offset,count);
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
await actualStream.WriteAsync(buffer, offset, count, cancellationToken);
}
}
public class StreamPiper : IDisposable
{
CancellationTokenSource token=new CancellationTokenSource();
Thread _t1,_t2;
Stream _s1,_s2;
bool ownStrm;
public StreamPiper(Stream s1,Stream s2,bool ownStrm=true)
{
_s1=s1;
_s2=s2;
_t1=new Thread(CopyStream1To2);
_t2=new Thread(CopyStream2To1);
this.ownStrm=ownStrm;
}
private void CopyStream1To2()
{
try{
_s1.CopyToAsync(_s2,1024,token.Token).Wait();
}catch(System.AggregateException ex)
{
_=ex;
token.Cancel();
}
}
private void CopyStream2To1()
{
try{
_s2.CopyToAsync(_s1,1024,token.Token).Wait();
}catch(System.AggregateException ex)
{
_=ex;
token.Cancel();
}
}
public void Dispose()
{
token.Cancel();
token.Dispose();
_t1.Abort();
_t2.Abort();
if(ownStrm)
{
_s1.Dispose();
_s2.Dispose();
}
}
public void Pipe(CancellationToken token=default(CancellationToken))
{
token.Register(()=>{
this.token.Cancel();
});
_t1.Start();
_t2.Start();
_t1.Join();
_t2.Join();
}
}
public class RangeStream : Stream
{
Stream _strm;
long _len;
long _read=0;
public RangeStream(Stream strm,long? pos,long? len)
{
long _pos=0;
if(pos.HasValue)
{
_pos=pos.Value;
strm.Seek(pos.Value,SeekOrigin.Begin);
}
if(len.HasValue)
{
_len=len.Value;
}else{
_len=strm.Length;
}
_len=Math.Min(_len,strm.Length - _pos);
_strm=strm;
}
public override bool CanRead => _strm.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => _len;
public override long Position { get => _read; set => throw new NotImplementedException(); }
public override void Flush()
{
_strm.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
int read=(int)Math.Min(_len-_read,count);
if(read == 0) return 0;
read=_strm.Read(buffer,offset,count);
_read+= read;
return read;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}