SHA-1 Sum Every File

Easiest way to check whether file is valid after download is to grab it’s SHA-1 sum. Most commonly it has same name as file but with additional .sha1 extension (e.g. temp.zip would have SHA-1 sum in temp.zip.sha1). One annoyance is how to generate all those .sha1 files…

To make my life little bit easier, I made a bash script. This script will go through given directories and create all SHA-1 sums. I use content and download directories in this case:

#!/bin/bash
for file in ~/public_html/{content,download}/*
do
    if [ -f "$file" ]
    then
        if [ ${file: -5} != ".sha1" ]
        then
            file1=$file
            file2="$file1.sha1"
            file1Sum=`sha1sum $file1 | cut --delimiter=' ' -f 1`
            if [ -e "$file2" ]
            then
                file2Sum=`cat $file2`
                if [ "$file1Sum" == "$file2Sum" ]
                then
                    echo "  $file1"
                else
                    echo "X $file1"
                    echo "$file1Sum" > "$file2"
                fi
            else
                echo "+ $file1"
                echo "$file1Sum" > "$file2"
            fi
        else
            file1=${file%.sha1}
            file2=$file
            if [ ! -e "$file1" ]
            then
                echo "- $file1"
                rm "$file2"
            fi
        fi
    fi
done

Probably some explanation is in order. Script check each file in content and download directories. If file ends in .sha1 (bottom of the script), we will just remove that file and log action with minus (-) sign. This serves as clean-up for orphaned SHA-1 sums.

If file does exist, we need to check existing SHA-1 sum. If there is no sum script will just create one and log it with plus (+) sign. If sum does exist, script compares it with newly generated value. If both match, there is nothing to do, if they do not match, that is logged with X character.

Example output would be:

  /public_html/download/qtext301.exe
+ /public_html/download/qtext310.exe
X /public_html/download/seobiseu110.exe
- /public_html/download/temp.zip

Here we can see that sum for qtext301.exe was valid and no action was taken. Sum for qtext310.exe was added and one for seobiseu110.exe was fixed (it’s value didn’t match). File temp.zip.sha1 was removed since temp.zip does not exist anymore.

P.S. While this code is not perfect and it might not be best solution, it does work for me. :)

I Like Unique Identifiers

Illustration

As I was finishing my order of MSDN magazine I was puzzled with one field. It said “In lieu of a signature, we require a unique identifier. In what month were you born?”

I am not quite sure in what universe month of birth is even close to being unique…

P.S. It is January.

IPv6 Multicast

Last post dealt with sending same message to multiple clients in IPv4. Since IPv4 pool is almost gone, we might as well see how to do it in IPv6.

Believe it or not, code is virtually identical:

this.Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
this.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.Socket.Bind(new IPEndPoint(IPAddress.IPv6Any, 65535));
this.Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(IPAddress.Parse("ff08::1")));

Just use socket as you would normally do.

Code example is available for download.

P.S. For this example I used ff08::1 as multicast address. You might want to change this to something not as usual as this (but compliant to ffx8::/16). E.g. ff28::1:2:3:4:5 might do the trick.

Using IPC-3605N Without EaZy Wizard

Illustration

My laptop has no DVD drive since I removed it a while ago in order to get another hard drive in. Therefore I was little bit unprepared when I bought myself ZyXEL IPC-3605N camera. User guide told me I have to run tool found on CD that I could not read.

I am lazy, so first I tried to download that tool (eaZy Wizard) from ZyXEL pages. Only when I could not find it anywhere (thank you ZyXEL for forcing users to keep CD around) I decided upon more imaginative solutions.

Since manual did mention some addresses in 192.168.0.x range and that range being most often used, I set my laptop’s wired network adapter to 192.168.0.254 and connected camera directly to it. Than I used MagiWOL’s import functionality to scan network for all MAC addresses in range 192.168.0.1-192.168.0.253. That resulted in single hit - my camera was at 192.168.0.100.

After finding out IP address, all I had to do was to enter this IP in browser and use “admin”/“1234” as user/password combination (not “admin”/“admin” as user manual suggested). With that I could proceed with setting-up configuration.

And CD was left forgotten.

Multicast

Whenever there is need to distribute same data to multiple applications over network I tend to see same thing. Everybody just makes broadcast socket. That is usually wrong way to do it.

From the very beginning of IP, there is special class called multicast addresses. Idea is simple: you “join” multicast address and whatever you send to it is received by everybody else who joined.

While this might seem a lot like broadcast, it is not the same thing. If you have network of 100 computers and only two need to talk, broadcast will send same data to 100 of them anyway. In multicast case switch can optimize this and send data only to two computers that need it.

Even in case of dumb switch which behaves with multicast in same manner as with broadcast, there is benefit. Since multicast addresses reside in completely different range, there is no fear that we will interfere with any normal socket that is listening on same port. Yes, we might stumble at another multicast group by accident but chances are pretty slim.

Creation of multicast socket is quite similar to creation of any other socket:

this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.Socket.Bind(new IPEndPoint(IPAddress.Any, 65535));
this.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.192.0.1"), IPAddress.Any));

As you can see, only real difference is in additional socket option that adds our socket to multicast group (do not forget do remove it on application exit).

And that is it. Everything else works as it would with “normal” socket.

Code example is available for download.

P.S. For this example I use multicast address of 239.192.0.1. You might want to change this to something not as usual as this (but still in 239.192.0.0 range).