How to Get CPU Information on Android

Unlike iPhone, Android devices come with different hardware from different manufacturers. One important difference is the CPU architecture. Although almost all Android devices use ARM CPU, it comes with different versions, including armv5, armv5te, armv6, armv6 with VFP, armv7, armv7 with VFP, armv7 with neon etc.

Most of the time there’s no need for a developer to care about CPU types, but if you are developing CPU intensive apps, e.g. video player, video converter etc, you may want to optimize your code based on CPU types.

Retrieving CPU types on Android devices is actually quite simple. Android is based on Linux, and Linux /proc file system has provided an interface for users to get CPU information — /proc/cpuinfo. So to get the CPU information, you simply read this file. And read this file doesn’t require super user privilege.

To get the CPU info from command line, simple enter the command below,

adb shell                              (connect to your Android device shell)

cat /proc/cpuinfo               (read the CPU info)

If you want to get the CPU info programmatically, use the code below,

private String getInfo() {

    StringBuffer sb = new StringBuffer();

    sb.append("abi: ").append(Build.CPU_ABI).append("n");

    if (new File("/proc/cpuinfo").exists()) {

        try {

            BufferedReader br = new BufferedReader(new FileReader(new File("/proc/cpuinfo")));

            String aLine;

            while ((aLine = br.readLine()) != null) {

                sb.append(aLine + "n");

            }

            if (br != null) {

                br.close();

            }

        } catch (IOException e) {

            e.printStackTrace();

        } 

    }

    return sb.toString();

}

You can download the entire code from here or get it from my github repo here.
A sample output is as below,

It gives the process type, and features that are supported by it.

Video Converter Android 0.9 Released

This is an app idea has been in the mind for quite a few months. I am busy with work and study, but finally it’s ready for release.

Previously I did some work to port ffmpeg to android platform as an app, I received a dozen of positive feedback. But many of them suggest the UI could be better. Now hopefully this app can help.

It’s the first release for this app, but I think it’s already very powerful. 🙂 The app is capable of converting almost any commonly-used video formats to videos playable by Android system default player. The list of codecs is supports include (but not limited to) asf, avi, divx, flv, m2v, m4v, mjpeg, mkv, mov, mpg, ogg, ogv, rm, rmvb, webm, wmv etc.

I’m planning to allow user to configure more about the output video settings, like resolution, codec format, container format, etc. Also an ffmpeg command line interface might be provided for advanced users. It might take some time for these features to be ready, as I’m still busy with work and study. As always, feel free to suggest or feedback anything!

Side Note: I did a search on video converter, only a few apps exist. Their method is to upload the video to some remote server, convert the videos there, and then download the video to the device. Hope Video Converter Android can help some users who don’t want to do that.

You can download the app at Android Market: https://market.android.com/details?id=roman10.media.converter

Using telnet to Help Debugging TCP-based Application

Telnet can refer to either the Telnet network protocol used to provide a bidirectional interactive text-oriented communication facility or the telnet program that implements the client side of the Telnet protocol. This post focuses on the telnet program.

Telnet doesn’t encrypt data sent (including password) over the connection, so it’s not secure. SSH has been widely used to replace telnet for remote login/control.

Telnet data are transmitted over TCP. Except some special characters, telnet can be used to establish a raw TCP connection. Because of this, telnet can be used to debug TCP-based applications, such as HTTP server, FTP server, etc. You can also use it to test TCP servers developed by yourself.

0. An Example of Using Telnet to Debug HTTP

We can issue HTTP request to a HTTP server and examine the response. Below is an example of using HTTP to connect to google web server.

telnet www.google.com 80
Trying 74.125.235.51…
Connected to www.l.google.com.
Escape character is ‘^]’.
GET /index.html HTTP/1.1

HTTP/1.1 302 Found
Location: http://www.google.com.sg/index.html
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=0cf4ad941da7097d:FF=0:TM=1323450677:LM=1323450677:S=4CGr4KBGwGHxlgql; expires=Sun, 08-Dec-2013 17:11:17 GMT; path=/; domain=.google.com
Date: Fri, 09 Dec 2011 17:11:17 GMT
Server: gws
Content-Length: 232
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
<HTML><HEAD><meta http-equiv=”content-type” content=”text/html;charset=utf-8″>
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF=”http://www.google.com.sg/index.html”>here</A>.
</BODY></HTML>

