Completely destroyed game

Looks like a lot more than just netcode is getting rewritten. Removing coroutines because there are better ways of handling asynchronous tasks, removing filestream because that's to be reimplemented later
This commit is contained in:
juanjp600
2016-08-30 19:59:14 -03:00
parent 37ffd64490
commit 9416eb64d7
31 changed files with 72 additions and 1437 deletions
@@ -0,0 +1,321 @@
using Lidgren.Network;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma.Networking
{
class FileStreamReceiver : IDisposable
{
const int MaxFileSize = 1000000;
public delegate void OnFinished(FileStreamReceiver fileStreamReceiver);
private OnFinished onFinished;
private NetClient client;
private ulong length;
private ulong received;
private FileStream writeStream;
private int timeStarted;
private string downloadFolder;
private FileTransferMessageType fileType;
public string FileName
{
get;
private set;
}
public string FilePath
{
get;
private set;
}
public ulong FileSize
{
get { return length; }
}
public ulong Received
{
get { return received; }
}
public FileTransferMessageType FileType
{
get { return fileType; }
}
public FileTransferStatus Status
{
get;
private set;
}
public string ErrorMessage
{
get;
private set;
}
public float BytesPerSecond
{
get;
private set;
}
public float Progress
{
get { return (float)received / (float)length; }
}
public FileStreamReceiver(NetClient client, string filePath, FileTransferMessageType fileType, OnFinished onFinished)
{
this.client = client;
this.downloadFolder = filePath;
this.fileType = fileType;
this.onFinished = onFinished;
Status = FileTransferStatus.NotStarted;
}
public void ReadMessage(NetIncomingMessage inc)
{
try
{
TryReadMessage(inc);
}
catch (Exception e)
{
ErrorMessage = "Error while receiving file ''"+FileName+"'' {"+e.Message+"}";
DeleteFile();
if (onFinished != null) onFinished(this);
}
}
private bool ValidateInitialData(byte type, string fileName, ulong fileSize)
{
if (fileSize > MaxFileSize)
{
ErrorMessage = "File too large (" + MathUtils.GetBytesReadable((long)fileSize) + ")";
return false;
}
if (type != (byte)fileType)
{
ErrorMessage = "Unexpected file type ''" + type + "'' (expected " + fileType + ")";
return false;
}
if (!Regex.Match(fileName, @"^[\w\- ]+[\w\-. ]*$").Success)
{
ErrorMessage = "Illegal characters in file name ''" + fileName + "''";
return false;
}
switch (type)
{
case (byte)FileTransferMessageType.Submarine:
if (Path.GetExtension(fileName) != ".sub")
{
ErrorMessage = "Wrong file extension ''" + Path.GetExtension(fileName) + "''! (Expected .sub)";
return false;
}
break;
}
return true;
}
public void DeleteFile()
{
if (FileName == null) return;
string file = Path.Combine(downloadFolder, FileName);
if (writeStream!=null)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
writeStream = null;
}
Status = FileTransferStatus.Canceled;
if (File.Exists(file))
{
try
{
File.Delete(file);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't delete file ''" + file + "''!", e);
}
}
}
private void TryReadMessage(NetIncomingMessage inc)
{
if (Status == FileTransferStatus.Error ||
Status == FileTransferStatus.Finished ||
Status == FileTransferStatus.Canceled) return;
byte transferMessageType = inc.ReadByte();
//int chunkLen = inc.LengthBytes;
if (length == 0)
{
if (transferMessageType != (byte)FileTransferMessageType.Initiate) return;
if (!string.IsNullOrWhiteSpace(downloadFolder) && !Directory.Exists(downloadFolder))
{
Directory.CreateDirectory(downloadFolder);
}
byte fileTypeByte = inc.ReadByte();
length = inc.ReadUInt64();
FileName = inc.ReadString();
if (!ValidateInitialData(fileTypeByte, FileName, length))
{
Status = FileTransferStatus.Error;
DeleteFile();
if (onFinished != null) onFinished(this);
return;
}
FilePath = Path.Combine(downloadFolder, FileName);
writeStream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None);
timeStarted = Environment.TickCount;
Status = FileTransferStatus.NotStarted;
return;
}
if (received + (ulong)inc.LengthBytes > length*1.1f)
{
ErrorMessage = "Receiving more data than expected (> " + MathUtils.GetBytesReadable((long)(received + (ulong)inc.LengthBytes)) + ")";
Status = FileTransferStatus.Error;
if (onFinished != null) onFinished(this);
return;
}
byte[] all = inc.ReadBytes(inc.LengthBytes - inc.PositionInBytes);
received += (ulong)all.Length;
writeStream.Write(all, 0, all.Length);
int passed = Environment.TickCount - timeStarted;
float psec = passed / 1000.0f;
BytesPerSecond = received / psec;
Status = FileTransferStatus.Receiving;
if (received >= length)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
writeStream = null;
Status = IsReceivedFileValid() ? FileTransferStatus.Finished : FileTransferStatus.Error;
if (onFinished!=null) onFinished(this);
if (Status == FileTransferStatus.Error) DeleteFile();
Dispose();
}
}
private bool IsReceivedFileValid()
{
switch (fileType)
{
case FileTransferMessageType.Submarine:
string file = Path.Combine(downloadFolder, FileName);
Stream stream = null;
try
{
stream = SaveUtil.DecompressFiletoStream(file);
}
catch (Exception e)
{
ErrorMessage = "Loading submarine ''" + file + "'' failed! {"+ e.Message + "}";
return false;
}
if (stream == null)
{
ErrorMessage = "Decompressing submarine file''" + file + "'' failed!";
return false;
}
try
{
stream.Position = 0;
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.IgnoreProcessingInstructions = true;
using (var reader = XmlReader.Create(stream, settings))
{
while (reader.Read())
{
}
}
}
catch
{
stream.Close();
stream.Dispose();
ErrorMessage = "Parsing file ''"+file+"'' failed! The file may not be a valid submarine file.";
return false;
}
stream.Close();
stream.Dispose();
break;
}
return true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (writeStream != null)
{
writeStream.Flush();
writeStream.Close();
writeStream.Dispose();
}
}
}
}
@@ -0,0 +1,187 @@
using Lidgren.Network;
using System;
using System.IO;
namespace Barotrauma.Networking
{
enum FileTransferStatus
{
NotStarted, Sending, Receiving, Finished, Error, Canceled
}
enum FileTransferMessageType
{
Unknown, Initiate, Submarine, Cancel
}
class FileStreamSender : IDisposable
{
public static TimeSpan MaxTransferDuration = new TimeSpan(0, 2, 0);
private FileStream inputStream;
private int sentOffset;
private int chunkLen;
private byte[] tempBuffer;
private NetConnection connection;
float waitTimer;
DateTime startingTime;
private FileTransferMessageType fileType;
public FileTransferStatus Status
{
get;
private set;
}
public string FileName
{
get;
private set;
}
public string FilePath
{
get;
private set;
}
public float Progress
{
get { return inputStream == null ? 0.0f : (float)sentOffset / (float)inputStream.Length; }
}
public int Sent
{
get { return sentOffset; }
}
public long FileSize
{
get { return inputStream == null ? 0 : inputStream.Length; }
}
public static FileStreamSender Create(NetConnection conn, string filePath, FileTransferMessageType fileType)
{
if (!File.Exists(filePath))
{
DebugConsole.ThrowError("Sending a file failed. File ''"+filePath+"'' not found.");
return null;
}
FileStreamSender sender = null;
try
{
sender = new FileStreamSender(conn, filePath, fileType);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open file ''"+filePath+"''",e);
}
return sender;
}
private FileStreamSender(NetConnection conn, string filePath, FileTransferMessageType fileType)
{
connection = conn;
inputStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 100;
tempBuffer = new byte[chunkLen];
sentOffset = 0;
FilePath = filePath;
FileName = Path.GetFileName(filePath);
this.fileType = fileType;
Status = FileTransferStatus.NotStarted;
startingTime = DateTime.Now;
}
public void Update(float deltaTime)
{
if (inputStream == null ||
Status == FileTransferStatus.Canceled ||
Status == FileTransferStatus.Error ||
Status == FileTransferStatus.Finished) return;
if (DateTime.Now > startingTime + MaxTransferDuration)
{
CancelTransfer();
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)FileTransferMessageType.Initiate);
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((byte)fileType);
message.Write(tempBuffer, 0, sendBytes);
connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
sentOffset += sendBytes;
waitTimer = connection.AverageRoundtripTime;
//Program.Output("Sent " + m_sentOffset + "/" + m_inputStream.Length + " bytes to " + m_connection);
if (remaining - sendBytes <= 0)
{
//Dispose();
Status = FileTransferStatus.Finished;
}
}
public void CancelTransfer()
{
Status = FileTransferStatus.Canceled;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
inputStream.Close();
inputStream.Dispose();
inputStream = null;
}
}
}