/****************************************************************
 *                                                              *
 *  LIBDIST V1.0						*
 *                                                              *
 *  libdist.h -- a library for distributed applications         *
 *                                                              *
 *  Last changed: 09.03.96                                      *
 *  Author: Frank Kargl (frank.kargl@informatik.uni-ulm.de)     *
 *                                                              *
 *  Restrictions: works only for Solaris 2.6 or above           *
 *                                                              *
 ****************************************************************/

#ifndef LIBDIST_H

#define LIBDIST_H

#include "config.h"

#include <unistd.h>		/* needed for everything ;-) */
#include <stdlib.h>		/* needed for everything ;-) */
#include <stdio.h>		/* needed for everything ;-) */
#include <thread.h>		/* for thread handling */
#include <sys/socket.h>		/* for socket routines */
#include <sys/types.h>		/* various datatypes */
#include <signal.h>		/* for signal handling */
#include <synch.h>		/* for semaphores and DSM */
#include <netinet/in.h>		/* for struct sockaddr_in */

/****************************************************************
 * PART ONE: thread handling                                    *
 ****************************************************************/

/***
 *** thread_t dl_thr_create(void *(*function)(void *),void *arg)
 ***
 *** Function: create a new thread starting with 'function'
 ***           that gets passed arg as argument
 *** Return  : thread identifier
 ***           DL_ERROR if error
 ***/

thread_t dl_thr_create(void *(*function)(void *),void *arg);

/***
 *** void dl_thr_exit(void)
 ***
 *** Function: exit the current thread
 *** Return  : -
 ***/

void dl_thr_exit(void);

/***
 *** int dl_thr_kill(thread_t thread, int sig)
 *** 
 *** Function: send signal 'sig' to thread 'thread'
 *** Return  : values != DL_OK indicate an error
 ***           DL_THR_NSS = no such signal
 ***           DL_THR_NST = no such thread
 ***/

int dl_thr_kill(thread_t thread,int sig);

/****************************************************************
 * PART TWO: communication primitives                           *
 ****************************************************************/

/***
 *** int dl_sck_getport(char *service,int type)
 ***
 *** Function: find the port number for an Internet service
 *** Return  : port number
 ***	       DL_ERROR if error
 ***/

int dl_sck_getport(char *service,int type);

/***
 *** int dl_sck_server(char *service, int type, void *(*function)(int *sock))
 ***
 *** Function: create a server socket of specified type
 ***           on the port that is specified by service
 ***           service may either be a number or a service name
 ***           according to services(4)
 ***	       when service is NULL, then don't do bind
 ***           when *function != NULL and type==DL_SCK_TCP
 ***           then dl_sck_server
 ***           accepts incoming requests, forks (a thread) and passes
 ***           the client socket to function
 ***           in this case dl_sck_server is an endless loop
 ***           if type==DL_SCK_UDP then function is ignored and
 ***           should be NULL
 *** Return  : the socket id
 ***           DL_ERROR if error
 ***/

int dl_sck_server(char *service, int type, void *(*function)(int *sock));

/***
 *** int dl_sck_connect(char *rem_ip, char *service, int type)
 ***
 *** Function: open a connection to a remote server
 ***           rem_ip may either be a dotted-decimal or
 ***           DNS style address string
 ***	       port is either a number or a name according to services(4)
 ***           type is analogous to dl_sck_server
 *** Return  : the socket id
 ***           DL_ERROR if error
 ***/

int dl_sck_connect(char *rem_ip, char *service, int type);

/***
 *** void dl_sck_close(int socket)
 ***
 *** Function: closes a socket connection
 *** Return  : -
 ***/

void dl_sck_close(int socket);

/***
 *** char *dl_sck_receive(int socket)
 ***
 *** Function: reads one line of text from 'socket'
 *** Return  : one textline stripped of any trailing <LF> or <CR><LF>
 ***           'eof' when end of connection reached
 ***           NULL indicates an error or eof
 ***           as the buffer for line is static the result
 ***           should be copied elsewhere before the next call
 ***           to dl_sck_receive
 ***/

