Sun ONE logo     Previous     Contents     Index     Next     
Sun ONE Messaging and Collaboration Event Notification Service Manual



Chapter 4   Sun ONE Calendar Server Specific Information


This chapter describes the Sun™ ONE Calendar Server specific items you need to use the ENS APIs.

This chapter contains these sections:



Sun ONE Calendar Server Notifications

There are two parts to the format of an Sun ONE Calendar Server notification:

  • The event reference - A URL identifying the event.

  • The payload - The data describing the event. Three different payload formats are supported: binary, text/calendar, and text/XML.

There are two types of calendar notifications: alarm notifications, which relay reminders; and calendar update notifications, which distribute changes to the calendar database.


Alarm Notifications

Alarm notifications notifications relay reminders. They are published by the csadmind daemon whenever it wants to send a reminder. The default subscriber for these alarms in Sun ONE is the csnotifyd daemon. Notifications consumed by csnotifyd have a binary payload and are acknowledged (reliable).

Additionally, the server can be configured to generate one additional notification for each reminder, which can be consumed by a third party notification infrastructure.

Table 4-1 has information on how the two different alarm notifications are enabled, their base event URLs, and the event payload format for each. (See "Format of Calendar Notifications".)


Table 4-1    Alarm Notifications

Type

Enabled by

Base Event URL

Event Payload Format

Default alarm notification  

Default  

enp:///ics/alarms  

Binary  

Optional alarm notification  

In ics.conf, the existence of a non-null value for
caldb.serveralarms.
contenttype

enables the optional alarm notification.
 

Set the ics.conf file parameter
caldb.serveralarms.
url

to this value: enp:///ics/alarms
 

Set the ics.conf file parameter
caldb.serveralarms.
contenttype
to one of these values: text/calendar or text/xml
 

Event URL parameters are the same for either one:

  • calid - Calendar ID

  • uid - Component, either event or todo (task) ID

  • rid - Recurrence ID

  • aid - Alarm ID

  • comptype - An event or a todo (task)


Calendar Update Notifications

Calendar update notifications distribute changes to the calendar database. They are published by the cshttpd or csdwpd daemons whenever a change is made to the database (if the notification is enabled for this type of change).

Table 4-2 lists each type of calendar update notification, and the ics.conf setting and base even URL for each of them.


Table 4-2    Calendar Update Notifications  

Types

Enabling ics.conf Parameters
(all parameters default to "yes" unless otherwise noted)

Base Event URL and Value
or Event Payload

Attendee refesh actions  

caldb.berkeleydb.ensmsg.
refreshevent

default=no  

caldb.berkeleydb.ensmsg.
refreshevent.url

default value:
enp:///ics/caleventrefresh
 

Attendee refresh action  

caldb.berkeleydb.ensmsg.
refreshevent.contenttype
 

Event payload default value: text/xml  

Attendee reply action  

caldb.berkeleydb.ensmsg.
replyevent

default=no  

caldb.berkeleydb.ensmsg.
replyevent.url

default value:
enp:///ics/caleventreply
 

Attendee reply action  

caldb.berkeleydb.ensmsg
replyevent.contenttype
 

Event payload default value: text/xml  

Calendar creation  

caldb.berkeleydb.ensmsg.createcal  

caldb.berkeleydb.ensmsg.
createcal.url

default value:
enp:///ics/calendarcreate
 

Calendar deletion  

caldb.berkeleydb.ensmsg.deletecal  

caldb.berkeleydb.ensmsg.
deletecal.url

default value:
enp:///ics/calendardelete
 

Calendar modification  

caldb.berkeleydb.ensmsg.modifycal  

caldb.berkeleydb.ensmsg.
modifycal.url

default value:
enp:///ics/calendarmodify
 

Event creation  

caldb.berkeleydb.ensmsg.
createevent
 

caldb.berkeleydb.ensmsg.
createevent.url

default value:
enp:///ics/caleventcreate
 

Event modification  

caldb.berkeleydb.ensmsg.
modifyevent
 

caldb.berkeleydb.ensmsg.
modifyevent.url

