Tuesday, May 10, 2011

Android Cloud to Device Messaging(C2DM) Tutorial

This tutorial is for getting started with Android Cloud to Device Messaging (C2DM) on Android. In the iOS world it is knows as “push notifications”.

This feature will definitely help developers and their apps to streamline and optimize the data transfers. This would mean that apps now do not have to poll their servers at regular intervals to check for updates. The servers will be able to send updates (like Push Notifications) to the devices and makes it easier for mobile applications to sync data with servers.


There are many different ways of accomplishing the same thing(polling,constant server connections,SMS messages).

C2DM Alternatives:

Polling: The application itself would periodically poll your servers to check for new messages. You would need to implement everything from queuing messages to writing the polling code. Alerts are no good if they’re delayed due to a low polling period but the more frequently you poll, the more the battery is going to die.

SMS: Android can intercept SMS messages and you could include a payload to tell the application what to do. But then why not just use SMS in the first place? SMS is costly.

Persistent Connection: This would solve the problem of periodic polling but would destroy the battery life.

Cloud to device messaging 


“Android Cloud to Device Messaging (C2DM) is a service that helps developers send data from servers to their applications on Android devices. The service provides a simple, lightweight mechanism that servers can use to tell mobile applications to contact the server directly, to fetch updated application or user data. The C2DM service handles all aspects of queueing of messages and delivery to the target application running on the target device.”

It is a server push service provided by Google so that 3rd party applications can push messages to their applications on android devices.
Here are a few basic things to know about C2DM:
  1. It requires Android 2.2; C2DM uses Google services which are present on any device running the Android Market. 
  2. It uses existing connections for Google services. This requires the users to sign into their Google account on Android. 
  3. It allows 3rd party servers to send lightweight data messages to their apps. The C2DM service is not designed for pushing a lot of user content; rather it should be used like a “tickle”, to tell the app that there is new data on the server, so the app can fetch it. 
  4. An application doesn’t need to be running to receive data messages. The system will wake up the app via an Intent broadcast when the the data message arrives, so long as the app is set up with the proper Intent Receiver and permissions. 
  5. No user interface is required for receiving the data messages. The app can post a notification (or display other UI) if it desires.
Here is how it works:

To enable C2DM, an application on the device registers with Google and get a registration ID, and sends the ID to its server.

An Android application needs to register with C2DM servers before receiving any message. To register it needs to send an Intent (com.google.android.c2dm.intent.REGISTER), with 2 extra parameters:
  • sender is the ID of the account authorized to send messages to the application, typically the email address of an account set up by the application's developer.
  • app is the application's ID, set with a PendingIntent to allow the registration service to extract application information.
For example:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
registrationIntent.putExtra("sender", emailOfSender);
startService(registrationIntent);

The C2DM servers route the message to the device, and an Intent broadcast is sent to the app.

// Registration ID received via an Intent
public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();
  if (“com.google.android.c2dm.intent.REGISTRATION”.equals(action)) {
    handleRegistration(context, intent);
  }
}
public void handleRegistration(Context context, Intent intent) {
  String id = intent.getExtra(“registration_id”);
  if ((intent.getExtra(“error”) != null) {
    // Registration failed.  Try again later, with backoff.
  } else if (id != null) {
    // Send the registration ID to the app’s server.
    // Be sure to do this in a separate thread.
  }
}
The app can unregister with C2DM when the user no longer wants messages to be pushed to it.
Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
startService(unregIntent);

Friday, May 6, 2011

IPC:Shared Memory

Shared Memory

Shared Memory is an efficeint means of passing data between programs. One program will create a memory portion which other processes (if permitted) can access.

In the Solaris 2.x operating system, the most efficient way to implement shared memory applications is to rely on the mmap() function and on the system's native virtual memory facility. Solaris 2.x also supports System V shared memory, which is another way to let multiple processes attach a segment of physical memory to their virtual address spaces. When write access is allowed for more than one process, an outside protocol or mechanism such as a semaphore can be used to prevent inconsistencies and collisions.

A process creates a shared memory segment using shmget()|. The original owner of a shared memory segment can assign ownership to another user with shmctl(). It can also revoke this assignment. Other processes with proper permission can perform various control functions on the shared memory segment using shmctl(). Once created, a shared segment can be attached to a process address space using shmat(). It can be detached using shmdt() (see shmop()). The attaching process must have the appropriate permissions for shmat(). Once attached, the process can read or write to the segment, as allowed by the permission requested in the attach operation. A shared segment can be attached multiple times by the same process. A shared memory segment is described by a control structure with a unique ID that points to an area of physical memory. The identifier of the segment is called the shmid. The structure definition for the shared memory segment control structures and prototypews can be found in .

Accessing a Shared Memory Segment

shmget() is used to obtain access to a shared memory segment. It is prottyped by:

int shmget(key_t key, size_t size, int shmflg);
The key argument is a access value associated with the semaphore ID. The size argument is the size in bytes of the requested shared memory. The shmflg argument specifies the initial access permissions and creation control flags.

When the call succeeds, it returns the shared memory segment ID. This call is also used to get the ID of an existing shared segment (from a process requesting sharing of some existing memory portion).

The following code illustrates shmget():

#include
#include
#include

...

key_t key; /* key to be passed to shmget() */
int shmflg; /* shmflg to be passed to shmget() */
int shmid; /* return value from shmget() */
int size; /* size to be passed to shmget() */

...

key = ...
size = ...
shmflg) = ...