1. An Example of Using Telnet to Debug a Simple TCP Server

If we build a TCP server application, we can use telnet to test it. We use the TCP server program here for illustration. Below is the execution of running the server on port 12345 and using telnet to connect to it.

At server:

./server 12345
connection accepted
received: hello world
sent: hello world
received: hello roman10
sent: hello roman10
received: telnet sample
sent: telnet sample
received: for simple tcp server
sent: for simple tcp server
received: we’re going to finish
sent: we’re going to finish

At another terminal running telnet:

telnet 127.0.0.1 12345
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is ‘^]’.
hello world
hello world
hello roman10
hello roman10
telnet sample
telnet sample
for simple tcp server
for simple tcp server
we’re going to finish
we’re going to finish
Connection closed by foreign host.

Alternatives to Telnet

Telnet can be used as raw TCP client at many cases, but there’re some special characters telnet cannot handle like raw TCP client. Fortunately, there’re true raw TCP clients can be used as alternatives to telnet, including netcat and socat on Linux/UNIX, and PuTTY on Windows. We can use similar method to debug TCP-based applications using those programs.

Reference:
Telnet on Wikipedia: http://en.wikipedia.org/wiki/Telnet

Using mmap for Random Access of Files

mmap allows a program to map a section of the file into the program’s memory space, and access it with a pointer. This post illustrates mmap for random access of files.

0. Description

The mmap system call is defined in sys/mman.h as below,

void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

 

The input parameters have the following meanings,

  • addr: the address we want to map to. Usually set to zero to let the OS decide the address for us.
  • len: the length of data we want to map.
  • prot: the access rights the process want to have to the mapped memory. The values can be PROT_READ, PROT_WRITE and PROT_EXEC, which corresponds to read, write and execute permissions respectively. Note that one can specify multiple permissions by ORing the values.
  • flags: Set to MAP_SHARED if you want to share the file with other processes. Set to MAP_PRIVATE will get your process a copy of the mapped region, and your changes won’t be reflected in the original file. There’re other flags, you can refer to man page.
  • fildes: the file descriptor of the file you want to map. It can be obtained using the open system call as below. Note that the access mode should be the same as prot flags you set in mmap call.

    int fd = open(“test”, O_RDWR);

  • off: the offset of the file to start mmap. Note that this must be a multiple of virtual memory page size, which can be get by a call to getpagesize() or sysconf(_SC_PAGE_SIZE)

On success, mmap returns a pointer to the beginning of the mapped data region. Otherwise, it returns a value of MAP_FAILED and sets errno.

After mmap the file, we got a pointer to the mapped data. We can use the pointer to jump to a specific byte to access the data. The example given in part 1 illustrates this by reading a specific byte you specify.

After we’re done with mmap, we can unmap by mummap call,

int munmap(void *addr, size_t len);

 

  • addr: the address of unmap, which should be the address returned by mmap call.
  • len: the length to unmap, which should be the same as the len parameter passed in mmap call.

Note that a mapped file is unmapped automatically upon process termination.

1. Example

Below is an example illustrating mmap,

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    int fd, offset;
    unsigned char *data;
    struct stat sbuf;
    FILE *f;
    int i;
    unsigned char writeBytes[10];

    if (argc != 2) {
        fprintf(stderr, "usage: mmapdemo offsetn");
        exit(1);
    }

    /*create the test file*/
    for (i = 0; i < 10; ++i) {
    writeBytes[i] = (unsigned char)i;
    }
    f = fopen("./test", "w");
    for (i = 0; i < 10; ++i) {
        fwrite(writeBytes, 1, 10, f);
    }
    fclose(f);

    if ((fd = open("./test", O_RDONLY)) == -1) {
        perror("open");
        exit(1);
    }
    if (stat("./test", &sbuf) == -1) {
        perror("stat");
        exit(1);
    }
    printf("file size: %ldn", sbuf.st_size);
    offset = atoi(argv[1]);
    if (offset < 0 || offset > sbuf.st_size-1) {
        fprintf(stderr, "mmapdemo: offset must be in the range 0-%ldn", (sbuf.st_size-1));
        exit(1);
    }

    data = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)    ;
    if (data == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }

    printf("byte at offset %d is %dn", offset, data[offset]);
    munmap(data, sbuf.st_size);

    return 0;
}