default value:
enp:///ics/caleventmodify
 

Event deletion  

caldb.berkeleydb.ensmsg.
deleteevent
 

caldb.berkeleydb.ensmsg.
deleteevent.url

default value:
enp:///ics/caleventdelete
 

Todo (task) creation  

caldb.berkeleydb.ensmsg.
createtodo
 

caldb.berkeleydb.ensmsg.
createtodo.url

default value:
enp:///ics/caltodocreate
 

Todo (task) modification  

caldb.berkeleydb.ensmsg.
modifytodo
 

caldb.berkeleydb.ensmsg.
modifytodo

default value:
enp:///ics/caltodomodify
 

Todo (task) deletion  

caldb.berkeleydb.ensmsg.
deletetodo
 

caldb.berkeleydb.ensmsg.
deletetodo.url

default value:
enp:///ics/caltododelete
 

Event URL parameters include:

  • calid - Calendar ID

  • uid - Component, either event or todo (task) ID

  • rid - Recurrence ID


Format of Calendar Notifications

There are two parts to a notification:

  • Event reference - URL identifying the event.

  • Payload - Data describing the event. Three data formats are supported: binary, text/calendar, text/XML.


Advanced Topics

Normally, ENS notifications for attendee replies and organizer refreshes are published to the caldb.berkeleydb.ensmsg.modifyevent topic along with other modifications. By setting the ics.conf variable caldb.berkeleydb.ensmsg.advancedtopics to "yes" (the default is "no"), the ENS notifications can be published to separate modify, reply and refresh topics. This allows the consumer of the notification to understand more precisely what type of transaction triggered the notification.

Table 4-3 shows the topics ENS publishes notifications to depending on the setting of the ics.conf variable caldb.berkeleydb.ensmsg.advancedtopics.

Table 4-3    Advanced Topics Variable

Value of ics.conf Variable caldb.berkeleydb.ensmsg.advancedtopics

Topics to Which ENS Publishes Attendee Notifications

yes  

caldb.berkeleydb.ensmsg.modifyevent
caldb.berkeleydb.ensmsg.refreshevent
caldb.berkeleydb.ensmsg.replyevent
 

no  

caldb.berkeleydb.ensmsg.modifyevent  


WCAP appid parameter and X-Tokens

When ENS sends out notifications of modifications made to existing events, it returns two X-Tokens with the notification, X-NSCP-COMPONENT-SOURCE and X-NSCP-TRIGGERED-BY.

The contents of the X-NSCP-COMPONENT-SOURCE X-Token varies depending on who originated the event and the absence or presence of the appid parameter in the original WCAP command that requested the event.

If the appid parameter is present in the original WCAP command, ENS returns its value in the X-NSCP-COMPONENT-SOURCE X-Token.(Only certain commands take the appid parameter. See the Sun ONE Calendar Server Programmer's Manual for further information on the appid parameter.) Using this mechanism, applications can "tag" ENS notifications in order to detect which ones it originated. The value of the appid command is a character string of the application's choosing. If the appid parameter is missing, standard values are assigned to the X-Token depending on the origin, see Table 4-4 that follows for the standard values).

The X-Token, X-NSCP-TRIGGERED-BY holds the name (uid) of the organizer or attendee that triggered the notification regardless of the absence or presence of the appid parameter.

Table 4-4 shows the effect of the presence of the appid parameter in WCAP commands on the value of the X-Token X-NSCP-COMPONENT-SOURCE.

Table 4-4    Presence of appid and Value of X-Token X-NSCP-COMPONENT-SOURCE

appid Present?

Value of X-Token X-NSCP-COMPONENT-SOURCE (with Request Origin)

no  

Standard Values:
WCAP (default)
CALENDAR EXPRESS (from UI)
ADMIN (from Admin tools)
 

yes  

Value of appid  



Sun ONE Calendar Server Sample Code



Sun ONE Calendar Server ships with a complete ENS implementation. If you wish to customize it, you may use the ENS APIs to do so. The following four code samples, a simple publisher and subscriber pair, and a reliable publisher and subscriber pair, illustrate how to use the ENS API. The sample code is provided with the product in the following directory:

/opt/SUNWics5/cal/csapi/samples/ens


Sample Publisher and Subscriber

This sample code pair establishes a simple interactive asynchronous publisher and subscriber.


Publisher Code Sample

/*
 * Copyright 2000 by Sun Microsystems, Inc.
 * All rights reserved
 *
 * apub : simple interactive asynchronous publisher using
 *
 * Syntax:
 * apub host port
 */

#include <stdlib.h>
#include <stdio.h>

#include "pasdisp.h"
#include "publisher.h"

static pas_dispatcher_t *disp = NULL;
static publisher_t *_publisher = NULL;
static int _shutdown = 0;

static void _read_stdin();

static void _exit_usage()
{
   printf("\nUsage:\n   apub host port\n");
   exit(5);
}

static void _exit_error(const char *msg)
{
   printf("%s\n", msg);
   exit(1);
}

static void _call_shutdown()
{
   _shutdown = 1;
   pas_shutdown(disp);
}

static void _open_ack(void *arg, int rc, void *enc)
{
   _publisher = (publisher_t *)enc;
   (void *)arg;

   if (!_publisher)
   {
      printf("Failed to create publisher with status %d\n", rc);
      _call_shutdown();
      return;
   }

   _read_stdin();

   return;
}

static void _publish_ack(void *arg, int rc, void *ignored)
{
   (void *)ignored;

   free(arg);

   if (rc != 0)
   {

      printf("Publish failed with status %d\n", rc);

      _call_shutdown();

      return;
   }

   _read_stdin();

   return;
}

static void _read_stdin()
{

   static char input[1024];

   printf("apub> ");

   fflush(stdout);

   while (!_shutdown)
   {

      if ( !fgets(input, sizeof(input), stdin) )
      {
          continue;

      } else {
         char *message;
         unsigned int message_len;

         input[strlen(input) - 1] = 0; /* Strip off the \n */

         if (*input == '.' && input[1] == 0)
         {
            publisher_delete(_publisher);
            _call_shutdown();
            break;
         }

         message = strdup(input);
         message_len = strlen(message);
         publish(_publisher, "enp://yoyo.com/xyz",message,
                message_len,
                _publish_ack, NULL, (void *)message, 0);
         return;
      }
   }
   return;
}

main(int argc, char **argv)
{
   unsigned short port = 7997;
   char host[256];

   if (argc < 2) _exit_usage();

   if (*(argv[1]) == '0')
   {
      strcpy(host, "127.0.0.1");
   } else {
      strcpy(host, argv[1]);
   }

   if (argc > 2)
   {
      port = (unsigned short)atoi(argv[2]);
   }

   disp = pas_dispatcher_new(NULL);
   if (disp == NULL) _exit_error("Can't create publisher");

   publisher_new_a(disp, NULL, host, port, _open_ack, disp);

   pas_dispatch(disp);

   _shutdown = 1;

   pas_dispatcher_delete(disp);

   exit(0);
}


Subscriber Code Sample

/*
 * Copyright 1997 by Sun Microsystems, Inc.
 * All rights reserved
 *
 * asub : example asynchronous subscriber
 *
 * Syntax:
 * asub host port
 */

#include <stdlib.h>
#include <stdio.h>

#include "pasdisp.h"
#include "subscriber.h"

static pas_dispatcher_t *disp = NULL;
static subscriber_t *_subscriber = NULL;
static subscription_t *_subscription = NULL;
static renl_t *_renl = NULL;

static void _exit_usage()
{
   printf("\nUsage:\n   asub host port\n");
   exit(5);
}

static void _exit_error(const char *msg)
{
   printf("%s\n", msg);
   exit(1);
}

static void _subscribe_ack(void *arg, int rc, void *subscription)
{
   (void)arg;

   if (!rc)
   {
      _subscription = subscription;
      printf("Subscription successful\n");
   } else {
      printf("Subscription failed - status %d\n", rc);
      pas_shutdown(disp);
   }
}