char *dl_sck_receive(int socket);

/***
 *** char *dl_sck_recvtio(int socket,int timeout)
 ***
 *** Function: read a datagram from socket but with timeout (in usec)
 *** Return  : the datagram as string
 ***           NULL indicates an timeout
 ***           as the buffer for line is static the result
 ***           should be copied elsewhere before the next call
 ***           to dl_sck_recvtio
 ***/

char *dl_sck_recvtio(int socket, int timeout);

/***
 *** int dl_sck_send(int socket, char *line)
 ***
 *** Function: sends one line of text to 'socket'
 ***           <CR><LF> is autmatically added if not present
 ***           suited only for DL_SCK_TCP
 *** Return  : the number of characters sent
 ***           DL_ERROR if error
 ***/

int dl_sck_send(int socket, char *line);

/***
 *** int dl_sck_sockb(void);
 ***
 *** Function: open a broadcast socket
 *** Return  : the socket id
 ***           DL_ERROR if error
 ***/

int dl_sck_sockb(void);

/***
 *** int dl_sck_sendb(int socket, char *service, char *line)
 ***
 *** Function: send text to 'socket' as a broadcast
 ***           the port to use is specified by 'service'
 *** Return  : the number of characters sent
 ***           DL_ERROR indicates an error
 ***/

int dl_sck_sendb(int socket, char *service, char *line);

/***
 *** struct sockaddr_in *dl_sck_getifadr(void)
 ***
 *** Function: get the interface address of the current interface
 *** Return  : an Internet endpoint address
 ***           NULL indicates an error
 ***/

struct sockaddr_in *dl_sck_getifadr(void);

/****************************************************************
 * PART THREE: signal handling                                  *
 ****************************************************************/

/***
 *** void dl_sig_catch(int sig, void(*function)(int))
 ***
 *** Function: 'function' is called each time 'sig' is received
 ***           It isn't necessary to reinstall the
 ***           signal handler at the end
 *** Return  : -
 ***/

void dl_sig_catch(int sig, void(*function)(int));

/***
 *** void dl_sig_free(int sig)
 ***
 *** Function: 'sig' isn't caught anymore
 *** Return  : -
 ***/

void dl_sig_free(int sig);

/****************************************************************
 * PART FOUR: semaphores                                        *
 ****************************************************************/

/***
 *** sema_t *dl_sem_create(char *name,int value)
 ***
 *** Function: create (or search for) a semaphore 'name'
 ***           if name==NULL then a new semaphore with a random
 ***           name is created
 ***           if semaphore 'name' is created then it is
 ***           initialy set to 'val'
 ***           if semaphore 'name' allready exists then
 ***           ID is just returned and no further action
 ***           is taken
 ***           value should be zero in this case
 *** Return  : the semphore id
 ***           NULL if error
 *** Restrictions: Semaphores are only valid within
 ***               threads of the same process
 ***/

sema_t *dl_sem_create(char *name,int value);

/***
 *** void dl_sem_p(sema_t *sem)
 ***
 *** Function: P operation for 'sem'
 *** Return  : -
 ***/

void dl_sem_p(sema_t *sem);

/***
 *** void dl_sem_v(sema_t *sem)
 ***
 *** Function: V operation for 'sem'
 *** Return  : -
 ***/

void dl_sem_v(sema_t *sem);

/****************************************************************
 * PART FIVE: distributed shared memory (not yet implemented)   *
 ****************************************************************/

/***
 *** int dl_dsm_init(void)
 ***
 *** Function: start the dsm_server for this machine
 ***           should be done only once per machine
 *** Return  : DL_OK if ok
 ***           DL_ERROR if error
 ***/

int dl_dsm_init(void);

/*** void *dl_dsm_page(char *key, int timeout)
 ***
 *** Function: create a new page associated with 'key' or give access to an
 ***           existing one
 *** Return  : pointer to the shared memory segment
 ***           (void *)DL_ERROR if error
 *** Restrictions: only one page can be used, key is ignored
 ***/