The code creates a test file first. It opens the file to get a file descriptor. stat is called to get the file size. mmap is then applied to map the entire file into memory. After that, we can access a specific byte using the pointer returned by printing its value. Note that we can define the data pointer as pointer to some other data types. If we define as int, then we can access the data as ints.

Copy, paste and save the file to mmaptest.c, and then compile the code using,

gcc -o mmaptest mmaptest.c

Below are some sample execution,

./mmaptest 99

file size: 100

byte at offset 99 is 9

./mmaptest 2

file size: 100

byte at offset 2 is 2

./mmaptest 50

file size: 100

byte at offset 50 is 0

mmap can perform better than fseek, fread in certain cases. mmap can also be used to share file between different processes, which can reduce memory access significantly as it avoids loading the same file for each process.

Update 1: mmap can perform faster when dealing with big files. The normal read/write uses system call and frequent reads and writes cause lots of context switch between kernel space and user space. These context switches can be a significant overhead.

Update 2: mmap doesn’t load the entire file into memory. It adopts lazy access approach — when the data is needed, it is loaded into memory. This leads to another optimization for mmap based file accessing — pre-loading the content before the content is actually needed.

 

A Bug Caused by Overlooking Operators Precedence in C

Side Note: I’ve been thinking of writing blogs for bugs that have caused me hours to locate and fix for quite some time.

Sometimes I found myself making silly mistakes, sometimes I made same mistakes multiple times. Just like every other programmer, I spent lots of time locating bugs and fixing them. It’s worthwhile to note the mistake down and avoid making them again. So here comes the first one.

0. The Context
I’m developing an application that needs to read files using mmap. I code the part that mmap a file, but whenever I run the program, the mmap operation always give me “No Such Device” error.

1. Locate the Bug
I searched mmap Linux man page, the “No Such Device” error code means “The fildes parameter does not refer to a *TYPE2 stream file (*STMF) in the “root” (/), QOpenSys, or user-defined file systems.”

A couple of other articles discussed this bug, but I’m not making the same mistake as discussed in those articles.

As the application contains lots of code and difficult to debug, I decided to write a simple test program (actually I just found a mmap sample online and copied it).

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <unistd.h>

#include <sys/mman.h>

#include <sys/stat.h>

#include <errno.h>

 

int main(int argc, char *argv[])

{

    int fd, offset;

    char *data;

    struct stat sbuf;

    FILE *f;

 

    if (argc != 2) {

        fprintf(stderr, "usage: mmapdemo offsetn");

        exit(1);

    }

 

    f = fopen("./h1_1280_720_5m.mp4_mbstpos_gop1.txt", "w");

    fprintf(f, "sssssssssssssssssssssssssss");

    fflush(f);

    //this line will cause no such device error

    printf("fd: %dn", fd);

    if (fd = open("./h1_1280_720_5m.mp4_mbstpos_gop1.txt", O_RDONLY) == -1) {            //line caused bug

    //if ((fd = open("./h1_1280_720_5m.mp4_mbstpos_gop1.txt", O_RDONLY)) == -1) {            //correct source code

        perror("open");

        exit(1);

    }

    printf("fd: %dn", fd);

    if (stat("./h1_1280_720_5m.mp4_mbstpos_gop1.txt", &sbuf) == -1) {

        perror("stat");

        exit(1);

    }

    printf("file size: %ld", sbuf.st_size);

    offset = atoi(argv[1]);

    if (offset < 0 || offset > sbuf.st_size-1) {

        fprintf(stderr, "mmapdemo: offset must be in the range 0-%ldn", sbuf.st_size-1);

        exit(1);

    }

    

    data = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)    ;

    if (data == (-1)) {

        perror("mmap");

        exit(1);

    }

 

    printf("byte at offset %d is '%c'n", offset, data[offset]);

 

    return 0;

}

