/*

  |=============================================================================|
  |                                                                             |
  |      The main concept of handling client connections is the following       |
  |                                                                             |
  |=============================================================================|

  -------------
  BASIC CONCEPT
  -------------

  Server ( the powersave daemon ) 
  ------------------------------------------

  1. provide socket to which clients can connect

  2. client sends connection request

  3. Accept the connection

  4. Receive the request string

  5. server checks if the client has sent a valid request string (protocol
     version, requested mode(s))

     request is not valid -> skip the client and send him a message about a
       failure ( instead of the mode, a -1 is sent )
   
     request is valid --> add the client (with the request) to the list of
       connected clients 

  6. Everytime there happens an event or a notification, send all the
     clients this event/message which have requested this information

     --> if the client does not read the information remove the client from
         the list


  Client
  ------------------------------------------

  1. Connect to the server socket and send a request string

  2. get the current infos from the server and whether the server accepted the
     connection/request

  3. Poll for events on the server socket

  4. Receive events and handle them




  ----------------
  DETAILED CONCEPT
  ----------------

  Request string
  -------------------------------------------

  - string delimited by a char (e.g. | ) and terminated by a \0.
  - for example:

  0.1|1|\0

  Sections ------------------------------------------
  1. protocol version
  2. This is the requested mode. Mode is one of MODE_POWERSAVE_EVENTS,
     MODE_ACPI_EVENTS, MODE_NOTIFICATION or MODE_SCREENSAVER which are
     defined in powersave_clientsocket.h You can also request all three modes
     together with adding up the values. They are simple integers


  data exchange
  ------------------------------------------

  1. client connects and sends request string 0.1|2|\0
     --> the client wants all powersave events and is aware
         of protocol version 0.1

    If the server sends back a string like 0.1|-1|, he didn't accept the request.
    Either there is a protocol mismatch or the request string is not valid.
    
  3. Server accepts the connection and adds the client to the already connected clients
     ( there will be no answer from the daemon if the connection succeeded )
  
  4. client polls the socket for new information (eg. with QT - use a QSocketNotifier)
     or the function pollForLine(...) in this library
  
  5. server waits for internal changes --> If there is one, send it to the
     socket(clients)

     The protocol version is sent each time.

  6. client receives new data and handles it. An example of a reveived answer from
     the daemon might look like:
        0.1|2|button.power|\0


  For an example code how a client might look like, refer to the
  testclient directory located in the base directory of powersave.


*/




#ifndef POWERSAVE_CLIENTSOCKET_H
#define POWERSAVE_CLIENTSOCKET_H

#ifdef __cplusplus
extern "C" {
#endif


// define that we are using protocol version 0.1
#define PROTOCOL_VERSION "0.1"

// define the different modes clients can request
#define MODE_ACPI_EVENTS 1
#define MODE_POWERSAVE_EVENTS 2
#define MODE_NOTIFICATIONS 4
#define MODE_SCREENSAVER 8
#define MODE_PROGRESS 16


// this node holds some values/states
typedef struct cNode {
	// the filedescriptor
	int fd;
	// holds the protocol version
	char *version;
	// mode
	int mode;
	// holds the protocol version
	char *message;
} cNode;


	/* The provided functions are declared in the same order as they
	 * should be used when writing a client application */

// establishes a connection to the daemon with the requeststring requeststring
// and returns the filedescriptor on which information is sent
// you have to read the reply with readLine() on your own
int connectToDaemon( const char *requeststring);

// polls the given filedescriptor for a line and returns as far there
// happended something on the socket. So this function is blocking
int pollForLine(int fd);

// reads one line from the socket refered to the filedescriptor fd and returns it.
// memory for the returned char is allocated inside this function
// NULL is returned if there was an error while reading from the socket.
// Maybe powersave died
char *readLine(int fd);

// parses one line buf into the node node. Memory for the node has to be
// allocated before
int parseLine( cNode* node, const char *buf);


	/*
	 * internal funtions. You do not have to use them
	 */

// opens a connection to the daemon, is called by connectToDaemon, only
// for internal use. It is called by connectToDaemon(...)
int open_client_connection(void);

// reads on item delimited by two pipe characters |...|
// only for internal use. It is called by parse Line
int readSection(const char *buf, char* section, int i);


#ifdef __cplusplus
}
#endif


#endif
