##
##  SA - OSSP Socket Abstraction Library
##  Copyright (c) 2001 Ralf S. Engelschall <rse@engelschall.com>
##  Copyright (c) 2001 The OSSP Project <http://www.ossp.org/>
##  Copyright (c) 2001 Cable & Wireless Deutschland <http://www.cw.com/de/>
##
##  This file is part of OSSP SA, a socket abstraction library which
##  can be found at http://www.ossp.org/pkg/sa/.
##
##  Permission to use, copy, modify, and distribute this software for
##  any purpose with or without fee is hereby granted, provided that
##  the above copyright notice and this permission notice appear in all
##  copies.
##
##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
##  SUCH DAMAGE.
##
##  sa.pod: socket abstraction library manual page
##

=pod

=head1 NAME

B<OSSP sa> - Socket Abstraction Library

=head1 SYNOPSIS

=over 4

=item B<Abstract Data Types>:

sa_rc_t,
sa_addr_t,
sa_t.

=item B<Address Object Operations>:

sa_addr_create,
sa_addr_destroy.

=item B<Address Operations>:

sa_addr_u2a,
sa_addr_s2a,
sa_addr_a2u,
sa_addr_a2s,
sa_addr_match.
            
=item B<Socket Object Operations>:

sa_create,
sa_destroy. 
            
=item B<Socket Parameter Operations>:

sa_type,
sa_timeout,
sa_buffer, 
sa_option, 
sa_syscall. 
            
=item B<Socket Connection Operations>:

sa_bind,
sa_connect,
sa_listen,
sa_accept,  
sa_getremote,
sa_getlocal,
sa_getfd,
sa_shutdown.

=item B<Socket Input/Output Operations (Stream Communication)>:
            
sa_read,
sa_readln,
sa_write,
sa_writef,
sa_flush.   

=item B<Socket Input/Output Operations (Datagram Communication)>:

sa_recv,
sa_send.

=item B<Socket Error Handling>:

sa_error.

=back

=head1 DESCRIPTION

B<OSSP sa> is an abstraction library for the Unix I<Socket> networking
interface featuring stream and datagram oriented communication over
I<Unix Domain> and I<Internet Domain> (TCP and UDP) sockets.

It provides the following key features:

=over 4

=item B<Stand-Alone, Self-Contained, Embeddable>

Although there are various Open Source libraries available which provide
a similar abstraction approach, they all either lack important features
or unfortunately depend on other companion libraries. B<OSSP sa> fills
this gap by providing all important features (see following points) as a
stand-alone and fully self-contained library. This way B<OSSP sa> can be
trivially embedded as a sub-library into other libraries. It especially
provides additional support for namespace-safe embedding of its API in
order to avoid symbol conflicts (see C<SA_PREFIX> in F<sa.h>).

=item B<Address Abstraction>

Most of the uglyness in the Unix I<Socket> API is the necessarity to
have to deal with the various address structures (C<struct sockaddr_xx>)
which exist because of both the different communication types and
addressing schemes. B<OSSP sa> fully hides this by providing an abstract
and opaque address type (C<sa_addr_t>) together with utility functions
which allow one to convert from the traditional C<struct sockaddr> or
URI specification to the C<sa_addr_t> and vice versa without having to
deal with special cases related to the underlying particular C<struct
sockaddr_xx>. B<OSSP sa> support I<Unix Domain> and both IPv4 and IPv6
I<Internet Domain> addressing.

=item B<Type Abstraction>

Some other subtle details in the Unix I<Socket> API make the life hard
in practice: C<socklen_t> and C<ssize_t>. These two types originally
were (and on some platforms still are) plain integers or unsigned
integers while POSIX later introduced own types for them (and even
revised these types after some time again). This is nasty, because
for 100% type-correct API usage (especially important on 64-bit
machines where pointers to different integer types make trouble), every
application has to check whether the newer types exists and if not
provide own definitions which map to the still actually used integer
type on the underlying platform. B<OSSP sa> hides most of this in its
API and for C<socklen_t> provides a backward-compatibility definition.
Instead of C<ssize_t> it uses C<size_t> because B<OSSP sa> does not use
traditional Unix return code semantics.

=item B<I/O Timeouts>

Each I/O function in B<OSSP sa> is aware of timeouts (set by
sa_timeout()), i.e., all I/O operations return C<SA_ERR_TMT> if the
timeout expired before the I/O operation was able to succeed. This
allows one to easily program less-blocking network services. B<OSSP
sa> internally implements these timeouts either through the
C<SO_{SND,RCV}TIMEO> feature on more modern I<Socket> implementations
or through traditional select(2). This way high performance is achieved
on modern platforms while the full functionality still is available on
older platforms.