The test code works fine, I then compare the code with the mmap code from the app. I didn’t notice any difference. Then I started to replace the code from test code with the app code line by line (comments out the original code, copy app code over and change parameters. In this way, both the test code and app code are kept and I can compare them easily). The error appears! It’s good that I can reproduce the error. I know that’s the first step to locate the bug in lots of cases.

Then I compare the code line by line, and located the difference.

if (fd = open(“./h1_1280_720_5m.mp4_mbstpos_gop1.txt”, O_RDONLY) == -1)
if ((fd = open(“./h1_1280_720_5m.mp4_mbstpos_gop1.txt”, O_RDONLY)) == -1)

2. The Reason and Fix

Once I located the bug, I almost know why this occurs. It must due to the precedence of “=” and “==” operators. I don’t remember the detail, so I googled it.

“==” operator has hight precedence than “=” operator. So in the app code, the open method return value is compared with -1 first, and the comparison result is assigned to fd. If the file is opened successfully, open method return values won’t equal to -1, the comparison result would be 0 (false). I then added some printf statement to confirm the reasoning.

Once the reason is found, fixing the bug is easy.

3. How to Avoid Such Bugs

I actually once read a programming suggestion that we should use parenthesis to indicate the order of evaluation in a compound statement. I agreed and followed most of the time.

Sometimes it can be painful to count the number of parenthesis as the statement is really complicated. Maybe that’s why I didn’t follow the practice so strictly.

The bug took me around 1.5 hours to fix and another 45 minutes to note it down. I’ve paid my price and I should remember to use parenthesis to indicate the execution order clearly, even they’re ugly sometimes. If the statement is too complex, we can always break it down to multiple simple statements.

The lesson is: Make precedence explicit by Parenthesis!

References:
1. C Operator Precedence and Associativity: http://www.difranco.net/cop2220/op-prec.htm

How to Compile SQLite for Android using NDK

According to SQLite home page, SQLite is a open source software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine.

Self-contained means SQLite depends little on external libraries; serverless means SQLite doesn’t follow the client-server model that most other SQL database engines follow. SQLite reads and writes directly from the database files on disk. zero-configuraiton means SQLite is easy to deploy and set up; Transactional means all changes and queries are atomic, consistent, isolated and durable. Details of these terms can be found on SQLite home page at reference 0.

This post covers how to compile SQLite for using with native code. Currently Android only provides APIs to access SQLite database on SDK using Java. No NDK interface is publicly available. However, as SQLite is open source and self-contained, it’s possible to build an embedded version of SQLite for using with NDK.

0. Download SQLite Source Code
One can download the SQLite source code here. It’s easier to build the version with all C source code combined into a single file, so download the amalgamation version. Once downloaded, extract the source files to your Android project’s jni folder.

The source code consists of only four files, sqlite3.h, sqlite3.c, sqlite3ext.h, shell.c. If we want to build an embedded version of SQLite, we only need sqlite3.h and sqlite3.c. Shell.c is for building a command line utility to access SQLite database, sqlite3ext.h is for building extension for SQLite.

1. A Simple Example of Using SQLite
For simplicity, we provided a C program modified from SQLite website example, the code is as below,

#include <sqlite3.h>

 

static int callback(void *NotUsed, int argc, char **argv, char **azColName) {

    int i;

    for (i = 0; i < argc; ++i) {

        printf("%s = %sn", azColName[i], argv[i] ? argv[i] : "NULL");

    }

    printf("n");

    return 0;

}