void *dl_dsm_page(char *key, int timeout);

/*** 
 *** void dl_dsm_remove(char *key)
 ***
 *** Function: remove a shared memory segment from your use
 *** Return  : -
 *** Restrictions: only one page can be used, key is ignored
 ***/

void dl_dsm_remove(char *key);

/***
 *** void dl_dsm_end(void)
 ***
 *** Function: end all dsm activity for this machine
 *** Return  : stop the dsm_server
 ***/

void dl_dsm_end(void);

/****************************************************************
 * PART SIX: naming service                                     *
 ****************************************************************/

/***
 *** thread_t dl_ns_start(void)
 ***
 *** Function: start a name server on this machine
 *** Return  : the thread id of the nameserver
 ***           DL_ERROR if error
 ***/

thread_t dl_ns_start(void);

/***
 *** int dl_ns_enter(char *key, char *data)
 ***
 *** Function: send data identified by key to all nameservers
 *** Return  : values != 0 indicate an error
 ***           detailed return errors to be specified when needed
 *** Return  : DL_OK if successfull
 ***           DL_ERROR if error
 ***/

int dl_ns_enter(char *key, char *data);

/***
 *** char *dl_ns_retrieve(char *key)
 ***
 *** Function: retrieve the data associated with key from a nameserver
 *** Return  : nameserver entry if found
 ***           DL_ERROR if error
 ***           DL_NS_NOTFOUND if not found
 ***/

char *dl_ns_retrieve(char *key);

/***
 *** void dl_ns_dump(void)
 ***
 *** Function: dump the namespace
 *** Return  : -
 *** This is for debugging purposes only
 ***/
	  
void dl_ns_dump(void);

/***
 *** int dl_ns_delete(char *key)
 ***
 *** Function: delete the data associated with key from a nameserver
 *** Return  : DL_OK if successfull
 ***           DL_ERROR if error
 ***           DL_NS_NOTFOUND if not found
 ***/

int dl_ns_delete(char *key);

/****************************************************************
 * PART SEVEN: election algorithm                               *
 ****************************************************************/

/***
 *** int dl_el_startele(char *service)
 *** 
 *** Function: start an election for all clients on the specified
 ***           by service
 *** Return  : DL_OK if success
 ***	       DL_ERROR if error
 *** Restrictions: note that a client must also be running
 ***               for this process to participate in the election
 ***/

#define DL_EL_ERROR 1
#define DL_EL_OK 0

int dl_el_startele(char *service);

/***
 *** thread_t dl_el_startserver(char *service, \
 ***			void(*function)(char *winner, int winport, int myport))
 ***
 *** Function: start a server for the election port specified by service
 ***           that is participating in elections from now on
 ***           after an election function is called with the winner as
 ***           argument
 *** Return  : the thread id of the server
 ***           DL_ERROR if error
 ***/

thread_t dl_el_startserver(char *service, \
		    void(*function)(char *winner, int winport, int myport));

/***
 *** int dl_el_stopserver(thread_t server)
 ***
 *** Function: stop the specified server from participating
 ***           in elections
 *** Return  : DL_OK if success
 ***           DL_ERROR if error
 ***/

int dl_el_stopserver(thread_t server);

/****************************************************************
 * PART EIGHT: berkeley time synchronisation (implemented later)*
 ****************************************************************/

/***
 *** int dl_ns_startserv(int port, client_t list)
 ***
 *** start the server process on the specified port 
 *** list contains a list of clients that are polled
 *** return value 0 means error, everything else success
 ***/

/*int dl_ns_startserv(int, client_t);*/

/***
 *** int dl_ns_startclient(int port)
 ***
 *** starts a client process on the specified port
 *** clients reply to time requests or set the system time anew
 *** after timeset messages
 *** return value 0 means error, everything else success
 ***/

/*int dl_ns_startclient(int);*/

#endif /* LIBDIST_H */

/*******************************************************************
 * THE END                                                         *
 *******************************************************************/
