public void SendFile() { SharedObject shared = new SharedObject(this.socket, this.connectionNumber, this.inFile, this.measure); Task timeoutChecker = new Task(TimeoutCheckerThread, shared); Task receive = new Task(ReceiveThread, shared); Task dataProccess = new Task(ProccessDataThread, shared); Task[] tasks = new Task[] { timeoutChecker, receive, dataProccess }; try { measure.Start(); foreach (Task t in tasks) { t.Start(); } Task <Task> waiter = Task.WhenAny(timeoutChecker, receive, dataProccess); waiter.Wait(); Task whoEndIt = waiter.Result; Logger.WriteLine($"Thread {whoEndIt.Id} ended his work"); if (whoEndIt.Exception != null) { throw whoEndIt.Exception.InnerException; } } catch (MaximumAttempException) { Logger.WriteLine("Maximum attemp of send, sending RST packet", ConsoleColor.Yellow); CommunicationFacade.Send(this.socket, new CommunicationPacket(this.connectionNumber, 0, 0, (byte)Flag.RST, new byte[] { })); throw; } catch (InvalidPacketException e) { Logger.WriteLine($"Invalid packet ({e.Message}), sending RST packet", ConsoleColor.Yellow); CommunicationFacade.Send(this.socket, new CommunicationPacket(this.connectionNumber, 0, 0, (byte)Flag.RST, new byte[] { })); throw; } catch (CommunicationException) { Logger.WriteLine($"Error occurs during communication", ConsoleColor.Yellow); throw; } finally { shared.Ended = true; foreach (Task t in tasks) { if (t.Status == TaskStatus.Running) { t.Wait(); } t.Dispose(); } this.measure.ShowSpeed(shared.Confirmed); } }
static private void ReceiveThread(object Param) { Logger.WriteLine($"Receive thread started with id {Task.CurrentId}"); SharedObject data = (SharedObject)Param; while (!data.Ended) { data.Socket.ReceiveTimeout = (int)PacketsProps.WAIT_TIME; try { CommunicationPacket p = CommunicationFacade.Receive(data.Socket); UInt64 currentPoint; lock (data.CountersLocker) currentPoint = data.Confirmed; UInt64 confirmationNumber = CommunicationFacade.ComputeRealNumber(p.ConfirmationNumber, currentPoint, UInt16.MaxValue, (uint)Sizes.WINDOW_SIZE); UploadRecvPacket recv = new UploadRecvPacket(p.ConnectionNumber, p.Flags, p.Data, confirmationNumber); lock (data.ArriveQueue) data.ArriveQueue.Enqueue(recv); } catch (SocketException e) when(e.SocketErrorCode == SocketError.TimedOut) { } } }
public static UInt32 InitConnection(Socket socket, Command action) { int i = 0; socket.ReceiveTimeout = 100; while (i < 20) { CommunicationFacade.Send(socket, new CommunicationPacket(0, 0, 0, (byte)Flag.SYN, new byte[] { (byte)action })); try { while (true) { CommunicationPacket recived = CommunicationFacade.Receive(socket); if (recived.Flags == (byte)Flag.SYN && recived.Data[0] == (byte)action && recived.SerialNumber == 0 && recived.ConfirmationNumber == 0) { Logger.WriteLine($"Connection established - communication {recived.ConnectionNumber:X}"); socket.ReceiveTimeout = 0; return(recived.ConnectionNumber); } else { Console.WriteLine("Data obtained before connection packet received, ignoring"); } } } catch (SocketException e) when(e.SocketErrorCode == SocketError.TimedOut) { Logger.WriteLine($"Connection timeouted, attemp number {i + 1}"); i++; } } throw new Exceptions.MaximumAttempException(); }
private DownloadPacket receive(CommunicationPacket p) { UInt64 realSerial = CommunicationFacade.ComputeRealNumber(p.SerialNumber, this.required, UInt16.MaxValue, (uint)Sizes.WINDOW_SIZE); DownloadPacket toReturn = new DownloadPacket(p.Data, p.ConnectionNumber, p.Flags, realSerial);; Logger.WriteLine($"Downloader recive packet with serial={toReturn.SerialNumber}"); return(toReturn); }
static private void TimeoutCheckerThread(object Param) { Logger.WriteLine($"TimeoutChecker thread started with id {Task.CurrentId}"); SharedObject data = (SharedObject)Param; UploadSendPacket p; while (!data.Ended) { p = null; //check the oldest packet lock (data.SendedPackets) { if (data.SendedPackets.Count > 0) { TimeSpan diff = DateTime.Now - data.SendedPackets.First.Value.LastSend; if (Math.Abs(diff.TotalMilliseconds) >= (ushort)PacketsProps.WAIT_TIME) { p = data.SendedPackets.First.Value; data.SendedPackets.RemoveFirst(); } } } //if expires oldes packet if (p != null) { //check if is required to send it UInt64 currentConfirmed; lock (data.CountersLocker) { currentConfirmed = data.Confirmed; } bool sendIt = p.SerialNumber >= currentConfirmed; //send it if needed if (sendIt) { //socket have highter serial number that is confirmed number p.Sended++; p.LastSend = DateTime.Now; if (p.Sended == (ushort)PacketsProps.MAX_ATTEMPS) { throw new MaximumAttempException(); } Logger.WriteLine($"Packet {p.SerialNumber} timeouted, sends again"); CommunicationFacade.Send(data.Socket, p.CreatePacketToSend()); lock (data.SendedPackets) data.SendedPackets.AddLast(p); } } else //timeout not expired for the oldest packet { Thread.Sleep(0); } } }
public void AcceptFile() { try { byte[] empty = new byte[] { }; IPriorityQueue <DownloadPacket, UInt64> queue = new SimplePriorityQueue <DownloadPacket, UInt64>(); //TODO add priority queue while (true) { DownloadPacket pack = this.receive(CommunicationFacade.Receive(this.socket)); pack = this.validatePacket(pack); if (pack.Flags == (byte)Flag.FIN) { Logger.WriteLine("All data arrive", ConsoleColor.Cyan); CommunicationFacade.Send(this.socket, new CommunicationPacket(this.connectionNumber, 0, Convert.ToUInt16(this.required & UInt16.MaxValue), (byte)Flag.FIN, empty)); return; } queue.Enqueue(pack, pack.SerialNumber); //Attach into priority queue while (queue.Count > 0 && queue.First.SerialNumber <= this.required) { DownloadPacket toProccess = queue.Dequeue(); if (toProccess.SerialNumber < this.required) { continue; } Logger.WriteLine($"Accepted packet {toProccess.SerialNumber}"); this.outFile.Write(toProccess.Data); this.required += (uint)toProccess.Data.Length; if (toProccess.Data.Length != 255) { Logger.WriteLine("Last packet arrive, waiting to FIN packet", ConsoleColor.Cyan); this.waitingToFin = true; } } Logger.WriteLine($"Waiting for packet {this.required}"); CommunicationFacade.Send(this.socket, new CommunicationPacket(this.connectionNumber, 0, Convert.ToUInt16(this.required & UInt16.MaxValue), 0, empty)); } } catch (CommunicationException) { Logger.WriteLine("Occurs error during communication", ConsoleColor.Yellow); throw new TerminateException(); } catch (InvalidPacketException e) { Logger.WriteLine($"Obtained invalid packet: {e.Message}", ConsoleColor.Yellow); CommunicationFacade.Send(this.socket, new CommunicationPacket(this.connectionNumber, 0, Convert.ToUInt16(this.required & UInt16.MaxValue), (byte)Flag.RST, new byte[] { })); throw new TerminateException(); } }
public void InitConnection() { this.connectionNumber = CommunicationFacade.InitConnection(this.socket, Command.UPLOAD); }