int main(int argc, char **argv) {

    char create_table[100] = "CREATE TABLE IF NOT EXISTS customers (id INTEGER PRIMARY KEY,name TEXT NOT NULL)";

    char insert_value[100] = "INSERT INTO customers VALUES('1', 'roman10')";

    sqlite3 *db;

    char *errMsg;

    int rv;

    if (argc != 2) {

        printf("Usage: %s databasen", argv[0]);

        return 1;

    }

    rv = sqlite3_open(argv[1], &db);

    if (rv) {

        printf("Cannot open database: %sn", sqlite3_errmsg(db));

        sqlite3_close(db);

        return 1;

    }

    rv = sqlite3_exec(db, create_table, callback, 0, &errMsg);

    if (rv != SQLITE_OK) {

        printf("SQLite statement execution error: %sn", errMsg);

    }

    rv = sqlite3_exec(db, insert_value, callback, 0, &errMsg);

    if (rv != SQLITE_OK) {

        printf("SQLite statement execution error: %sn", errMsg);

    }

    sqlite3_close(db);

    return 0;

}

The code accepts a database name as input parameter. It first uses sqlite3_open to open (or create, if the database doesn’t exist) a database. It then execute two SQL query. The first one create a new table “customers” with columns “id” and “name”. The second SQL query insert a record with id = 0, name = “roman10” into the table “customers”.

2. Android.mk to Build the Example
To build the example for Android, you can use the Android.mk file below,

#LOCAL_PATH is used to locate source files in the development tree.

#the macro my-dir provided by the build system, indicates the path of the current directory

LOCAL_PATH:=$(call my-dir)

 

#####################################################################

#            build sqlite3                                            #

#####################################################################

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(LOCAL_PATH)/sqlite-amalgamation-3070900

LOCAL_MODULE:=sqlite3

LOCAL_SRC_FILES:=sqlite-amalgamation-3070900/sqlite3.c

include $(BUILD_STATIC_LIBRARY)

#include $(BUILD_SHARED_LIBRARY)

 

 

#####################################################################

#            build our code                    #

#####################################################################

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(LOCAL_PATH)/sqlite-amalgamation-3070900

LOCAL_MODULE:=sqlitetest

LOCAL_SRC_FILES:=sqlite_test.c

LOCAL_STATIC_LIBRARIES:=libsqlite3

#LOCAL_SHARED_LIBRARIES:=libsqlite3

LOCAL_LDLIBS:=-llog -lm

#include $(BUILD_SHARED_LIBRARY)

include $(BUILD_EXECUTABLE)

Note that the above build file builds the sqlite as static library, you can also build it as shared library.

Also note that the example illustrates how to build executable using SQLite, you can also call sqlite API in your JNI method, and provide an interface for your Java code to access the SQLite APIs you have embedded.

3. Run the Code
The compiled sqlitetest program should be found under your Android project’s libs/armabi-* folder. You can use adb push to push the executable to your phone. And you might want to change the permission of the sqlitetest to executable. Note that this operation need rooted device.

But root is not required to build SQLite and provide database access through JNI. It’s the limitation of the example provided here. If you don’t have a rooted device, just study the code and build scripts and I believe you can still get the idea.

Below is a screenshot of running sqlitetest program we compiled under Android,

Figure 1. Execution of the Sqlitetest Program

References:
0. SQLite home page: http://www.sqlite.com/
1. An Introduction to SQLite C/C++ Interface: http://www.sqlite.org/cintro.html

Simple TCP Socket Client and Server Communication in C Under Linux

This post doesn’t provide details about how Linux socket works, its design etc. It mainly for providing source code of simple TCP socket client and server in C. I’m writing this because I found myself need simple TCP client and server for testing from time to time. 🙂
1. The TCP Server Code

You can refer to TCP Server code below (save it as tcpserver.c),

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/types.h> 

#include <sys/socket.h>

#include <netinet/in.h>

 

void nonblock(int sockfd)

{

    int opts;

    opts = fcntl(sockfd, F_GETFL);

    if(opts < 0)

    {

        fprintf(stderr, "fcntl(F_GETFL) failedn");

    }

    opts = (opts | O_NONBLOCK);

    if(fcntl(sockfd, F_SETFL, opts) < 0) 

    {

        fprintf(stderr, "fcntl(F_SETFL) failedn");

    }

}

 

int main(int argc, char *argv[])