static void _unsubscribe_ack(void *arg, int rc, void *ignored)
{
   (void *)ignored;
   (void *)arg;

   if (rc != 0)
   {
      printf("Unsubscribe failed - status %d\n", rc);
   }

   subscriber_delete(_subscriber);
   pas_shutdown(disp);
}

static int _handle_notify(void *arg, char *url, char *str, int len)
{
   (void *)arg;
   printf("[%s] %.*s\n", url, len, (str) ? str : "(null)");
   return 0;
}

static void _open_ack(void *arg, int rc, void *enc)
{
   _subscriber = (subscriber_t *)enc;

   (void *)arg;
   if (rc)
   {
      printf("Failed to create subscriber with status %d\n", rc);
      pas_shutdown(disp);
      return;
   }

   subscribe(_subscriber, "enp://yoyo.com/xyz",
            _handle_notify, NULL,
            _subscribe_ack, NULL);

   return;
}

static void _unsubscribe(int sig)
{
   (int)sig;
   unsubscribe(_subscriber, _subscription, _unsubscribe_ack, NULL);
}

main(int argc, char **argv)
{
   unsigned short port = 7997;
   char host[256];

   if (argc < 2) _exit_usage();
   if (*(argv[1]) == '0')
   {
      strcpy(host, "127.0.0.1");
   } else {
      strcpy(host, argv[1]);
   }
   if (argc > 2)
   {
      port = (unsigned short)atoi(argv[2]);
   }

   disp = pas_dispatcher_new(NULL);
   if (disp == NULL) _exit_error("Can't create publisher");

   subscriber_new_a(disp, NULL, host, port, _open_ack, NULL);

   pas_dispatch(disp);

   pas_dispatcher_delete(disp);

   exit(0);
}


Reliable Publisher and Subscriber

This sample code pair establishes a reliable asynchronous publisher and subscriber.


Reliable Publisher Sample

/*
 * Copyright 2000 by Sun Microsystems, Inc.
 * All rights reserved
 *
 * rpub : simple *reliable* interactive asynchronous publisher.
 *    It is designed to be used in combination with rsub,
 *    the reliable subscriber.
 *
 * Syntax:
 * rpub host port
 */

#include <stdlib.h>
#include <stdio.h>

#include "pasdisp.h"
#include "publisher.h"

static pas_dispatcher_t *disp = NULL;
static publisher_t *_publisher = NULL;
static int _shutdown = 0;
static renl_t *_renl;

static void _read_stdin();

static void _exit_usage()
{

   printf("\nUsage:\n   rpub host port\n");

   exit(5);
}

static void _exit_error(const char *msg)
{
   printf("%s\n", msg);
   exit(1);
}

static void _call_shutdown()
{
   _shutdown = 1;
   pas_shutdown(disp);
}

static void _renl_create_cb(void *arg, int rc, void *ignored)
{
   (void *)arg;
   (void *)ignored;

   if (!_publisher)
   {
      printf("Failed to create RENL - status %d\n", rc);
      _call_shutdown();
      return;
   }

   _read_stdin();

   return;
}

static void _publisher_new_cb(void *arg, int rc, void *enc)
{
   _publisher = (publisher_t *)enc;

   (void *)arg;

   if (!_publisher)
   {
      printf("Failed to create publisher - status %d\n", rc);
      _call_shutdown();
      return;
   }

   renl_create_publisher(_publisher, "renl_id", NULL,
                       _renl_create_cb,NULL);

   return;
}

static void _recv_ack(void *arg, int rc, void *ignored)
{
   (void *)ignored;

   if (rc < 0)
   {
      printf("Acknowledgment Timeout\n");
   } else if ( rc == 0) {
      printf("Acknowledgment Received\n");
   }
   fflush (stdout);

   _read_stdin();

   free(arg);

   return;
}

