stream.h 4.95 KB
/*
 * Zunächst ein paar allgemeine Bemerkungen zu scot_stream:
 *
 * 1. scot-stream ist eine auf andere Klassen aufbauende Klasse. Es gibt
 *    kein scot_stream_new. Mann kann natürlich über malloc ein leeres
 *    stream-objekt anlegen, das macht für gewöhnlich aber keinen Sinn.
 *    Stattdessen gibt es in Klassen, die stream-io Endpunkte darstellen
 *    Funktionen der Form scot_<Klasse>_get_new_stream 
 *    (z.B. scot_socket_get_new_stream). Diese Funktionen geben ein
 *    gültiges Stream Objekt zu einem Objekt der übergeordneten Klasse
 *    zurück. Das Objekt der übergeordnete Klasse muss sich alle auf diese 
 *    Art angelegten Stream-Objekte merken.
 * 2. Wenn ein Objekt der übergeordneten Klasse geschlossen wird, so werden
 *    auch alle Stream Objekte die von diesem erzeugt wurden freigegeben und
 *    auf NULL gesetzt. (Auf Sie währe eh keine Sinnvolle operation mehr
 *    möglich.)
 * 3. Wird ein Stream-Objekt freigegeben, so bleibt das übergeordnete
 *    Objekt erhalten (und somit auch der handle geöffnet).
 * 4. Ein close auf ein Stream Objekt schließt auch das übergeordnete
 *    Objekt und gibt es frei. Somit werden auch alle weiteren Stream
 *    Objekte geschlossen.
 *
 * !!!Zusammenfassend bleibt nochmal hervorzuheben das close gegenüber free
 *    die stärkere operation ist und zu einem free aller stream objekte und
 *    des übergeordneten Objekts führt.!!!
 */
#ifndef SCOT_STREAM_H
#define SCOT_STREAM_H

#include <scot/scot_int.h>
#include <scot/scot_types.h>

#define SCOT_STREAM_BUF_SIZE		100

/* scot stream types (scot_stream:s_type) . */
/* Die ersten bis zum --- Kommentar sind stream_pool fähig */
#define SCOT_STREAM_TYPE_SOCKET  0
#define SCOT_STREAM_TYPE_PIPE    1
#define SCOT_STREAM_TYPE_TERM    2
/* --- */
#define SCOT_STREAM_TYPE_FILE    3
#define SCOT_STREAM_TYPE_INOTIFY 4

#ifdef WIN32
# include <Windows.h>
# include <scot/stream_win.h>
# define SCOT_FILE_READ  win_file_read
#else
# define SCOT_FILE_READ  read
#endif /* WIN32 */

/* s must me a pointer to a stream...this is normally the case! */
#define SCOT_STREAM_TO_SOCKET(s)	 ((struct scot_socket *)(s))
#define SCOT_STREAM_TO_PIPE(s)	 ((struct scot_pipe *)(s))
#define SCOT_STREAM_TO_TERM(s)	 ((struct scot_term *)(s))
#define SCOT_STREAM_TO_FILE(s)	 ((struct scot_file *)(s))
#define SCOT_STREAM_TO_INOTIFY(s) ((struct scot_inotify *)(s))

/* 
 * get the base object of the given stream with the correct type 
 * Those base types has to be specified here at the moment... maybe
 * sometimes there will be some kind of registration method for 
 * base types
 */
#define SCOT_STREAM_PROV(st) \
	((st)->s_type == SCOT_STREAM_TYPE_SOCKET)? SCOT_STREAM_TO_SOCKET((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_PIPE)?   SCOT_STREAM_TO_PIPE((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_TERM)?   SCOT_STREAM_TO_TERM((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_FILE)?   SCOT_STREAM_TO_FILE((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_INOTIFY)?SCOT_STREAM_TO_INOTIFY((st)):(st)

#define SCOT_STREAM_FREE(st) \
	((st)->s_type == SCOT_STREAM_TYPE_SOCKET)?\
		scot_socket_free (SCOT_STREAM_TO_SOCKET (st)):\
	((st)->s_type == SCOT_STREAM_TYPE_PIPE)?   scot_stream_free ((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_TERM)?   scot_stream_free ((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_FILE)?   scot_stream_free ((st)):\
	((st)->s_type == SCOT_STREAM_TYPE_INOTIFY)?scot_stream_free ((st)):\
		scot_stream_free ((st))

/* 
 * connections via ssl must be handled separately, because communication
 * over them has some very distinc behaviour then with other streams.
 * First, read and write are not done on a handle but on an ssl object.
 * Next, ssl has an all or nothing approach. If a write could not send
 * all data it sould be assumed as failed. This is neccessary for the
 * encryption.
 * Next, ssl is designed to sit on top of most stream types. Thus it
 * is a separate object, that should be createable by a stream object.
 */

struct scot_stream
{
#ifndef WIN32
	union
	{
		int32_t file;
		int32_t sock;
	} handle;
#else
	union
	{
		HANDLE file;
		SOCKET sock;
	} handle;
#endif
	char     rbuf [SCOT_STREAM_BUF_SIZE];
	char     wbuf [SCOT_STREAM_BUF_SIZE];
	uint32_t rbuf_idx;
	uint32_t wbuf_idx;
	int32_t  s_type;   /* an identifier of this stream (file, socket, pipe...) */
	int16_t  s_blk;
};

int     scot_stream_eof       (struct scot_stream *);
SSIZE_T scot_stream_read      (struct scot_stream *, char *, SIZE_T);
SSIZE_T scot_stream_write     (struct scot_stream *, char *, SIZE_T);
void    scot_stream_flush     (struct scot_stream *);

SSIZE_T scot_stream_read_pending  (struct scot_stream *);
SSIZE_T scot_stream_write_pending (struct scot_stream *);

int     scot_stream_get_blocking (struct scot_stream *);
void    scot_stream_set_block    (struct scot_stream *);
void    scot_stream_set_nonblock (struct scot_stream *);

void    scot_stream_close     (struct scot_stream *);
int     scot_stream_is_closed (struct scot_stream *);

void    scot_stream_free      (struct scot_stream *);

#endif /* SCOT_STREAM_H */