{

     int BUFLEN = 2000;

     int sockfd, newsockfd, portno;

     socklen_t clilen;

     char buffer[BUFLEN];

     struct sockaddr_in serv_addr, cli_addr;

     int n, i;

     int one = 1;

 

     if (argc < 2) {

         fprintf(stderr,"please specify a port numbern");

         exit(1);

     }

     sockfd = socket(AF_INET, SOCK_STREAM, 0);

     if (sockfd < 0) {

        perror("ERROR create socket");

        exit(1);

     }

     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);    //allow reuse of port

     //bind to a local address

     bzero((char *) &serv_addr, sizeof(serv_addr));

     portno = atoi(argv[1]);

     serv_addr.sin_family = AF_INET;

     serv_addr.sin_addr.s_addr = INADDR_ANY;

     serv_addr.sin_port = htons(portno);

     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {

        perror("ERROR on bind");

        exit(1);

     }

     //listen marks the socket as passive socket listening to incoming connections, 

     //it allows max 5 backlog connections: backlog connections are pending in queue

     //if pending connections are more than 5, later request may be ignored

     listen(sockfd,5);

     //accept incoming connections

     clilen = sizeof(cli_addr);

     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

     //nonblock(newsockfd);        //if we want to set the socket as nonblock, we can uncomment this

     if (newsockfd < 0) {

        perror("ERROR on accept");

        exit(1);

     }

     printf("connection acceptedn");

     for (i = 0; i < 5; ++i) {

         bzero(buffer,BUFLEN);

         n = read(newsockfd,buffer,BUFLEN);

         if (n < 0) {

            perror("ERROR read from socket");

         }

         printf("received: %s",buffer); 

         n = write(newsockfd, buffer, n);

         printf("sent: %s", buffer);

         if (n < 0) {

            perror("ERROR write to socket");

         }

     }

     close(newsockfd);

     close(sockfd);

     return 0; 

}

The code first create a socket of SOCK_STREAM type in AF_INET domain. SOCK_STREAM corresponds to TCP, and AF_INET refers to IPv4.

It calls setsockopt to make the socket resuable. For example, your server open up a socket at a port number, and then it exits. Without this line of code, sometimes you may not bind the socket to same port.

The program then binds the socket to a local IP address with a specific port number. listen(sockfd, 5) will set the socket as passive socket listening to incoming connections. 5 means the maximum number of backlog is 5. Backlog connections are pending connect request in queue. If pending request are more than 5, later request may be ignored.

The code then calls accept method to accept incoming connections. This is a block call, and it returns when a new connect request is received, or an error occurred.

In the for loop, the tcp server listens to incoming packets and echo the message back. Note that the nonblock(newsockfd) has been commented out. You can uncomment it to enable nonblock read and write, but you may want to modify the read and write part to make it work properly.

2. The TCP Client Code
The TCP client code is as below (save it as tcpclient.c),

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h> 

 

void nonblock(int sockfd)

{

    int opts;

    opts = fcntl(sockfd, F_GETFL);

    if(opts < 0)

    {

        fprintf(stderr, "fcntl(F_GETFL) failedn");

    }

    opts = (opts | O_NONBLOCK);

    if(fcntl(sockfd, F_SETFL, opts) < 0) 

    {

        fprintf(stderr, "fcntl(F_SETFL) failedn");

    }

}

 

int main(int argc, char *argv[])

{

    int BUFLEN = 2000;

    int sockfd, portno, n;

    struct sockaddr_in serv_addr;

    struct hostent *server;

    int i;

 

    char buffer[BUFLEN];

    if (argc < 3) {

       fprintf(stderr,"usage: %s hostname_or_ip portn", argv[0]);

       exit(0);

    }

    portno = atoi(argv[2]);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0) {

        perror("ERROR creating socket");

        exit(1);

    }

    //get the address info by either host name or IP address

    server = gethostbyname(argv[1]);

    if (server == NULL) {

        fprintf(stderr,"ERROR, no such hostn");

        exit(1);

    }

    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

    serv_addr.sin_port = htons(portno);

    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)  {

        perror("ERROR connecting");

        exit(1);

    }

    printf("connection establishedn");

    //nonblock(sockfd);    //uncomment this line if we want to make the socket non-block

    for (i = 0; i < 5; ++i) {

        printf("Please enter the message: ");

        bzero(buffer,BUFLEN);

        fgets(buffer,BUFLEN,stdin);

        n = write(sockfd,buffer,strlen(buffer));

        printf("sent: %s", buffer);

        if (n < 0) {

             perror("ERROR writing to socket");

        }

        bzero(buffer,BUFLEN);

        n = read(sockfd,buffer,BUFLEN);

        if (n < 0) {

             perror("ERROR reading from socket");

        }

        printf("received: %s",buffer);

    }

    close(sockfd);

    return 0;

}

