private NumCheckResult CheckNumbers(TCP tcp) { ACKMyNumber = true; if (tcp.AcknowledgementNumber != MySequenceNumber) { ACKMyNumber = false; Console.Error.WriteLine("Unexpected Acknowledgement Number, Got " + tcp.AcknowledgementNumber + " Expected " + MySequenceNumber); if (tcp.AcknowledgementNumber != OldMyNumber) { throw new Exception("Unexpected Acknowledgement Number did not Match Old Number of " + OldMyNumber); } } if (tcp.SequenceNumber != ExpectedSequenceNumber) { if (tcp.GetPayload().Length == 0) { Console.Error.WriteLine("Unexpected Sequence Number From Act Packet, Got " + tcp.SequenceNumber + " Expected " + ExpectedSequenceNumber); } else { if (ReceivedSequenceNumbers.Contains(tcp.SequenceNumber)) { Console.Error.WriteLine("Got an Old Seq Number on an Data packet"); return(NumCheckResult.GotOldData); } else { throw new Exception("Unexpected Sequence Number From Data Packet, Got " + tcp.SequenceNumber + " Expected " + ExpectedSequenceNumber); } } } return(NumCheckResult.OK); }
private NumCheckResult CheckNumbers(TCP tcp) { GetAllMyNumbers(out UInt32 seqNum, out List <UInt32> oldSeqNums); Log_Verb("CHECK_NUMBERS"); Log_Verb("[SRV]CurrSeqNumber = " + seqNum + " [PS2]Ack Number = " + tcp.AcknowledgementNumber); Log_Verb("[SRV]CurrAckNumber = " + expectedSeqNumber + " [PS2]Seq Number = " + tcp.SequenceNumber); Log_Verb("[PS2]Data Length = " + tcp.GetPayload().Length); if (tcp.AcknowledgementNumber != seqNum) { Log_Verb("[PS2]Sent Outdated Acknowledgement Number, Got " + tcp.AcknowledgementNumber + " Expected " + seqNum); if (!oldSeqNums.Contains(tcp.AcknowledgementNumber)) { Log_Error("Unexpected Acknowledgement Number did not Match Old Numbers, Got " + tcp.AcknowledgementNumber + " Expected " + seqNum); throw new Exception("Unexpected Acknowledgement Number did not Match Old Numbers, Got " + tcp.AcknowledgementNumber + " Expected " + seqNum); } } else { Log_Verb("[PS2]CurrSeqNumber Acknowleged By PS2"); myNumberACKed.Set(); } if (tcp.SequenceNumber != expectedSeqNumber) { if (tcp.GetPayload().Length == 0) { Log_Verb("[PS2]Sent Unexpected Sequence Number From ACK Packet, Got " + tcp.SequenceNumber + " Expected " + expectedSeqNumber); } else { if (receivedPS2SeqNumbers.Contains(tcp.SequenceNumber)) { Log_Error("[PS2]Sent an Old Seq Number on an Data packet, Got " + tcp.SequenceNumber + " Expected " + expectedSeqNumber); return(NumCheckResult.GotOldData); } else { Log_Error("[PS2]Sent Unexpected Sequence Number From Data Packet, Got " + tcp.SequenceNumber + " Expected " + expectedSeqNumber); throw new Exception("Unexpected Sequence Number From Data Packet, Got " + tcp.SequenceNumber + " Expected " + expectedSeqNumber); } } } return(NumCheckResult.OK); }
private void ErrorOnNonEmptyPacket(TCP tcp) { NumCheckResult ResultFIN = CheckNumbers(tcp); if (ResultFIN == NumCheckResult.GotOldData) { return; } if (ResultFIN == NumCheckResult.Bad) { Log_Error("Bad TCP Numbers Received"); throw new Exception("Bad TCP Numbers Received"); } if (tcp.GetPayload().Length > 0) { uint delta = GetDelta(expectedSeqNumber, tcp.SequenceNumber); if (delta == 0) { return; } Log_Error("Invalid Packet, Packet Has Data"); throw new Exception("Invalid Packet"); } }
//PS2 Sending Data private bool SendData(TCP tcp) { if (tcp.SYN) { Log_Error("Attempt to Connect to an open Port"); throw new Exception("Attempt to Connect to an open Port"); } if (tcp.URG) { throw new Exception("Urgent Data Not Supported"); } for (int i = 0; i < tcp.Options.Count; i++) { switch (tcp.Options[i].Code) { case 0: //End case 1: //Nop continue; case 8: lastRecivedTimeStamp = ((TCPopTS)(tcp.Options[i])).SenderTimeStamp; break; default: Log_Error("Got Unknown Option " + tcp.Options[i].Code); throw new Exception("Got Unknown Option " + tcp.Options[i].Code); //break; } } windowSize = tcp.WindowSize << windowScale; NumCheckResult Result = CheckNumbers(tcp); uint delta = GetDelta(expectedSeqNumber, tcp.SequenceNumber); if (Result == NumCheckResult.GotOldData) { Log_Verb("[PS2] New Data Offset: " + delta + " bytes"); Log_Verb("[PS2] New Data Length: " + ((uint)tcp.GetPayload().Length - delta) + " bytes"); } if (Result == NumCheckResult.Bad) { Log_Error("Bad TCP Numbers Received"); throw new Exception("Bad TCP Numbers Received"); } if (tcp.GetPayload().Length != 0) { if (tcp.GetPayload().Length - delta > 0) { Log_Verb("[PS2] Sending: " + tcp.GetPayload().Length + " bytes"); receivedPS2SeqNumbers.RemoveAt(0); receivedPS2SeqNumbers.Add(expectedSeqNumber); //Send the Data try { int sent = 0; byte[] payload = tcp.GetPayload(); while (sent != payload.Length) { SocketError err; try { sent = client.Send(payload, sent, payload.Length - sent, SocketFlags.None, out err); } catch (ObjectDisposedException) { err = SocketError.Shutdown; } if (err != SocketError.WouldBlock & err != SocketError.Success) { throw new SocketException((int)err); } if (err == SocketError.WouldBlock) { System.Threading.Thread.Sleep(0); } } } catch (SocketException e) { Log_Error("TCP Send Error: " + e.Message); Log_Error("Error Code: " + e.ErrorCode); //Connection Lost //Send Shutdown by RST (Untested) client.Close(); CloseByRemoteRST(); return(true); } unchecked { expectedSeqNumber += ((uint)tcp.GetPayload().Length - delta); } //Done send } //ACK data Log_Verb("[SRV] ACK Data: " + expectedSeqNumber); TCP ret = CreateBasePacket(); ret.ACK = true; PushRecvBuff(ret); } return(true); }
public override bool send(IPPayload payload) { TCP tcp = (TCP)payload; if (DestPort != 0) { if (!(tcp.DestinationPort == DestPort && tcp.SourcePort == SrcPort)) { Console.Error.WriteLine("TCP packet invalid for current session (Duplicate key?)"); return(false); } } if (tcp.RST == true) //Test this { if (client.Connected) { lock (sentry) { client.Close(); } state = TCPState.Closed; open = false; return(true); } } switch (state) { case TCPState.None: #region "SYN" DestPort = tcp.DestinationPort; SrcPort = tcp.SourcePort; if (tcp.SYN == false) { PerformRST(); Console.Error.WriteLine("Connection Not in Connected State"); return(true); } ExpectedSequenceNumber = tcp.SequenceNumber + 1; //Fill out last received numbers ReceivedSequenceNumbers.Add(tcp.SequenceNumber); ReceivedSequenceNumbers.Add(tcp.SequenceNumber); ReceivedSequenceNumbers.Add(tcp.SequenceNumber); ReceivedSequenceNumbers.Add(tcp.SequenceNumber); ReceivedSequenceNumbers.Add(tcp.SequenceNumber); for (int i = 0; i < tcp.Options.Count; i++) { switch (tcp.Options[i].Code) { case 0: //End case 1: //Nop continue; case 2: //MSS MaxSegmentSize = ((TCPopMSS)(tcp.Options[i])).MaxSegmentSize; break; case 3: //WinScale //Console.Error.WriteLine("Got WinScale"); // = ((TCPopWS)(tcp.Options[i])).WindowScale; break; case 8: //TimeStamp LastRecivedTimeStamp = ((TCPopTS)(tcp.Options[i])).SenderTimeStamp; SendTimeStamps = true; TimeStamp.Start(); break; default: Console.Error.WriteLine("Got Unknown Option " + tcp.Options[i].Code); throw new Exception(); //break; } } client = new TcpClient(); IPAddress address = new IPAddress(DestIP); client.BeginConnect(address, DestPort, new AsyncCallback(AsyncConnectComplete), tcp); state = TCPState.SendingSYN_ACK; open = true; return(true); #endregion case TCPState.SendingSYN_ACK: return(true); //Ignore reconnect attempts while we are still attempting connection case TCPState.SentSYN_ACK: #region "Syn-Ack" lock (sentry) { if (tcp.SYN == true) { throw new Exception("Attempt to Connect to an operning Port"); } NumCheckResult Result = CheckNumbers(tcp); if (Result == NumCheckResult.Bad) { throw new Exception("Bad TCP Number Received"); } for (int i = 0; i < tcp.Options.Count; i++) { switch (tcp.Options[i].Code) { case 0: //End case 1: //Nop continue; case 8: //Timestamp LastRecivedTimeStamp = ((TCPopTS)(tcp.Options[i])).SenderTimeStamp; break; default: Console.Error.WriteLine("Got Unknown Option " + tcp.Options[i].Code); throw new Exception(); //break; } } //Next packet will be data state = TCPState.Connected; } return(true); #endregion case TCPState.Connected: #region "Connected" if (tcp.SYN == true) { throw new Exception("Attempt to Connect to an open Port"); } lock (sentry) { for (int i = 0; i < tcp.Options.Count; i++) { switch (tcp.Options[i].Code) { case 0: //End case 1: //Nop continue; case 8: //Console.Error.WriteLine("Got TimeStamp"); LastRecivedTimeStamp = ((TCPopTS)(tcp.Options[i])).SenderTimeStamp; break; default: Console.Error.WriteLine("Got Unknown Option " + tcp.Options[i].Code); throw new Exception(); //break; } } NumCheckResult Result = CheckNumbers(tcp); if (Result == NumCheckResult.GotOldData) { throw new NotImplementedException(); //return true; } if (Result == NumCheckResult.Bad) { throw new Exception("Bad TCP Number Received"); } if (tcp.FIN == true) //Connection Close Part 1, receive FIN from PS2 { PerformCloseByPS2(); return(true); } if (tcp.GetPayload().Length != 0) { ReceivedSequenceNumbers.RemoveAt(0); ReceivedSequenceNumbers.Add(ExpectedSequenceNumber); //Send the Data try { client.GetStream().Write(tcp.GetPayload(), 0, tcp.GetPayload().Length); } catch (Exception e) { System.Windows.Forms.MessageBox.Show("Got IO Error :" + e.ToString()); //Connection Lost //Send Shutdown (Untested) PerformRST(); open = false; return(true); } unchecked { ExpectedSequenceNumber += ((uint)tcp.GetPayload().Length); } //Done send //ACK data TCP ret = CreateBasePacket(); ret.ACK = true; recvbuff.Add(ret); } } return(true); #endregion case TCPState.ConnectionClosedByPS2AndRemote: #region "Closing" //Close Part 4, Recive ACK from PS2 Console.Error.WriteLine("Compleated Close By PS2"); NumCheckResult ResultFIN = CheckNumbers(tcp); if (ResultFIN == NumCheckResult.GotOldData) { return(false); } if (ResultFIN == NumCheckResult.Bad) { throw new Exception("Bad TCP Number Received"); } state = TCPState.Closed; open = false; return(true); #endregion case TCPState.ConnectionClosedByRemote: #region "Closing" //Expect fin+ack if (tcp.FIN == true) { Console.Error.WriteLine("Compleated Close By Remote"); ReceivedSequenceNumbers.RemoveAt(0); ReceivedSequenceNumbers.Add(ExpectedSequenceNumber); unchecked { ExpectedSequenceNumber += 1; } TCP ret = CreateBasePacket(); ret.ACK = true; recvbuff.Add(ret); state = TCPState.ConnectionClosedByPS2AndRemote; open = false; return(true); } //throw new Exception("Invalid Packet"); return(false); //break; #endregion default: throw new Exception("Invalid State"); } }