if ((shmid = shmget (key, size, shmflg)) == -1) {
perror("shmget: shmget failed"); exit(1); } else {
(void) fprintf(stderr, "shmget: shmget returned %d\n", shmid);
exit(0);
}
...
Controlling a Shared Memory Segment

shmctl() is used to alter the permissions and other characteristics of a shared memory segment. It is prototyped as follows:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
The process must have an effective shmid of owner, creator or superuser to perform this command. The cmd argument is one of following control commands:

SHM_LOCK
-- Lock the specified shared memory segment in memory. The process must have the effective ID of superuser to perform this command.
SHM_UNLOCK
-- Unlock the shared memory segment. The process must have the effective ID of superuser to perform this command.
IPC_STAT
-- Return the status information contained in the control structure and place it in the buffer pointed to by buf. The process must have read permission on the segment to perform this command.
IPC_SET
-- Set the effective user and group identification and access permissions. The process must have an effective ID of owner, creator or superuser to perform this command.
IPC_RMID
-- Remove the shared memory segment.
The buf is a sructure of type struct shmid_ds which is defined in

The following code illustrates shmctl():

#include
#include
#include

...

int cmd; /* command code for shmctl() */
int shmid; /* segment ID */
struct shmid_ds shmid_ds; /* shared memory data structure to
hold results */
...

shmid = ...
cmd = ...
if ((rtrn = shmctl(shmid, cmd, shmid_ds)) == -1) {
perror("shmctl: shmctl failed");
exit(1);
}
...
Attaching and Detaching a Shared Memory Segment

shmat() and shmdt() are used to attach and detach shared memory segments. They are prototypes as follows:

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);
shmat() returns a pointer, shmaddr, to the head of the shared segment associated with a valid shmid. shmdt() detaches the shared memory segment located at the address indicated by shmaddr

. The following code illustrates calls to shmat() and shmdt():

#include
#include
#include

static struct state { /* Internal record of attached segments. */
int shmid; /* shmid of attached segment */
char *shmaddr; /* attach point */
int shmflg; /* flags used on attach */
} ap[MAXnap]; /* State of current attached segments. */
int nap; /* Number of currently attached segments. */

...

char *addr; /* address work variable */
register int i; /* work area */
register struct state *p; /* ptr to current state entry */
...

p = &ap[nap++];
p->shmid = ...
p->shmaddr = ...
p->shmflg = ...

p->shmaddr = shmat(p->shmid, p->shmaddr, p->shmflg);
if(p->shmaddr == (char *)-1) {
perror("shmop: shmat failed");
nap--;
} else
(void) fprintf(stderr, "shmop: shmat returned %#8.8x\n",
p->shmaddr);

...
i = shmdt(addr);
if(i == -1) {
perror("shmop: shmdt failed");
} else {
(void) fprintf(stderr, "shmop: shmdt returned %d\n", i);

for (p = ap, i = nap; i--; p++)
if (p->shmaddr == addr) *p = ap[--nap];

}
...
Example two processes comunicating via shared memory: shm_server.c, shm_client.c

We develop two programs here that illustrate the passing of a simple piece of memery (a string) between the processes if running simulatenously:

shm_server.c
-- simply creates the string and shared memory portion.
shm_client.c
-- attaches itself to the created shared memory portion and uses the string (printf.
The code listings of the 2 programs no follow:

shm_server.c

#include
#include
#include
#include

#define SHMSZ 27

main()
{
char c;
int shmid;
key_t key;
char *shm, *s;

/*
* We'll name our shared memory segment
* "5678".
*/
key = 5678;

/*
* Create the segment.
*/
if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
perror("shmget");
exit(1);
}

/*
* Now we attach the segment to our data space.
*/
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}

/*
* Now put some things into the memory for the
* other process to read.
*/
s = shm;

for (c = 'a'; c <= 'z'; c++)
*s++ = c;
*s = NULL;

/*
* Finally, we wait until the other process
* changes the first character of our memory
* to '*', indicating that it has read what
* we put there.
*/
while (*shm != '*')
sleep(1);

exit(0);
}
shm_client.c

/*
* shm-client - client program to demonstrate shared memory.
*/
#include
#include
#include
#include

#define SHMSZ 27

main()
{
int shmid;
key_t key;
char *shm, *s;

/*
* We need to get the segment named
* "5678", created by the server.
*/
key = 5678;

/*
* Locate the segment.
*/
if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
perror("shmget");
exit(1);
}

/*
* Now we attach the segment to our data space.
*/
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}

/*
* Now read what the server put in the memory.
*/
for (s = shm; *s != NULL; s++)
putchar(*s);
putchar('\n');

/*
* Finally, change the first character of the
* segment to '*', indicating we have read
* the segment.
*/
*shm = '*';

exit(0);
}

How TOPT Works: Generating OTPs Without Internet Connection

Introduction Have you ever wondered how authentication apps like RSA Authenticator generate One-Time Passwords (OTPs) without requiring an i...