The code creates a TCP socket. It then tries to connect to a server address with specified IP and port number. The connect is a block call, it returns when the connection is established, which means it receives the ACK from tcp server, which is third packet of TCP 3-way handshake (SYN, ACK+SYN, ACK).

In the loop the tcp client sends and receives messages. Also the nonblock code has been disabled.

3. Compile and Run
To compile the code, use the commands below,

gcc -o client tcpclient.c
gcc -o server tcpserver.c

A sample run could be,

./server 12345 (at one terminal)
./client localhost 12345 (at another terminal)

Simple File Uploading using PHP

This is my first post for PHP, a server-side scripting language widely used for web development. As I’m new to this language, the techniques may sounds naive. 🙂

To receive file uploaded through http, you can use the PHP script below (let’s call it receive.php),

<?php

    ini_set('display_errors', 'On');

    error_reporting(E_ALL);

    $target_path = "./upload/";

    $target_path = $target_path . basename( $_FILES['myfile']['name']); 

    echo $target_path;

    if(move_uploaded_file($_FILES['myfile']['tmp_name'], $target_path)) {

        echo "The file ".  basename( $_FILES['myfile']['name']). 

        " has been uploaded";

    } else{

        echo "There was an error uploading the file, please try again!";

    }

?>

PHP does a lot of things for you and keep the interface simple. For file uploading, it will save the received the file data to a temporary file. The temporary file is going to be removed at the end of execution of the script. To get the file, one needs to use move_uploaded_file.

move_uploaded_file method takes two parameters, the temporary file and the destination. The temporary file name can be retrieved using $_FILES[‘myfile’][‘tmp_name’], where myfile is the name of of the name of the file input type you defined in your html page. The code above construct the target_path as the upload folder + the uploaded file name.

The first two lines enable the error reporting. It’s convenient for debugging.
To test the code, one can use the following html page (let’s call it test.html),

<html>

<body>

<form action="receive.php" method="post"

enctype="multipart/form-data">

<input type="file" name="myfile"><br>

<br />

<input type="submit" name="submit" value="Submit" />

</form>

</body>

</html>

The html page declares an input of file type with name “myfile”. It uses html post message to upload the file, and the file data is encrypted using multipart. We indicates receive.php to handle the post message.

If you have your testing web server set up with php configured properly. You can place the receive.php and test.html files into the web directory. Create a upload folder with proper permission. And open up test.html page in a browser as shown below,

Figure 1. Upload Test Page Interface

You can browse for a file and click submit, then the file upload will be handled by receive.php.

Figure 2. Upload Result Page

Note that the html page and php scripts are for illustration and study only. The actually production script should consider a lot of other stuff, like error handling, security etc.

How to Build and Use libnetfilter_queue for Android

If you’re looking for general information about how to use libnetfilter_queue for Linux, please refer here.

0. Preparation
First, you’ll need to check if your Android system kernel is compiled with support for libentfilter_queue. Follow the following steps,

  • Connect your android device to your computer.
  • Enter command “adb pull /proc/config.gz” to get the config.gz file from your android device.
  • Extract config.gz file, you’ll get a file named config. This is actually your Android Linux kernel build configuration file.
  • Search for CONFIG_NETFILTER_ADVANCED, CONFIG_NETFITLER_NETLINK and CONFIG_NETFILTER_NETLINK_QUEUE in config file, make sure they’re not commented out.

If your Android build is not compiled with these features, you’ll need to compile customized kernel build to use libnetfilter_queue.

