Ryan Merl

I'm a college guy who has an unhealthy obsession with code.

 

My first wrangle with NoSQL. An explanation of what I made and my thoughts on NoSQL versus the traditional RDBMS

I had a random idea the other day. I wanted to write a server that would serve, generate and store image manipulations on the fly. So that’s what I made. You can check out the GitHub repository here. The server itself takes HTTP requests much like a standard web server. It takes an image id and any sizing or cropping parameters you would like and returns the image. When you pass sizing or cropping parameters it checks to see if the image with those parameters already exists and returns that if it does. This avoids regenerating images all the time. It stores information about the images in the Mongo database.

This was sort of a new field to me as it was my first venture into the world of NoSQL. I really like the way everything works. I think this project worked well with the “Unstructured Data” that NoSQL is really good for. Different images could have a couple of sets of different attributes (and of course this would expand if I added more types of manipulations). It would certainly have been doable in an relational database, but I think this works better.

MongoDB uses a notation called BSON for its definitions and queries. BSON is much like the  - probably more – familiar JSON, except with the ability to have binary objects (hence the B in BSON). Defining the data in BSON is rather trivial and, in my opinion, more natural than SQL (and certainly less verbose). I also like the fact that you can have nested data. In some instances this can be used as opposed to the using a foreign key in an RDBMS.

I did a good bit of reading before I dove into NoSQL to see if it was really any better. I had heard lots on how “NoSQL is the new wave and it’s so much better!”. Well the answer I found: It depends. There’s lots of arguments that say NoSQL, because of it’s unstructured nature, is much better at scaling. However, there’s plenty that say RDBMSs scale just fine too. I think it’s not that one can scale up better than the other, I think it’s just easier to scale up a NoSQL database in terms of code implementation. What I really got out of my reading was that the reason to use NoSQL is not necessarily for scaling, but really, it comes down to whether you need the ability to have unstructured data. As I stated, what I did with my server was not necessarily completely structured, however it could still have been implemented in typical relational style. I’ve heard that there are scenarios where you would need to have unstructured data storing abilities. I assume it’s true, though I can’t really think of an example so who knows.

All in all, I like the interactions with MongoDB a lot better than I do using SQL like I would with MySQL (Which is what I have been using for data storage since I started programming 8 years ago). However, I could get very similar interactions by using an ORM (Object Relational Mapper). Those pretty much keeps the SQL away from my eyes and lets me use an Object-Oriented interface with the server. In general, for my needs, I could use either one. I don’t really have to worry about the scale issue (for now anyways) but like i said, it really comes down to the need for structured vs. unstructured data.

I should note: my GitHub project code is not ‘ready for distribution’. It was really just a test project. The code is there for anyone to play with and modify, or look at as an example. It wont run straight away if you download it and fire it up. You will need to modify it for your environment.

 

Recently I needed to write some code to query a list of WhoIs servers to find the registration date of each url in another list. I needed to write it in VB.NET so that it would link in with our VB ASP.NET code.

My first approach was to grab a list of whois servers from a flat file and just do a for loop to go through them all until I found the information I was looking for. The problem with this is that it is horridly slow and can take a very, very long time. It was suggested to me to process them in parallel so I did some searching through the web to find a good way to do just that and what I found was not only amazingly simple but also very, very fast. Microsoft has a Parallel.For and Parallel.ForEach. I also needed to know stop the loop when I get the information I need, which is where MSDN’s article on how to stop or break from a Parallel.For loop came in handy.

Notice how Stop and Break are two different things here. The basic difference is the time at which it stops threads running the loop that aren’t the one that the stop or break is being called by.

Stop tells the other threads, including ones that may be executing items after the one that is in the current thread, to finish their processing and stop when convenient. So let’s say that we’re doing a for loop from 0 to 9. 10 items. We might have something similar to the following:

Parallel.For(0, 10, Sub(i, loopState)
                               'processing code here
                               ' Somewhere in here we call:
                               loopState.Stop()
                    End Sub)

