Files
LuaCsForBarotraumaEP/Subsurface/Source/Networking/FileStreamSender.cs

134 lines
3.8 KiB
C#

using Lidgren.Network;
using System;
using System.IO;
namespace Barotrauma.Networking
{
enum FileTransferStatus
{
NotStarted, Sending, Receiving, Finished, Error, Canceled
}
enum FileTransferType
{
Unknown, Submarine
}
class FileStreamSender : IDisposable
{
private FileStream inputStream;
private int sentOffset;
private int chunkLen;
private byte[] tempBuffer;
private NetConnection connection;
float waitTimer;
private FileTransferType fileType;
public FileTransferStatus Status
{
get;
private set;
}
public string FileName
{
get;
private set;
}
public static FileStreamSender Create(NetConnection conn, string fileName, FileTransferType fileType)
{
if (!File.Exists(fileName))
{
DebugConsole.ThrowError("Sending a file failed. File ''"+fileName+"'' not found.");
return null;
}
return new FileStreamSender(conn, fileName, fileType);
}
private FileStreamSender(NetConnection conn, string fileName, FileTransferType fileType)
{
connection = conn;
inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 100;
tempBuffer = new byte[chunkLen];
sentOffset = 0;
FileName = fileName;
this.fileType = fileType;
Status = FileTransferStatus.NotStarted;
}
public void Update(float deltaTime)
{
if (inputStream == null) return;
waitTimer -= deltaTime;
if (waitTimer > 0.0f) return;
if (!connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, 1)) return;
// send another part of the file!
long remaining = inputStream.Length - sentOffset;
int sendBytes = (remaining > chunkLen ? chunkLen : (int)remaining);
// just assume we can read the whole thing in one Read()
inputStream.Read(tempBuffer, 0, sendBytes);
NetOutgoingMessage message;
if (sentOffset == 0)
{
// first message; send length, chunk length and file name
message = connection.Peer.CreateMessage(sendBytes + 8 + 1);
message.Write((byte)PacketTypes.FileStream);
message.Write((byte)fileType);
message.Write((ulong)inputStream.Length);
message.Write(Path.GetFileName(inputStream.Name));
connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
Status = FileTransferStatus.Sending;
}
message = connection.Peer.CreateMessage(sendBytes + 8 + 1);
message.Write((byte)PacketTypes.FileStream);
message.Write(tempBuffer, 0, sendBytes);
connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
sentOffset += sendBytes;
waitTimer = connection.AverageRoundtripTime + 0.05f;
//Program.Output("Sent " + m_sentOffset + "/" + m_inputStream.Length + " bytes to " + m_connection);
if (remaining - sendBytes <= 0)
{
//Dispose();
Status = FileTransferStatus.Finished;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
inputStream.Close();
inputStream.Dispose();
inputStream = null;
}
}
}