Cisco Simulators using ASP.NET MVC

Outline

Over the years, I created the NetworkSims ProfSims Cisco Simulators which run under Microsoft .NET. Unfortunately it has been difficult to update, and also difficult for it to run on range of computer systems. I have been working with ASP.NET MVC, and have found it to be amazing in terms of creating content which clearly separates the user interface from the rest of the software.

Here is what my simulator used to look like:

New ASP.NET Version

ASP.NET MVC allows you to separate the Model (the data), the Controller (the middle part), and View (the user interface). It took a while to get the simulator to work on a range of browser, but here’s the result:

Capturing keystrokes

It is quite a challenge to capture keystrokes, especially on different browsers. First we setup the first time screen:

<script type="text/javascript">
    var part1 = "System Bootstrap, Version 11.0(10c)XB2, PLATFORM SPECIFIC RELEASE SOFTWARE (fc1)\nCopyright (c) 1986-1998 by cisco Systems\n2500 processor with 2048 Kbytes of main memory\n\nNotice: NVRAM invalid, possibly due to write erase.\n\nF3: 6700084+88348+451572 at 0x3000060\n\n              Restricted Rights Legend\n\nUse, duplication, or disclosure by the Government is\nsubject to restrictions as set forth in subparagraph\n(c) of the Commercial Computer Software - Restricted\nRights clause at FAR sec. 52.227-19 and subparagraph\n(c) (1) (ii) of the Rights in Technical Data and Computer\nSoftware clause at DFARS sec. 252.227-7013.\n\n           cisco Systems, Inc.\n           170 West Tasman Drive\n           San Jose, California 95134-1706\n\nCisco Internetwork Operating System Software \nIOS (tm) 2500 Software (C2500-D-L), Version 12.0(4), RELEASE SOFTWARE (fc1)\nCopyright (c) 1986-1999 by cisco Systems, Inc.\nCompiled Wed 14-Apr-99 21:21 by ccai\nImage text-base: 0x03037C88, data-base: 0x00001000\n\ncisco 2500 (68030) processor (revision L) with 2048K/2048K bytes of memory.\nProcessor board ID 13583483, with hardware revision 00000000\nBridging software.\nX.25 software, Version 3.0.0.\n2 Ethernet/IEEE 802.3 interface(s)\n2 Serial network interface(s)\n32K bytes of non-volatile configuration memory.\n8192K bytes of processor board System flash (Read ONLY)\n\nPress RETURN to get started! ";
    var prompt = "> ";

    var console = document.getElementById("console");

    var command = "";

    xmlHttp = new XMLHttpRequest();
    xmlHttp.open("POST", "/Cisco/ProcessCommandR", false);
    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttp.send("command=" + command.trim());

    var response = xmlHttp.responseText;

    var n = response.split("||");
    chall.value = n[1];
    response = n[0];


    console.value = console.value + part1;

    if (n.length > 1) details.value = n[2];


    console.value = console.value + prompt;
    selectEnd(console);
    console.focus();

which calls the MVC method of ProcessCommandR() within the CiscoController, and then puts the output to console.

We can then capture the key events with:

    document.getElementById("console").onkeydown =
		function (event) {

		    if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) return true;

		    event = event || window.event;

		    var e = event.keyCode;

		    if (e.which == 90 && e.ctrlKey) {

		        return true;
		    }

		    if (e == 8) {


		        pos = console.value.lastIndexOf('#');
		        pos2 = console.value.lastIndexOf('>');


		        if ((pos == console.value.length - 2) || (pos2 == console.value.length - 2)) return false;

		        else return true;
		    }

		    else if (e == 27) {

		        var command = getCommand();

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/ProcessCommandR", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("command=" + command.trim());

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        console.value = response;


		        selectEnd(console);
		        return false;
		    }




		}

		document.getElementById("console").onkeypress =
		function (event) {


		    event = event || window.event;

		    var e = event.keyCode;
		    // tab key
		    if (e == 9) {
		        var command = getCommand();

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/ProcessCommandREsc", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("command=" + command.trim());
		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        if (response.length > 0) {
		            console.value = console.value.slice(0, console.value.lastIndexOf(" "));
		            console.value = console.value + " " + response;
		        } else console.value = console.value;

		        selectEnd(console);
		        return false;

		    }
		    if (e == 8) {


		        pos = console.value.lastIndexOf('#');
		        pos2 = console.value.lastIndexOf('>');


		        if ((pos == console.value.length - 2) || (pos2 == console.value.length - 2)) return false;
		        else return true;
		    }
		    else if (e == 27) {

		        var command = getCommand();

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/ProcessCommandR", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("command=" + command.trim());

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        console.value = response;


		        selectEnd(console);
		        return false;
		    }
		    // Up Arrow
		    else if (e == 38) {

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/Up", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("");

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        console.value = response;


		        selectEnd(console);
		        return false;
		    }
		    else if (e == 40) {

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/Down", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("");

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];


		        console.value = response;


		        selectEnd(console);
		        return false;
		    }
		    else if (event.charCode == 63) {
		        var command = getCommand() + "?";

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/ProcessCommandR", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("command=" + command.trim());

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        if (response.length > 0) console.value = console.value + "?\n" + response;

		        console.value = console.value;

		        selectEnd(console);
		        return false;
		    }

		    else if (e == 13) {
		        var command = getCommand();

		        xmlHttp = new XMLHttpRequest();
		        xmlHttp.open("POST", "/Cisco/ProcessCommandR", false);
		        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		        xmlHttp.send("command=" + command.trim());

		        var response = xmlHttp.responseText;

		        var n = response.split("||");
		        chall.value = n[1];
		        response = n[0];

		        if (response.length > 0) console.value = console.value + "\n" + response;

		        if (n.length>1) details.value = n[2];

		        console.value = console.value;

		        selectEnd(console);
		        return false;
		    }

		}

    document.getElementById("console").onclick = function (event) { checkCursorPosition(event); }
    document.getElementById("console").onselectstart = function (event) { checkCursorPosition(event); }
    document.getElementById("console").onkeyup = function (event) { checkCursorPosition(event); }

Pop-up challenge

You will notice that I’ve used tabs for different windows. For this, I’ve created a pop-up window for the challenge:

 @(Html.Kendo().Window()
    .Name("ChallengeWindow")
    .Title("Challenge") 
         .Content(@<div>@</div@>
	)
    .Modal(false)
    .Draggable(true)
    .Width(450)
    .Scrollable(true)
            .Animation(true)
            
)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s