Next you’ll need to root your Android device. This is not the focus of this post, so it’s not covered here. But you can find lots of information online.

Thirdly, make sure your phone has iptables program. iptables program is used to configure the kernel packet filter table. Follow the command below to check,

adb shell

su

iptables –list

If the terminal doens’t complain about program not found, then you have iptables installed. If you don’t have iptables installed on your Android device, you may consider install busybox, or compile your own iptables program. I checked out the Android source code tree, it includes iptables in the external folder. So it should be doable to build on your own.

1. Build the Libraries and Test Executable
libnetfilter_queue depends on libnfnetlink, so we’ll need to download both libraries from here and here. After downloading, extract the libraries to your Android project jni folder.
Copy the nfqnl_test.c file from libnetfilter_queue-1.0.0/utils/ folder to jni folder. And create a Android.mk file with the content below,

#LOCAL_PATH is used to locate source files in the development tree.

#the macro my-dir provided by the build system, indicates the path of the current directory

LOCAL_PATH:=$(call my-dir)

 

#####################################################################

#            build libnflink                    #

#####################################################################

include $(CLEAR_VARS)

LOCAL_MODULE:=nflink

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink-1.0.0/include

LOCAL_SRC_FILES:=

    libnfnetlink-1.0.0/src/iftable.c 

    libnfnetlink-1.0.0/src/rtnl.c 

    libnfnetlink-1.0.0/src/libnfnetlink.c

include $(BUILD_STATIC_LIBRARY)

#include $(BUILD_SHARED_LIBRARY)

 

#####################################################################

#            build libnetfilter_queue            #

#####################################################################

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink-1.0.0/include 

    $(LOCAL_PATH)/libnetfilter_queue-1.0.0/include

LOCAL_MODULE:=netfilter_queue

LOCAL_SRC_FILES:=libnetfilter_queue-1.0.0/src/libnetfilter_queue.c

LOCAL_STATIC_LIBRARIES:=libnflink

include $(BUILD_STATIC_LIBRARY)

#include $(BUILD_SHARED_LIBRARY)

 

#####################################################################

#            build our code                    #

#####################################################################

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink-1.0.0/include 

    $(LOCAL_PATH)/libnetfilter_queue-1.0.0/include

LOCAL_MODULE:=nfqnltest

LOCAL_SRC_FILES:=nfqnl_test.c

LOCAL_STATIC_LIBRARIES:=libnetfilter_queue

LOCAL_LDLIBS:=-llog -lm

#include $(BUILD_SHARED_LIBRARY)

include $(BUILD_EXECUTABLE)

Then issue “ndk-build” command to build the libraries and executable nfqnltest.

Note that you’ll probably encounter an error “undefined reference to __fswab64”. This is an known issue as indicated here. Just apply the patch (or change according to the patch) to your NDK header file (platforms/android-9/arch-arm/usr/include/linux/byteorder/swab.h, replace “android-9” in the path with your targeted android version). It will resolve the build error.

2. Running the Code on Android
Follow the command below to copy and executable to your Android device and run it,

  • adb shell
  • su
  • mkdir /data/data/nfqnltest
  • chmod 777 /data/data/nfqnltest
  • Open another terminal. Go to libs/<armeabi*> folder of your Android project. Issue command “adb push nfqnltest /data/data/nfqnltest/”
  • Switch back to first terminal, “cd /data/data/nfqnltest”
  • ./nfqnltest

To configure iptables rules, you can open a new terminal, then follow the command below,

adb shell

su

iptables -A OUTPUT -p tcp -j NFQUEUE –queue-num 0

Then in terminal you’re running nfqnltest, you can see the program outputs. If you open browser app on your phone, and try to open google.com. You’ll see some packet information displayed,

pkt received

…….

hw_protocol=0x0000 hook=3 id=0 outdev=12 payload_len=288

entering callback

pkt received

hw_protocol=0x0000 hook=3 id=1 outdev=12 payload_len=869

entering callback

With libnetfilter_queue, you can do a lot of interesting stuff, like user space NATing, packet sniffing/capturing etc.