static void _read_stdin()
{
   static char input[1024];

   printf("rpub> ");
   fflush(stdout);
   while (!_shutdown)
   {
      if ( !fgets(input, sizeof(input), stdin) )
      {
         continue;
      } else {
         char *message;
         unsigned int message_len;

         input[strlen(input) - 1] = 0; /* Strip off the \n */

         if (*input == '.' && input[1] == 0)
         {
            publisher_delete(_publisher);
            _call_shutdown();
            break;
         }

         message = strdup(input);
         message_len = strlen(message);

         /* five seconds timeout */
         publish(_publisher, "enp://yoyo.com/xyz",
                message, message_len,
                NULL, _recv_ack, message, 5000);

         return;
      }
   }
   return;
}

main(int argc, char **argv)
{
   unsigned short port = 7997;
   char host[256];

   if (argc < 2) _exit_usage();
   if (*(argv[1]) == '0')
   {
      strcpy(host, "127.0.0.1");
   } else {
      strcpy(host, argv[1]);
   }
   if (argc > 2)
   {
      port = (unsigned short)atoi(argv[2]);
   }

   disp = pas_dispatcher_new(NULL);
   if (disp == NULL) _exit_error("Can't create publisher");

   publisher_new_a(disp, NULL, host, port, _publisher_new_cb,
                 NULL);

   pas_dispatch(disp);

   _shutdown = 1;

   pas_dispatcher_delete(disp);

   exit(0);
}


Reliable Subscriber Sample

/*
 * Copyright 1997 by Sun Microsystems, Inc.
 * All rights reserved
 *
 * asub : example asynchronous subscriber
 *
 * Syntax:
 * asub host port
 */

#include <stdlib.h>
#include <stdio.h>

#include "pasdisp.h"
#include "subscriber.h"

static pas_dispatcher_t *disp = NULL;
static subscriber_t *_subscriber = NULL;
static subscription_t *_subscription = NULL;
static renl_t *_renl = NULL;

static void _exit_usage()
{
   printf("\nUsage:\n   asub host port\n");
   exit(5);
}

static void _exit_error(const char *msg)
{
   printf("%s\n", msg);
   exit(1);
}

static void _subscribe_ack(void *arg, int rc, void *subscription)
{
   (void)arg;

   if (!rc)
   {
      _subscription = subscription;
      printf("Subscription successful\n");
      _renl = renl_create_subscriber(_subscription, "renl_id", NULL);
   } else {
      printf("Subscription failed - status %d\n", rc)
      pas_shutdown(disp);
   }
}

static void _unsubscribe_ack(void *arg, int rc, void *ignored)
{
   (void *)ignored;
   (void *)arg;

   if (rc != 0)
   {
      printf("Unsubscribe failed - status %d\n", rc);
   }

   subscriber_delete(_subscriber);
   pas_shutdown(disp);
}

static int _handle_notify(void *arg, char *url, char *str, int len)
{
   (void *)arg;
   printf("[%s] %.*s\n", url, len, (str) ? str : "(null)");
   return 0;
}

static void _open_ack(void *arg, int rc, void *enc)
{
   _subscriber = (subscriber_t *)enc;

   (void *)arg;
   if (rc)
   {
      printf("Failed to create subscriber with status %d\n", rc);
      pas_shutdown(disp);
      return;
   }

   subscribe(_subscriber, "enp://yoyo.com/xyz",_handle_notify,
            NULL,_subscribe_ack, NULL);

   return;
}

static void _unsubscribe(int sig)
{
   (int)sig;
   unsubscribe(_subscriber, _subscription, _unsubscribe_ack, NULL);
}

main(int argc, char **argv)
{
   unsigned short port = 7997;
   char host[256];

   if (argc < 2) _exit_usage();
   if (*(argv[1]) == '0')
   {
      strcpy(host, "127.0.0.1");
   } else {
      strcpy(host, argv[1]);
   }
   if (argc > 2)
   {
      port = (unsigned short)atoi(argv[2]);

   }

   disp = pas_dispatcher_new(NULL);

   if (disp == NULL) _exit_error("Can't create publisher");

   subscriber_new_a(disp, NULL, host, port, _open_ack, NULL);

   pas_dispatch(disp);

   pas_dispatcher_delete(disp);

   exit(0);

}


Previous     Contents     Index     Next     
Copyright 2002 Sun Microsystems, Inc. All rights reserved.

Last Updated August 30, 2002