=item B<I/O Stream Buffering>

If B<OSSP sa> is used for stream communication, internally all I/O
operations can be performed through input and/or output buffers (set
by sa_buffer()) for achieving higher I/O performance by doing I/O
operations on larger aggregated messages and with less system calls.
Additionally if B<OSSP sa> is used for stream communication, for
convinience reasons line-oriented reading (sa_readln()) and formatted
writing (sa_writef()) is provided, modelled after STDIO's fgets(3) and
fprintf(3). Both features fully leverage from the I/O buffering.

=back

=head1 DATA TYPES

B<OSSP sa> uses three data types in its API:

=over 4

=item B<sa_rc_t> (Return Code Type)

This is an exported enumerated integer type with the following possible
values:

 SA_OK       Everything Ok
 SA_ERR_ARG  Invalid Argument
 SA_ERR_USE  Invalid Use Or Context
 SA_ERR_MEM  Not Enough Memory
 SA_ERR_MTC  Matching Failed
 SA_ERR_EOF  End Of Communication
 SA_ERR_TMT  Communication Timeout
 SA_ERR_SYS  Operating System Error (see errno)
 SA_ERR_INT  Internal Error

=item B<sa_addr_t> (Socket Address Abstraction Type)

This is an opaque type representing a socket address. 
Only pointers to this abstract type are used in the API.

=item B<sa_t> (Socket Abstraction Type)

This is an opaque type representing a socket.
Only pointers to this abstract type are used in the API.

=back

=head1 FUNCTIONS

=head2 Address Object Operations

=over 4

=item sa_rc_t B<sa_addr_create>(sa_addr_t **I<saa>);

Create a socket address abstraction object.

=item sa_rc_t B<sa_addr_destroy>(sa_addr_t *I<saa>);

Destroy a socket address abstraction object.

=back

=head2 Address Operations

=over 4

=item sa_rc_t B<sa_addr_u2a>(sa_addr_t *I<saa>, const char *I<uri>, ...);

Import an address by converting from an URI specification
to the corresponding address abstraction. The supported URI
syntax is: C<unix:>I<path> for I<Unix Domain> addresses and
C<inet://>I<addr>C<:>I<port>[C<#>I<protocol>] for I<Internet Domain>
addresses.

I<path> can be an absolute or relative file path to an existing or
not-existing file. I<addr> can be an IPv4 address in dotted decimal
notation (C<127.0.0.1>), an IPv6 address in colon-separated (optionally
abbreviated) hexadecimal notation (C<::1>) or a to-be-resolved hostname
(C<localhost.example.com>). I<port> has to be either a decimal port in
the range C<1>...C<65535> or a port name. If I<port> is specified as a
name, it is resolved as a TCP port by default. To force resolving via a
particular protocol, I<protocol> can be specified as either C<tcp> or
C<udp>.

=item sa_rc_t B<sa_addr_s2a>(sa_addr_t *I<saa>, const struct sockaddr *I<sabuf>, socklen_t I<salen>);

Import an address by converting from a tranditional C<struct sockaddr> object
to the corresponding address abstraction. The accepted addresses are: C<struct
sockaddr_un> (C<AF_LOCAL>), C<struct sockaddr_in> (C<AF_INET>) and C<struct
sockaddr_in6> (C<AF_INET6>).

=item sa_rc_t B<sa_addr_a2u>(sa_addr_t *I<saa>, char **I<uri>);

Export an address by converting from the address abstraction to the
corresponding URI specification. The result is a string of the form
C<unix:>I<path> for I<Unix Domain> addresses and (unresolved/numerical)
C<inet://>I<addr>C<:>I<port> for I<Internet Domain> addresses. The
caller has to free(3) the I<uri> later.

=item sa_rc_t B<sa_addr_a2s>(sa_addr_t *I<saa>, struct sockaddr **I<sabuf>, socklen_t *I<salen>);

Export an address by converting from the address abstraction to the
corresponding traditional C<struct sockaddr> object. The result
is one of the following underlying address structures: C<struct
sockaddr_un> (C<AF_LOCAL>), C<struct sockaddr_in> (C<AF_INET>) and
C<struct sockaddr_in6> (C<AF_INET6>). The caller has to free(3) the
I<sabuf> later.

=item sa_rc_t B<sa_addr_match>(sa_addr_t *I<saa1>, sa_addr_t *I<saa2>, size_t I<prefixlen>);

