// This is called by underlying base class code, each time a new response is received from the wire or a protocol stage is resumed. // This function controls the setting up of a data socket/connection, and of saving off the server responses. protected override PipelineInstruction PipelineCallback(PipelineEntry entry, ResponseDescription response, bool timeout, ref Stream stream) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, $"Command:{entry?.Command} Description:{response?.StatusDescription}"); } // null response is not expected if (response == null) { return(PipelineInstruction.Abort); } FtpStatusCode status = (FtpStatusCode)response.Status; // // Update global "current status" for FtpWebRequest // if (status != FtpStatusCode.ClosingControl) { // A 221 status won't be reflected on the user FTP response // Anything else will (by design?) StatusCode = status; StatusLine = response.StatusDescription; } // If the status code is outside the range defined in RFC (1xx to 5xx) throw if (response.InvalidStatusCode) { throw new WebException(SR.net_InvalidStatusCode, WebExceptionStatus.ProtocolError); } // Update the banner message if any, this is a little hack because the "entry" param is null if (_index == -1) { if (status == FtpStatusCode.SendUserCommand) { _bannerMessage = new StringBuilder(); _bannerMessage.Append(StatusLine); return(PipelineInstruction.Advance); } else if (status == FtpStatusCode.ServiceTemporarilyNotAvailable) { return(PipelineInstruction.Reread); } else { throw GenerateException(status, response.StatusDescription, null); } } // // Check for the result of our attempt to use UTF8 // if (entry.Command == "OPTS utf8 on\r\n") { if (response.PositiveCompletion) { Encoding = Encoding.UTF8; } else { Encoding = Encoding.Default; } return(PipelineInstruction.Advance); } // If we are already logged in and the server returns 530 then // the server does not support re-issuing a USER command, // tear down the connection and start all over again if (entry.Command.IndexOf("USER") != -1) { // The server may not require a password for this user, so bypass the password command if (status == FtpStatusCode.LoggedInProceed) { _loginState = FtpLoginState.LoggedIn; _index++; } } // // Throw on an error with possible recovery option // if (response.TransientFailure || response.PermanentFailure) { if (status == FtpStatusCode.ServiceNotAvailable) { MarkAsRecoverableFailure(); } throw GenerateException(status, response.StatusDescription, null); } if (_loginState != FtpLoginState.LoggedIn && entry.Command.IndexOf("PASS") != -1) { // Note the fact that we logged in if (status == FtpStatusCode.NeedLoginAccount || status == FtpStatusCode.LoggedInProceed) { _loginState = FtpLoginState.LoggedIn; } else { throw GenerateException(status, response.StatusDescription, null); } } // // Parse special cases // if (entry.HasFlag(PipelineEntryFlags.CreateDataConnection) && (response.PositiveCompletion || response.PositiveIntermediate)) { bool isSocketReady; PipelineInstruction result = QueueOrCreateDataConection(entry, response, timeout, ref stream, out isSocketReady); if (!isSocketReady) { return(result); } // otherwise we have a stream to create } // // This is part of the above case and it's all about giving data stream back // if (status == FtpStatusCode.OpeningData || status == FtpStatusCode.DataAlreadyOpen) { if (_dataSocket == null) { return(PipelineInstruction.Abort); } if (!entry.HasFlag(PipelineEntryFlags.GiveDataStream)) { _abortReason = SR.Format(SR.net_ftp_invalid_status_response, status, entry.Command); return(PipelineInstruction.Abort); } // Parse out the Content length, if we can TryUpdateContentLength(response.StatusDescription); // Parse out the file name, when it is returned and use it for our ResponseUri FtpWebRequest request = (FtpWebRequest)_request; if (request.MethodInfo.ShouldParseForResponseUri) { TryUpdateResponseUri(response.StatusDescription, request); } return(QueueOrCreateFtpDataStream(ref stream)); } // // Parse responses by status code exclusivelly // // Update welcome message if (status == FtpStatusCode.LoggedInProceed) { _welcomeMessage.Append(StatusLine); } // OR set the user response ExitMessage else if (status == FtpStatusCode.ClosingControl) { _exitMessage.Append(response.StatusDescription); // And close the control stream socket on "QUIT" CloseSocket(); } // OR set us up for SSL/TLS, after this we'll be writing securely else if (status == FtpStatusCode.ServerWantsSecureSession) { // If NetworkStream is a TlsStream, then this must be in the async callback // from completing the SSL handshake. // So just let the pipeline continue. if (!(NetworkStream is TlsStream)) { FtpWebRequest request = (FtpWebRequest)_request; TlsStream tlsStream = new TlsStream(NetworkStream, Socket, request.RequestUri.Host, request.ClientCertificates); if (_isAsync) { tlsStream.BeginAuthenticateAsClient(ar => { try { tlsStream.EndAuthenticateAsClient(ar); NetworkStream = tlsStream; this.ContinueCommandPipeline(); } catch (Exception e) { this.CloseSocket(); this.InvokeRequestCallback(e); } }, null); return(PipelineInstruction.Pause); } else { tlsStream.AuthenticateAsClient(); NetworkStream = tlsStream; } } } // OR parse out the file size or file time, usually a result of sending SIZE/MDTM commands else if (status == FtpStatusCode.FileStatus) { FtpWebRequest request = (FtpWebRequest)_request; if (entry.Command.StartsWith("SIZE ")) { _contentLength = GetContentLengthFrom213Response(response.StatusDescription); } else if (entry.Command.StartsWith("MDTM ")) { _lastModified = GetLastModifiedFrom213Response(response.StatusDescription); } } // OR parse out our login directory else if (status == FtpStatusCode.PathnameCreated) { if (entry.Command == "PWD\r\n" && !entry.HasFlag(PipelineEntryFlags.UserCommand)) { _loginDirectory = GetLoginDirectory(response.StatusDescription); } } // Asserting we have some positive response else { // We only use CWD to reset ourselves back to the login directory. if (entry.Command.IndexOf("CWD") != -1) { _establishedServerDirectory = _requestedServerDirectory; } } // Intermediate responses require rereading if (response.PositiveIntermediate || (!UsingSecureStream && entry.Command == "AUTH TLS\r\n")) { return(PipelineInstruction.Reread); } return(PipelineInstruction.Advance); }
//Updates Pipeline Map public void setPipelineTexts(Label pNum, Label pFetch, Label pDecode, Label pExecute, Label pStore, PipelineInstruction instr) { String nullLine = "--------------"; pNum.Text = instr.instructionText + "(" + instr.instructionIndex + ")"; switch (instr.stage) { case 4: pFetch.Text = "F"; pFetch.ForeColor = Color.DarkGreen; pDecode.Text = "D"; pDecode.ForeColor = Color.DarkGreen; pExecute.Text = "X"; pExecute.ForeColor = Color.DarkGreen; pStore.Text = "M"; pStore.ForeColor = Color.DarkGreen; pNum.ForeColor = Color.DarkGreen; break; case 3: pFetch.Text = "F"; pDecode.Text = "D"; pExecute.Text = "X"; pStore.Text = nullLine; pFetch.ForeColor = label47.ForeColor; pDecode.ForeColor = label47.ForeColor; pExecute.ForeColor = label47.ForeColor; pStore.ForeColor = label47.ForeColor; pNum.ForeColor = label47.ForeColor; break; case 2: pFetch.Text = "F"; pDecode.Text = "D"; pExecute.Text = nullLine; pStore.Text = nullLine; pFetch.ForeColor = label47.ForeColor; pDecode.ForeColor = label47.ForeColor; pExecute.ForeColor = label47.ForeColor; pStore.ForeColor = label47.ForeColor; pNum.ForeColor = label47.ForeColor; break; case 1: pFetch.Text = "F"; pDecode.Text = nullLine; pExecute.Text = nullLine; pStore.Text = nullLine; break; pFetch.ForeColor = label47.ForeColor; pDecode.ForeColor = label47.ForeColor; pExecute.ForeColor = label47.ForeColor; pStore.ForeColor = label47.ForeColor; pNum.ForeColor = label47.ForeColor; case 0: pFetch.Text = nullLine; pDecode.Text = nullLine; pExecute.Text = nullLine; pStore.Text = nullLine; pFetch.ForeColor = label47.ForeColor; pDecode.ForeColor = label47.ForeColor; pExecute.ForeColor = label47.ForeColor; pStore.ForeColor = label47.ForeColor; pNum.ForeColor = label47.ForeColor; break; } }
void myCPU_OnBranch(object sender, BranchEventArgs args) { MethodInvoker method = delegate { if (args.taken) { Console.WriteLine("Branch taken in GUI " + this.myCPU.ACC); /*What this code does is goes through the instructions in the pipeline, * and removes the ones that were being worked on prior to the branch being * taken * NOTE: probably will have to add an if statement to check for branch prediction*/ int count = 0; Console.WriteLine("Queue contents before:"); foreach (var instr in instructionsInPipeline) { Console.WriteLine(count + ") " + instr.instructionText + ", stage is " + instr.stage); count++; } PipelineInstruction[] temp = new PipelineInstruction[instructionsInPipeline.Count()]; instructionsInPipeline.CopyTo(temp, 0); instructionsInPipeline.Clear(); int takenBranchIndex = args.CurrentInstrIndex; Console.WriteLine("Taken branch index is " + takenBranchIndex); for (int i = 0; i < temp.Count(); i++) { //if the index is larger than the branch that was taken, it needs to be flushed out if ((temp[i]).instructionIndex < takenBranchIndex) { instructionsInPipeline.Enqueue(temp[i]); } else if (temp[i].instructionIndex == takenBranchIndex) { temp[i].stage++;//this is to correct for the special branch case instructionsInPipeline.Enqueue(temp[i]); } } count = 0; Console.WriteLine("Queue contents after:"); foreach (var instr in instructionsInPipeline) { Console.WriteLine(count + ") " + instr.instructionText + ", stage is " + instr.stage); count++; } //this.setPipelineValuesToView(); } foreach (var branch in bhtBranches) { String currBranchName = Memory.getAssemblyInstructions().ElementAt(args.CurrentInstrIndex); if (currBranchName.CompareTo(branch.instrLabel) == 0) { if (args.taken) { branch.takenCount++; } else { branch.notTakenCount++; } } } //updateGUI(); }; if (this.InvokeRequired) { this.Invoke(method); } else { method.Invoke(); } }
void myCPU_OnBranch(object sender, BranchEventArgs args) { MethodInvoker method = delegate { if (args.taken) { Console.WriteLine("Branch taken in GUI " + this.myCPU.ACC); /*What this code does is goes through the instructions in the pipeline, and removes the ones that were being worked on prior to the branch being taken NOTE: probably will have to add an if statement to check for branch prediction*/ int count = 0; Console.WriteLine("Queue contents before:"); foreach (var instr in instructionsInPipeline) { Console.WriteLine(count + ") " + instr.instructionText + ", stage is " + instr.stage); count++; } PipelineInstruction[] temp = new PipelineInstruction[instructionsInPipeline.Count()]; instructionsInPipeline.CopyTo(temp, 0); instructionsInPipeline.Clear(); int takenBranchIndex = args.CurrentInstrIndex; Console.WriteLine("Taken branch index is " + takenBranchIndex); for (int i = 0; i < temp.Count(); i++) { //if the index is larger than the branch that was taken, it needs to be flushed out if ((temp[i]).instructionIndex < takenBranchIndex) { instructionsInPipeline.Enqueue(temp[i]); } else if (temp[i].instructionIndex == takenBranchIndex) { temp[i].stage++;//this is to correct for the special branch case instructionsInPipeline.Enqueue(temp[i]); } } count = 0; Console.WriteLine("Queue contents after:"); foreach (var instr in instructionsInPipeline) { Console.WriteLine(count + ") " + instr.instructionText + ", stage is " + instr.stage); count++; } //this.setPipelineValuesToView(); } foreach(var branch in bhtBranches){ String currBranchName = Memory.getAssemblyInstructions().ElementAt(args.CurrentInstrIndex); if (currBranchName.CompareTo(branch.instrLabel) == 0) { if (args.taken) { branch.takenCount++; } else { branch.notTakenCount++; } } } //updateGUI(); }; if (this.InvokeRequired) { this.Invoke(method); } else { method.Invoke(); } }