Basically, you’re passing an anonymous subroutine to the Parallel.For() function. So, passing a function to a function. That function takes two paramaters: the index (in this example i) and a ParallelLoopState object (i used loopState). The ParallelLoopState object is what you use to call the Stop() method. So for example’s sake, lets say we currently have threads with the index 4, 5, 6 running, and loopState.Stop() gets called from thread 5. It wont start any new threads with any new indexes, but it will wait for both for and 6 to finish what they were doing before finally stopping.

However Break tells any threads that are executing past the current index to drop whatever their doing, but lets anything previous to the current thread to finish before completely ending the loop. So going with the same example, running threads 4, 5, and 6, thread 5 calls loopState.Break(). Doing this lets thread 4 finish, but kills thread 6 immediately.

So now that we understand how the basics of these loops work, lets move on to the whois query part.

I basically wrote two functions; one to query all the whois servers for one particular domain in parallel, and one to execute the previous function on a list of domains I need the information from in parallel. The first function looks something like this:

Public Function ParallelQuery(ByVal domain As String) As String()

        Dim sr As StreamReader = New StreamReader("serverlist.txt")
        ' Read in the entire server list
        Dim whoisstring As String = sr.ReadToEnd()
        ' Split it by new line
        Dim whoislist As String() = whoisstring.Split(New Char() {vbCrLf})

        Dim returnData As String = ""

        Dim endData As String() = Nothing

        Parallel.ForEach(whoislist, Sub(d As String, loopstate As ParallelLoopState)
                                        Try
                                            returnData = ""
                                            d = d.Trim()
                                            ' Create a new TcpClient
                                            Dim tcpClient As TcpClient = New TcpClient(d, 43)

                                            Dim networkStream As NetworkStream = tcpClient.GetStream()
                                            If networkStream.CanRead And networkStream.CanWrite Then
                                                Dim sendBytes As Byte() = Encoding.ASCII.GetBytes(domain + vbCrLf)
                                                networkStream.Write(sendBytes, 0, sendBytes.Length)
                                                Dim bytes(tcpClient.ReceiveBufferSize) As Byte
                                                Dim recvSize As Int32
                                                recvSize = networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

                                                While recvSize <> 0
                                                    returnData += Encoding.ASCII.GetString(bytes, 0, recvSize)
                                                    recvSize = networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
                                                End While

                                                If returnData <> "" Then
                                                    ' This is where you do your processing of the return data from the request
                                                    ' I am using a regex expression to get the creation date.
                                                    Dim regex As New RegularExpressions.Regex("creation.date:\s+(.+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase)
                                                    Dim match As RegularExpressions.Match = regex.Match(returnData)

                                                    If match.Value <> "" Then
                                                        tcpClient.Close()
                                                        endData = {domain, match.Groups(1).Value}
                                                        ' If it finds what I need I can stop the loop.
                                                        loopstate.Stop()
                                                    End If
                                                End If

                                            End If
                                            tcpClient.Close()
                                        Catch ex As Exception
                                        End Try
                                    End Sub)
        Return endData
    End Function

The function that ran those queries in parallel looks like this:

 

Public Function processList(ByVal list As List(Of String)) As DataTable

        Parallel.ForEach(list, Sub(e)
                                   ' This returns the domain and creation date as a string for each one
                                   Dim res As String() = ParallelQuery(e)
                                   ' I can now do whatever I need to with the creation date

                               End Sub)

        Return dt

    End Function

 

You’ll notice that I used Parallel.ForEach loops in these functions. I didn’t need to use an index and instead thought it would be easier to have the object I’d be using inside the function passed to the function in place of the index. It’s relatively the same thing as the Parallel.For loop but you can use objects as the first parameter to the anonymous subroutine instead of just looking for an integer

 

So there you have it. I love .NET for creating this. AND it automatically chooses how many threads to use based on your system resources available. These methods make parallelism so easy it almost feels like cheating.


		
 

I’m writing a little module in python that contains lots of sorting algorithms (which can be found on my GitHub: here), and one i found particularly fun was the Binary Tree Sort.

This implements a “Node” Class to form the tree. Each Node has data and a left and right value. Left and Right should be other nodes or None. It has a “flatten” method that recursively flattens the tree into a sorted list. It makes use of a method, “_concatList”, that I had originally written for implementing the Quick Sort, but it ended up working quite well here too.

The sort itself is very simple. It loops through the list and inserts each element to a tree, and finally flattens it.

# Binary Tree Node
class Node:
	left, right, data = None, None, 0

	def __init__(self, data):
		self.left = None
		self.right = None
		self.data = data

	# add data to the tree
	def insert(self, data):
		# return false if the data is a duplicate
		if data == self.data:
			return false

		# if data is less than the current node go left
		elif data &lt; self.data:
			# if no data here, make a new node
			if self.left == None:
				self.left = Node(data)

			# else try the same on its left child
			else:
				self.left.insert(data)

		# if its greater, go right
		else:
			# if no data here, make a new node
			if self.right == None:
				self.right = Node(data)

			# else try the same on its right child
			else:
				self.right.insert(data) 

	# flatten a node into a list
	def flatten(self):
		# if no children, return this nodes data as a list
		if self.left == None and self.right == None:
			return [self.data]
		# create empty list
		li = []

		# append the first list
		if self.left is not None:
			li.extend(self.left.flatten())

		# append data
		li.append(self.data)

		# append the second list
		if self.right is not None:
			li.extend(self.right.flatten())

		return li

# Binary Tree Sort
def BinaryTreeSort(li):
	# create the root node with the first element
	root = Node(li[0])

	# add each element to the tree
	for i in xrange(1, len(li)):
		root.insert(li[i])

	#flatten the tree
	return root.flatten()

# Concatenate two sorted lists
# used for Binary Search Tree and Quick Sort
def _concatList(l1, a, l2):
	# create a new list
	li = []
	if l1 is not None:
		# append each of the elements from l1
		for l in l1:
			li.append(l)
	else:
		pass

	if a is not None:
		# append the middle if there is one
		li.append(a)
	else:
		pass

	if l2 is not None:
		# append each of the elements from l2
		for l in l2:
			li.append(l)
	else:
		pass

	return li

Here’s my test:

>>> Disorder.BinaryTreeSort([5,2,3,8,1,9,15,4,18])
[1, 2, 3, 4, 5, 8, 9, 15, 18]

 

.NET Reflection is a very, very powerful tool. One thing I used it for is making a basic plugin system for my web server.

I needed some sort of way to know what assemblies to load, so I used a configuration file with a simple format to parse. For each module I wanted to load, I put a line that was the path to the DLL, preceded by the word “mod”

mod C:modulesmodule.dll

I figured that me or someone else might write a plugin that used another external library, so I used “dep” to mark DLL’s that were needed for the modules.

dep C:dependenciesdependency.dll

When the server starts up, it reads through this configuration file, takes all the lines that start with mod or dep and assigns puts their path in module and dependency ArrayList’s respectively. Once the config file is read, it goes through and loads the dependencies first.

 Assembly.LoadFile(DependencyPath);

Loading the modules is a little more complicated. For this I created a simple Module class to hold some information I would need about it, and be able to give me access to the Assembly object that loading the dll returns. In this case, when I load the module, I want to go into a class called ModuleMap that contains the url mapping info that I require for the plugin, and call its GetUrlMap method.

    public class Module
    {
        public string ModulePath;
		public string ModuleNamespace;
        public Assembly ModuleAssembly;
        public List&lt;UrlMapItem&gt; UrlMap;

        public Module(string modulepath)
        {
            ModulePath = modulepath;
        }

        public void Load()
        {
            if (!File.Exists(ModulePath))
            {
                throw new NoSuchModuleException(&quot;Error: No such module at '&quot; + ModulePath + &quot;'.&quot;);
            }
            ModuleAssembly = Assembly.LoadFile(ModulePath);
            int lastslash = ModulePath.LastIndexOf(@&quot;&quot;);
            string assemblynamespace = ModulePath.Substring(lastslash+1, ModulePath.LastIndexOf('.') - lastslash-1);
			ModuleNamespace = assemblynamespace;
            Type t = ModuleAssembly.GetType(assemblynamespace+&quot;.ModuleMap&quot;);
            if (t != null)
            {
                MethodInfo m = t.GetMethod(&quot;GetUrlMap&quot;);
                if (m != null)
                {
                    UrlMap = (List&lt;UrlMapItem&gt;)m.Invoke(null, (new object[]{}));
                }
                else
                {
                    throw new InvalidModuleMapException(&quot;Error: The ModuleMap class is incorrect!&quot;);
                }
            }
            else
            {
                throw new InvalidModuleMapException(&quot;Error: The ModuleMap class is missing!&quot;);
            }
        }
    }

When I use the Invoke() method, I passed it two arguments. In this case, since it is a static method, the first argument is null. The second argument is an object array that contains the arguments for the invoked method. The Invoke() method returns an instance of an object class, so I casted it into the object type I needed, which in this case was a List.

Now, that UrlMapClass, that I now have a list of, contains two pieces of information:

  • A url
  • A method with the full namespace/class path (ex. “testnamespace.testclass.methodname”)

Then I took a Hashtable and used the namespace.class.method path as the key, and the Module.ModuleAssembly as the value object. This way when I go to call it, I can enter the path that I know is being called, take the Assembly object, and do what I did before and call MethodInfo.Invoke().

Assembly assembly = (Assembly)ModuleList[methodnamespace];
Type t = assembly.GetType(method.Substring(0, method.LastIndexOf('.')));
MethodInfo m = t.GetMethod(method.Substring(method.LastIndexOf('.') + 1));
Page p = (Page)m.Invoke(null, (new object[] { rq }));

The method variable contained the whole method.class.methodname path and the methodnamespace variable contained just the namespace. To get the class for GetType() I used a substring of the whole namespace.class.methodname string that was from 0 to the last . which would give you just namespace.class.

This is a pretty simple example. I structured my plugin DLL’s in such a way that it gave me all the info I needed to call the corresponding methods in a very simple manner. There are obviously much more complex ways to do this.

 

Here is a little tutorial for handling multiple simultaneous connections in C#.

The trick to doing asynchronous I/O with C# sockets is the AsyncCallback. You call the socket.Begin* methods, passing them an AsyncCallback object (which is a method) and a state object. The state object you pass is the socket itself. When the callback is called, it is passed an IAsyncResult. This contains the AsyncState, which is the state object you passed. You can cast it into a Socket and continue processing. Now we can get to the code:

The first thing we need is to include the proper references:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

You may be wondering why we need System.Threading. This is because we need a ManualResetEvent. This is used to signal events between the methods.

We’ll now write a class called ServerRunner, which starts the serving by its method Run(). It has 3 other methods, AcceptCon(), SendData(), and ReceiveData(). All 3 methods take an IAsyncResult “iar”.

First we need a couple of class variables

        private Byte[] data = new Byte[2048];
        private int size = 2048;
        private Socket server;
        static ManualResetEvent allDone = new ManualResetEvent(false);

This gives us some stuff for the actual transmission of the data, and of course the ManualResetEvent that I explained earlier. Heres our Run method that starts everything:

        public void Run()
        {
            try
            {
                server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, 33333);
                server.Bind(iep);
                Console.WriteLine(&quot;Server initialized..&quot;);
                server.Listen(100);
                Console.WriteLine(&quot;Listening...&quot;);
                while (true)
                {
                    allDone.Reset();
                    server.BeginAccept(new AsyncCallback(AcceptCon), server);
                    allDone.WaitOne();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

This starts like any listening socket. Create an IPEndPoint and bind your server socket to it. Then call the listen method. Then you want to start an infinite loop calling the BeginAccept() method with the AsyncCallback and state object. Around it, you want your ManualResetEvent’s Reset() and WaitOne() methods. This makes it so it waits until the connection has actually been accepted and started to be dealt with before it can start to accept a new one. In the next method You’ll see the ManualResetEvent’s Set() method, which tells it that it is ok to continue to the next connection. Heres the AcceptCon() method we put as the AsyncCallback to the BeginAccpet()

        void AcceptCon(IAsyncResult iar)
        {
            allDone.Set();
            try
            {
                Socket oldserver = (Socket)iar.AsyncState;
                Socket client = oldserver.EndAccept(iar);
                Console.WriteLine(client.RemoteEndPoint.ToString() + &quot; connected&quot;);
                byte[] message = Encoding.ASCII.GetBytes(&quot;Welcome&quot;);
                client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendData), client);
            }
            catch (Exception)
            {
                Console.WriteLine(&quot;Connection closed..&quot;);
                return;
            }
        }

In this method, first we call the ManualResetEvent’s Set() method, which tells it that we have gotten what we need. Then we cast the iar.AsyncState (the state object we passed into the method, which was a Socket) back to what it originally was so we can use it. This code sends a simple “Welcome” message to the client that connects. However you can choose to do whatever you want. We then call the BeginSend method, again with an AsyncCallback (this time to the SendData() method) and a state object (this time client socket).

        void SendData(IAsyncResult iar)
        {
            try
            {
                Socket client = (Socket)iar.AsyncState;
                int sent = client.EndSend(iar);
                client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
            }
            catch (Exception)
            {
                Console.WriteLine(&quot;Connection closed..&quot;);
                return;
            }
        }

This method finishes off the send, and then starts to listen for more data by calling the ReceiveData() method as an AsyncCallback, again passing the client socket as a state object.

        void ReceiveData(IAsyncResult iar)
        {
            try
            {
                Socket client = (Socket)iar.AsyncState;
                int recv = client.EndReceive(iar);
                if (recv == 0)
                {
                    client.Close();
                    server.BeginAccept(new AsyncCallback(AcceptCon), server);
                    return;
                }
                string receivedData = Encoding.ASCII.GetString(data, 0, recv);
                // process received data here
                // decide what to send back
                byte[] message2 = Encoding.ASCII.GetBytes(&quot;reply&quot;);
                client.BeginSend(message2, 0, message2.Length, SocketFlags.None, new AsyncCallback(SendData), client);
            }
            catch (Exception)
            {
                Console.WriteLine(&quot;Connection closed..&quot;);
                return;
            }
        }

This is where we do all the data handling. It takes in data, does what you need to do with the data, and sends back a response. In this method we check to see if the socket is done, in which case we close it, call BeginAccept again to continue listening, and return to end the method execution. This method doesn’t actually have any data handling in it, it simply sends the string “reply” as a response to every piece of data that comes in. But I left comments showing you where to put your methods to actually deal with the data and come up with a response. When we are done handling the data, we call the BeginSend, which sends off the data, and then goes back to receiving again. It continues until the connection is closed.

A small warning about this code: The only exception handling in here is to keep the server from crashing if the client disconnects unexpectedly. If you are planning to use this as any sort of production code, I suggest you put in much more detailed exception handling.

Well. There it is. It’s much simpler than I thought it was going to be, and it only requires those 3 methods really. Hope you can all put this to good use.

 

I’m writing this post for two reasons:

  1. It is a pretty cool thing to do and very useful
  2. The amount of useful documentation and links you can find is very small

It took me about 12 hours of futsing with this and Googling things to get this correct. Most of my information actually came from bug reports of various open source projects that use UPnP for peer-to-peer connections.

I haven’t put much error checking in here, I want to keep the code short and as easy to understand as possible. I’ll leave that one up to the users to figure out.

To use this code, you must first call NAT.Discover(). This makes sure you have a UPnP device available. After that you can go ahead and Add and Delete ports as you wish. Heres the code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Xml;
using System.IO;

namespace enChatClient
{
    public class NAT
    {
        static TimeSpan _timeout = new TimeSpan(0, 0, 0, 3);
        public static TimeSpan TimeOut
        {
            get { return _timeout; }
            set { _timeout = value; }
        }
        static string _descUrl, _serviceUrl, _eventUrl;
        public static bool Discover()
        {
            System.Net.NetworkInformation.NetworkInterface nic = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0];

            System.Net.NetworkInformation.GatewayIPAddressInformation gwInfo = nic.GetIPProperties().GatewayAddresses[0];
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            string req = "M-SEARCH * HTTP/1.1rn" +
            "HOST: " + gwInfo.Address.ToString() + ":1900rn" +
            "ST:upnp:rootdevicern" +
            "MAN:"ssdp:discover"rn" +
            "MX:3rnrn";
            Socket client = new Socket(AddressFamily.InterNetwork,
                SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint endPoint = new
            IPEndPoint(IPAddress.Parse(gwInfo.Address.ToString()), 1900);

            client.SetSocketOption(SocketOptionLevel.Socket,
                SocketOptionName.ReceiveTimeout, 5000);

            byte[] q = Encoding.ASCII.GetBytes(req);
            client.SendTo(q, q.Length, SocketFlags.None, endPoint);
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint senderEP = (EndPoint)sender;

            byte[] data = new byte[1024];
            int recv = client.ReceiveFrom(data, ref senderEP);
            string queryResponse = "";
            queryResponse = Encoding.ASCII.GetString(data);

            DateTime start = DateTime.Now;

            string resp = queryResponse;
            if (resp.Contains("upnp:rootdevice"))
            {
                resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                resp = resp.Substring(0, resp.IndexOf("r")).Trim();
                if (!string.IsNullOrEmpty(_serviceUrl = GetServiceUrl(resp)))
                {
                    _descUrl = resp;
                    return true;
                }
            }
            return false;
        }

        private static string GetServiceUrl(string resp)
        {
            XmlDocument desc = new XmlDocument();
            try
            {
                desc.Load(WebRequest.Create(resp).GetResponse().GetResponseStream());
            }
            catch (Exception)
            {
                return null;
            }   
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(desc.NameTable);
            nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
            XmlNode typen = desc.SelectSingleNode("//tns:device/tns:deviceType/text()", nsMgr);
            if (!typen.Value.Contains("InternetGatewayDevice"))
                return null;
            XmlNode node = desc.SelectSingleNode("//tns:service[tns:serviceType="urn:schemas-upnp-org:service:WANIPConnection:1"]/tns:controlURL/text()", nsMgr);
            if (node == null)
                return null;
            XmlNode eventnode = desc.SelectSingleNode("//tns:service[tns:serviceType="urn:schemas-upnp-org:service:WANIPConnection:1"]/tns:eventSubURL/text()", nsMgr);
            _eventUrl = CombineUrls(resp, eventnode.Value);
            return CombineUrls(resp, node.Value);
        }

        private static string CombineUrls(string resp, string p)
        {
            int n = resp.IndexOf("://");
            n = resp.IndexOf('/', n + 3);
            return resp.Substring(0, n) + p;
        }

        public static void ForwardPort(int port, ProtocolType protocol, string description)
        {
            if (string.IsNullOrEmpty(_serviceUrl))
                throw new Exception("No UPnP service available or Discover() has not been called");

            IPHostEntry ipEntry = Dns.GetHostByName(Dns.GetHostName());
            IPAddress addr = ipEntry.AddressList[0];

            XmlDocument xdoc = SOAPRequest(_serviceUrl,
                "<m:AddPortMapping xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string"></NewRemoteHost><NewExternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">" +
                port.ToString() + "</NewExternalPort><NewProtocol xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">" +
                protocol.ToString().ToUpper() + "</NewProtocol><NewInternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">" +
                port.ToString() + "</NewInternalPort><NewInternalClient xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">" +
                addr + "</NewInternalClient><NewEnabled xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="boolean">1</NewEnabled><NewPortMappingDescription xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">" +
                description + "</NewPortMappingDescription><NewLeaseDuration xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui4">0</NewLeaseDuration></m:AddPortMapping>",
                "AddPortMapping");
        }

        public static void DeleteForwardingRule(int port, ProtocolType protocol)
        {
            if (string.IsNullOrEmpty(_serviceUrl))
                throw new Exception("No UPnP service available or Discover() has not been called");
            
            XmlDocument xdoc = SOAPRequest(_serviceUrl,
            "<u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">" +
            "<NewRemoteHost></NewRemoteHost>" +
            "<NewExternalPort>" + port.ToString() + "</NewExternalPort>" +
            "<NewProtocol>" + protocol.ToString().ToUpper() + "</NewProtocol>" +
            "</u:DeletePortMapping>", "DeletePortMapping");
        }

        public static IPAddress GetExternalIP()
        {
            if (string.IsNullOrEmpty(_serviceUrl))
                throw new Exception("No UPnP service available or Discover() has not been called");
            XmlDocument xdoc = SOAPRequest(_serviceUrl, "<u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">" +
            "</u:GetExternalIPAddress>", "GetExternalIPAddress");
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
            nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
            string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr).Value;
            return IPAddress.Parse(IP);
        }

        private static XmlDocument SOAPRequest(string url, string soap, string function)
        {
            string req = "<?xml version="1.0"?>" +
            "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">" +
            "<s:Body>" +
            soap +
            "</s:Body>" +
            "</s:Envelope>";
            WebRequest r = HttpWebRequest.Create(url);
            r.Timeout = 10000;
            r.Method = "POST";
            byte[] b = Encoding.UTF8.GetBytes(req);
            r.Headers.Add("SOAPACTION", ""urn:schemas-upnp-org:service:WANIPConnection:1#" + function + """);
            r.ContentType = "text/xml; charset="utf-8"";
            r.ContentLength = b.Length;
            r.GetRequestStream().Write(b, 0, b.Length);
            XmlDocument resp = new XmlDocument();
            WebResponse wres = r.GetResponse();
            Stream ress = wres.GetResponseStream();
            resp.Load(ress);
            return resp;
        }
    }
}

These SOAP requests use two UPnP “commands”:

  • AddPortMapping
  • DeletePortMapping

AddPortMapping needs the following parameters:

  1. NewRemoteHost – Used to make it so that only one remote host can connect. Generally not used and OK to leave blank.
  2. NewExternalPort – The port that the incoming outside connection should be connecting on.
  3. NewProtocol – This is the protocol that will be running on the port. should be either “TCP” or “UDP”.
  4. NewInternalPort – The port on the inside of the network that the connection will be forwarded to.
  5. NewInternalClient – The internal IP address the connection should be forwarded to.
  6. NewEnabled – Whether the connection should be enabled or not. You want to set this to 1 so it actually works.
  7. NewPortMappingDescription – Just a short description of what the port is actually being used for. Generally the program name.
  8. NewLeaseDuration – Just set this to 0.

If the AddPortMapping doesn’t work for some reason you will get a server 500 error. Otherwise you will get an xml response

DeletePortMapping needs the following parameters:

  1. NewRemoteHost – Same thing as AddPortMapping. Not really used.
  2. NewExternalPort – The external port that the forwarding you’re deleting is running on.
  3. NewProtocol – The protocol it is running. “TCP” or “UDP”

If there is no such port mapping in the table, you will get a server 500 error, so be careful.

You can also check to see if a mapping exists by using GetSpecificPortMapping entry which takes NewRemoteHost, NewExternalPort, and NewPortMappingProtocol, and it returns a bunch of data on the connection. However the downside is that if it doesn’t exist, you get a server 500 error, and these can be trick to handle if you’re using a WebRequest, as it just throws it as a WebException.

The other way to do it is to GetGenericPortMappingEntry which returns the table of them and you can search it for the one you want.

NOTE: AddPortMapping will overwrite the previous mapping on the same port and protocol.

 

A while ago I made a post about a Web Crawler in less that 50 lines of python. Well, I took that and made it a little (and really, I mean just a little..) more sophisticated, and stuck it on GitHub. Anyone who wants to can contribute, or use the code however they want.

PyCrawler On GitHub

 

In my new site, Aud (which you can see my original post on here), I use a lot of javascript, and I wanted it to be very fast. One part that was amazingly slow was the generation of the playlist. The script does an ajax call to the server to get the playlist as JSON, and then turns each song into a table row and appends it to the table in the playlist div. Simple, yes, but if you do it wrong and have a lot of data, it’s very slow. Heres a tip I figured out to help speed up the process:

Instead of using your typical concatenation techniques like this:

var table = "";
for (var i = 0; i < playlist.length; i++) {
   table += "<tr><td><strong>Artist: " + artist + " Album: " + album + " Song: " + song + "</td></tr>";
}
$('#table').append(table);


You would do something like this:


var table = [];
for (var i = 0; i < playlist.length; i++) {
   table.push(["<tr><td><strong>Artist: ", artist, " Album: ", album, " Song: ", song, "</td></tr>"].join(''));
}
$('#table').append(table.join(''));


Now some people might think, “Well, why not put the .append() inside the loop?”. You really don’t want to do that. It’s very costly in terms of speed, and ends up even slower.

So if you have a lot of appending to strings, try making it an array, and pusing and joining!

 

I got kind of bored today, and wrote a pretty simple web crawler with python and it turned out to be less than 50 lines. It doesn’t store output, I’ll leave that up to anyone who wants to use the code, because, well, theres just too many ways to choose from. Right now you pass it a starting link as a parameter and it will crawl forever untill it runs out of links. But that is not a likely condition. So here ya go. Have fun. Feel free to ask questions

import sys
import re
import urllib2
import urlparse
tocrawl = set([sys.argv[1]])
crawled = set([])
keywordregex = re.compile('<metasname=["']keywords["']scontent=["'](.*?)["']s/>')
linkregex = re.compile('<as*href=['|"](.*?)['"].*?>')

while 1:
	try:
		crawling = tocrawl.pop()
		print crawling
	except KeyError:
		raise StopIteration
	url = urlparse.urlparse(crawling)
	try:
		response = urllib2.urlopen(crawling)
	except:
		continue
	msg = response.read()
	startPos = msg.find('<title>')
	if startPos != -1:
		endPos = msg.find('</title>', startPos+7)
		if endPos != -1:
			title = msg[startPos+7:endPos]
			print title
	keywordlist = keywordregex.findall(msg)
	if len(keywordlist) > 0:
		keywordlist = keywordlist[0]
		keywordlist = keywordlist.split(", ")
		print keywordlist
	links = linkregex.findall(msg)
	crawled.add(crawling)
	for link in (links.pop(0) for _ in xrange(len(links))):
		if link.startswith('/'):
			link = 'http://' + url[1] + link
		elif link.startswith('#'):
			link = 'http://' + url[1] + url[2] + link
		elif not link.startswith('http'):
			link = 'http://' + url[1] + '/' + link
		if link not in crawled:
			tocrawl.add(link)

** EDIT **

This was a very early draft of this program. As it turns out, I revisited this project a few months later and it evolved much more.
If you would like to check out the more evolved form, feel free to have a look here at my github!

 

Web Requests are amazingly easy in C# – All you need is this:

WebRequest myWebRequest = WebRequest.Create("http://www.google.com");
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
StreamReader readStream = new StreamReader(ReceiveStream);
String Response = readStream.ReadToEnd();

Returns everything from wherever you request. So simple. Need I explain more?

© 2012 Code Brain Suffusion theme by Sayontan Sinha