Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Sunday, January 8, 2017

Determine the byte order using Swift

As humans, when we look at a number, we put the most significant number first and the least significant number last.  As an example when we look at the number 123 we know that the number 1 represents 100 which is the most significant digit while 3 is the least significant digit.  For computers, the byte order refers to the order that data is stored in memory.  Some computers store the most significant bytes first (at the lowest byte address), while others store the most significant bytes last (highhest byte address). 

If a device stores the most significant bytes first, it is known big-endian while a device that stores the most significant bytes last is knows as little-endian. 

The order of how data is stored in memory is of great importance when doing network development because RFC1700 states that the byte order for Internet Protocols must be big-endian. If the device that our application is running on stores data in little-endian order than we need to convert it.  We can use the Network-to-Host and Host-to-Network functions to convert between the byte order of your device and the byte order of the network.  These function, will take into account the byte order of the device the application is running on (host) and will convert the data to big-endian (network) byte order if necessary.  These functions are:

·       htons() – Host to network short
·       htonl() – Host to network long
·       ntohs() – Network to host short
·       ntohl() – Network to host long

By using these functions we generally to not need to worry about the endianess of the device we are running on however there are times we will want to know.  In this post we will look at how we can determine the byte order of the device our application is running on.

It is a good idea to import the Foundation framework and either Glibc or Darwin framework depending on the operating system the application is running on therefore we will start off by importing these frameworks.  Here is our import statement.

    import Foundation
    #if os(Linux)
        import Glibc
    #else
        import Darwin
    #endif

In this code we import the Glibc framework if we are building for a Linux system otherwise we import the Darwin framework.  We import the Foundation framework for both platforms.
Now that we have imported the frameworks needed, lets determine the byte order for the device. 

    let number: UInt32 = 0x12345678
    let converted = number.bigEndian
    if number == converted {
        print("Big")
    } else {
        print("Little \(converted)")
    }

In this code we begin by defining a UInt32 number.  We then convert how it is stored to big endian.  When we compare the original number to the converted one, if the two numbers are equal then the device uses big endian otherwise we know it uses little endian.

The Swift standard library provides two instance properties that allow us to change the byte order.  These properties are bigEndian and littleEndian.  The device that our code is running on probably uses little endian therefore when we use the bigEndian property the byte order of the number is changed.  This will give us a different number therefore when we compare the original number to the converted one the numbers will not match.  This tells us that the device uses little endian to store data.  If the numbers do match, than we know the device uses big endian.


Saturday, January 7, 2017

Creating a Swift module

When we develop applications with Swift, for the Linux platform, we are able to use the Swift package manager to assist us with building our application.  The package manager is integrated with the build system to automate the process of downloading, compiling and linking the dependencies for our project.

One of the ways that we can define a dependency is to create a module.  Swift organises code into modules and each module uses access controls to determine which parts of its code can be accessed outside of the module.
For several projects in this blog we will be using modules to link external C libraries to our project.   We will refer to this post when we need to create these modules. 

To create a module we need to start off my creating a separate directory for it.  If we were creating a module to link the ifaddrs.h header file to our project we would want to create the directory like this:
    
    mkdir ifaddrs

Within this directory we need to create two files:  module.modulemap and Package.swift.  The module.modulemap file will contain a list of requirements for our module while the Package.swift file defines the name of our module.  Let’s begin by looking at the Package.swift file first.  To define the Ifaddrs module we would create a Package.swift file with the following code:

    import PackageDescription
    let package = Package(
        name: "Ifaddrs"
    )

Now we need to define the requirements for the Ifaddrs module in the module.modulemap file.  For this module we simply want to import the ifaddrs.h header file therefore we would put the following code in the this file:

    module Ifaddrs [system] {
        header "/usr/include/ifaddrs.h"
        export *
    }

The Swift package manager is based on the git repository therefore before we can use this module within any project, we need to create a git repository for it.  We could put this module in a github repository but that may be too much for a simple module like this.  We can create a local repository using the following commands within the modules directory:

    git init
    git add .
    git commit –m “Initial Commit”
    git tag 0.1.0

These four commands will create a local git repository for our module with a major version number of 0 and a minor version number of 1.

In the Ifaddrs module we simply included the ifaddrs.h header file in our project but if we wanted to include a third-party library, such as the libpcap library, we would need to link the library to our project as well.  For this we could link the library as shown in the following example:

    module Cpcap [system] {
        header "/usr/include/pcap.h"
        link "pcap"
        export *
    }

Once we create a module we can use the Swift package manager to automatically import and build the module when we build our project.  To do this, all we need to do is to define a dependency on the module within the projects Package.swift file.  The following example shows how we could define a dependency on the Ifaddrs module:

     import PackageDescription

     let package = Package(
        name: "ipaddr",
        dependencies: [
            .Package(url: "../ifaddrs", majorVersion: 0, minor: 1)
        ]
    )   

The dependencies array in the package defines the list of dependencies for our project.  The url is an absolute path to our module.  In this example the module is located on our local drive however we can also define modules that should be downloaded from the internet.  The following example shows how we defined the dependency for IBM’s BlueSocket module:

    import PackageDescription

    let package = Package(
       name: "echoServer",
       dependencies: [
           .Package(url: "https://github.com/IBM-Swift/BlueSocket", majorVersion: 0, minor: 12)
       ]
    )

In this example you will notice that the url defines a github repository rather than a local repository.
Once we define the dependency for a module we need to import it in our code.  We would do this by using the import command to import the namespace define by the module. 

In the beginning of this post we created the Ifaddrs module with the following Package.swift file:
    
    import PackageDescription

    let package = Package(
        name: "Ifaddrs"
    )

This example created a namespace of Ifaddrs for the module therefore to use the functionality provided by the module in our code we need to import the namespace like this:

    import Ifaddrs

We will be using modules extensively in this blog and will refer to this post to show how to create them.