Match two address abstractions by only taking the prefix part of length
I<prefixlen> into account. I<prefixlen> is number of path characters
for I<Unix Domain> addresses and number of bits for I<Internet Domain>
addresses.

=back
            
=head2 Socket Object Operations

=over 4

=item sa_rc_t B<sa_create>(sa_t **I<sa>);

Create a socket abstraction object.

=item sa_rc_t B<sa_destroy>(sa_t *I<sa>);

Destroy a socket abstraction object.

=back
            
=head2 Socket Parameter Operations

=over 4

=item sa_rc_t B<sa_type>(sa_t *I<sa>, sa_type_t I<type>);

=item sa_rc_t B<sa_timeout>(sa_t *I<sa>, sa_timeout_t I<id>, long I<sec>, long I<usec>);

=item sa_rc_t B<sa_buffer>(sa_t *I<sa>, sa_buffer_t I<id>, size_t I<size>);

=item sa_rc_t B<sa_option>(sa_t *I<sa>, sa_option_t I<id>, ...);

=item sa_rc_t B<sa_syscall>(sa_t *I<sa>, sa_syscall_t I<id>, void (*I<fptr>)(), void *I<fctx>);

=back

=head2 Socket Connection Operations

=over 4

=item sa_rc_t B<sa_bind>(sa_t *I<sa>, sa_addr_t *I<laddr>);

=item sa_rc_t B<sa_connect>(sa_t *I<sa>, sa_addr_t *I<raddr>);

=item sa_rc_t B<sa_listen>(sa_t *I<sa>, int I<backlog>);

=item sa_rc_t B<sa_accept>(sa_t *I<sa>, sa_addr_t **I<caddr>, sa_t **I<csa>);

=item sa_rc_t B<sa_getremote>(sa_t *I<sa>, sa_addr_t **I<raddr>);

=item sa_rc_t B<sa_getlocal>(sa_t *I<sa>, sa_addr_t **I<laddr>);

=item sa_rc_t B<sa_getfd>(sa_t *I<sa>, int *I<fd>);

=item sa_rc_t B<sa_shutdown>(sa_t *I<sa>, char *I<flags>);

=back

=head2 Socket Input/Output Operations (Stream Communication)

=over 4

=item sa_rc_t B<sa_read>(sa_t *I<sa>, char *I<buf>, size_t I<buflen>, size_t *I<bufdone>);

=item sa_rc_t B<sa_readln>(sa_t *I<sa>, char *I<buf>, size_t I<buflen>, size_t *I<bufdone>);

=item sa_rc_t B<sa_write>(sa_t *I<sa>, const char *I<buf>, size_t I<buflen>, size_t *I<bufdone>);

=item sa_rc_t B<sa_writef>(sa_t *I<sa>, const char *I<fmt>, ...);

=item sa_rc_t B<sa_flush>(sa_t *I<sa>);

=back

=head2 Socket Input/Output Operations (Stream Communication)

=over 4

=item sa_rc_t B<sa_recv>(sa_t *I<sa>, char *I<buf>, size_t I<buflen>, size_t *I<bufdone>, sa_addr_t **I<raddr>);

=item sa_rc_t B<sa_send>(sa_t *I<sa>, const char *I<buf>, size_t I<buflen>, size_t *I<bufdone>, sa_addr_t *I<raddr>);

=back

=head2 Socket Error Handling

=over 4

=item char *B<sa_error>(sa_rc_t I<rv>);

=back

=head1 STANDARDS

R. Gilligan, S. Thomson, J. Bound, W. Stevens,
"Basic Socket Interface Extensions for IPv6", 
RFC 2553, March 1999.

W. Stevens, 
"Advanced Sockets API for IPv6",
B<RFC 2292>, February 1998.

R. Fielding, L. Masinter, T. Berners-Lee, 
"Uniform Resource Identifiers: Generic Syntax", 
B<RFC 2396>, August 1998.

R. Hinden, S. Deering,
"IP Version 6 Addressing Architecture",
B<RFC 2373>, July 1998.

R. Hinden, B. Carpenter, L. Masinter, 
"Format for Literal IPv6 Addresses in URL's", 
B<RFC 2732>, December 1999.

=head1 HISTORY

B<OSSP sa> was invented in August 2001 by Ralf S. Engelschall for use
inside the OSSP project. Its creation was prompted by the requirement
to implement an SMTP logging channel for B<OSSP l2> (logging library).
Its initial code was derived from a predecessor sub-library originally
written for socket address abstraction inside B<OSSP lmtp2nntp>.

=head1 AUTHORS

 Ralf S. Engelschall
 rse@engelschall.com
 www.engelschall.com

=cut

