OSSP CVS Repository

ossp - Check-in [1477]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1477
Date: 2002-Jan-02 13:40:28 (local)
2002-Jan-02 12:40:28 (UTC)
User:rse
Branch:
Comment: lots of more documentation
Tickets:
Inspections:
Files:
ossp-pkg/sa/sa.pod      1.18 -> 1.19     232 inserted, 50 deleted

ossp-pkg/sa/sa.pod 1.18 -> 1.19

--- sa.pod       2001/11/17 15:03:04     1.18
+++ sa.pod       2002/01/02 12:40:28     1.19
@@ -56,12 +56,12 @@
 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,
@@ -69,7 +69,7 @@
 sa_buffer, 
 sa_option, 
 sa_syscall. 
-            
+
 =item B<Socket Connection Operations>:
 
 sa_bind,
@@ -82,7 +82,7 @@
 sa_shutdown.
 
 =item B<Socket Input/Output Operations (Stream Communication)>:
-            
+
 sa_read,
 sa_readln,
 sa_write,
@@ -103,8 +103,9 @@
 =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.
+application programming interface (API), featuring stream and datagram
+oriented communication over I<Unix Domain> and I<Internet Domain> (TCP
+and UDP) sockets.
 
 It provides the following key features:
 
@@ -143,11 +144,11 @@
 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
+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
+Instead of C<ssize_t> it can use C<size_t> because B<OSSP sa> does not use
 traditional Unix return code semantics.
 
 =item B<I/O Timeouts>
@@ -167,11 +168,11 @@
 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
+operations on larger aggregated messages and with less required 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.
+writing (see sa_writef()) is provided, modelled after STDIO's fgets(3)
+and fprintf(3). Both features fully leverage from the I/O buffering.
 
 =back
 
@@ -194,33 +195,49 @@
  SA_ERR_EOF  End Of Communication
  SA_ERR_TMT  Communication Timeout
  SA_ERR_SYS  Operating System Error (see errno)
+ SA_ERR_IMP  Implementation Not Available
  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.
+This is an opaque data type representing a socket address. 
+Only pointers to this abstract data 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.
+This is an opaque data type representing a socket.
+Only pointers to this abstract data type are used in the API.
 
 =back
 
 =head1 FUNCTIONS
 
+B<OSSP sa> provides a bunch of API functions, all modelled after the
+same prototype: "C<sa_rc_t> C<sa_>I<name>C<(sa_>[C<addr_>]C<_t *,>
+...C<)>". This means every function returns C<sa_rc_t> to indicate its
+success (C<SA_OK>) or failure (C<SA_ERR_XXX>) by returning a return code
+(the corresponding describing text can be determined by passing this
+return code to C<sa_error>). Each function name starts with the common
+prefix C<sa_> and receives a C<sa_t> (or C<sa_addr_t>) object on which
+it operates as its first argument.
+
 =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.
+Create a socket address abstraction object. 
+The object is stored in I<saa> on success.
+
+Example: C<sa_addr_t *saa; sa_addr_create(&saa);>
 
 =item sa_rc_t B<sa_addr_destroy>(sa_addr_t *I<saa>);
 
 Destroy a socket address abstraction object.
+The object I<saa> is invalid after this call succeeded.
+
+Example: C<sa_addr_destroy(saa);>
 
 =back
 
@@ -230,55 +247,120 @@
 
 =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>.
+Import an address into by converting from an URI specification to the
+corresponding address abstraction. 
+
+The supported syntax for I<uri> 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.
+
+In the URI, I<path> can be an absolute or relative filesystem 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 ("C<smtp>"). If I<port> is specified as a name, it is resolved as
+a TCP port by default. To force resolving a I<port> name via a
+particular protocol, I<protocol> can be specified as either "C<tcp>" or
+"C<udp>".
+
+The result is stored in I<saa> on success.
+
+Example: C<sa_addr_u2a(saa, "inet://192.168.0.1:smtp");>
 
 =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>).
+Import an address by converting from a tranditional C<struct sockaddr>
+object to the corresponding address abstraction.
+
+The accepted addresses for I<sabuf> are: C<struct sockaddr_un>
+(C<AF_LOCAL>), C<struct sockaddr_in> (C<AF_INET>) and C<struct
+sockaddr_in6> (C<AF_INET6>). The I<salen> is the corresponding
+C<sizeof()> of the underlying structure.
+
+The result is stored in I<saa> on success.
+
+Example: C<sockaddr_in in; sa_addr_s2a(saa, (struct sockaddr *)&in, (socklen_t)sizeof(in));>
 
 =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.
+corresponding URI specification. 
+
+The result is a string of the form "C<unix:>I<path>" for I<Unix
+Domain> addresses and "C<inet://>I<addr>C<:>I<port>" for I<Internet
+Domain> addresses. Notice that I<addr> and I<port> are returned in
+numerical (unresolved) way. Additionally, because usually one cannot map
+bi-directionally between TCP or UDP port names and the numerical value,
+there is no distinction between TCP and UDP here.
+
+The result is stored in I<uri> on success.
+The caller has to free(3) the I<uri> buffer later.
+
+Example: C<char *uri; sa_addr_a2u(saa, &uri);>
 
 =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.
+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 result is stored in I<sabuf> and I<salen> on success.
+The caller has to free(3) the I<sabuf> buffer later.
+
+Example: C<struct sockaddr sabuf, socklen_t salen; sa_addr_a2s(saa, &sa, &salen);>
 
 =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.
+Match two address abstractions up to a specified prefix.
+
+This compares the addresses I<saa1> and I<saa2> by only taking the
+prefix part of length I<prefixlen> into account. I<prefixlen> is number
+of filesystem path characters for I<Unix Domain> addresses and number
+of bits for I<Internet Domain> addresses. In case of I<Internet Domain>
+addresses, the addresses are matched in network byte order and the port
+(counting as an additional bit/item of length 1) is virtually appended
+to the address for matching. Specifying I<prefixlen> as C<-1> means
+matching the whole address (but without the virtually appended port)
+without having to know how long the underlying address representation
+(length of path for Unix Domain addresses, 32+1 [IPv4] or 128+1 [IPv6]
+for Internet Domain addresses) is. Specifying I<prefixlen> as C<-2> is
+equal to C<-1> but additionally the port is matched, too.
+
+This especially can be used to implement Access Control Lists (ACL)
+without having to fiddle around with the underlying representation.
+For this make I<saa1> the to be checked address and I<saa2> plus
+I<prefixlen> the ACL pattern as shown in the following example.
+
+Example:
+
+ sa_addr_t *srv_sa;
+ sa_addr_t *clt_saa;
+ sa_t      *clt_sa;
+ sa_addr_t *acl_saa;
+ char      *acl_addr = "192.168.0.0";
+ int        acl_len  = 24;
+ ...
+ sa_addr_u2a(&acl_saa, "inet://%s:0", acl_addr);
+ ...
+ while (sa_accept(srv_sa, &clt_saa, &clt_sa) == SA_OK) {
+     if (sa_addr_match(clt_saa, acl_saa, acl_len) != SA_OK) {
+         /* connection refused */
+         ...
+         sa_addr_destroy(clt_saa);
+         sa_destroy(clt_sa);
+         continue;
+     }
+     ...
+ }
+ ...
 
 =back
-            
+
 =head2 Socket Object Operations
 
 =over 4
@@ -286,10 +368,16 @@
 =item sa_rc_t B<sa_create>(sa_t **I<sa>);
 
 Create a socket abstraction object.
+The object is stored in I<sa> on success.
+
+Example: C<sa_t *sa; sa_create(&sa);>
 
 =item sa_rc_t B<sa_destroy>(sa_t *I<sa>);
 
 Destroy a socket abstraction object.
+The object I<sa> is invalid after this call succeeded.
+
+Example: C<sa_destroy(sa);>
 
 =back
             
@@ -299,14 +387,108 @@
 
 =item sa_rc_t B<sa_type>(sa_t *I<sa>, sa_type_t I<type>);
 
+Assign a particular communication protocol type to the socket
+abstraction object.
+
+A socket can only be assigned a single protocol type at any time.
+Nevertheless one can switch the type of a socket abstraction object at
+any time in order to reuse it for a different communication. Just keep
+in mind that switching the type will stop a still ongoing communication
+by closing the underlying socket.
+
+Possible values for I<type> are C<SA_TYPE_STREAM> (stream communication)
+and C<SA_TYPE_DATAGRAM> (datagram communication). The default
+communication protocol type is C<SA_TYPE_STREAM>.
+
+Example: C<sa_type(sa, SA_TYPE_STREAM);>
+
 =item sa_rc_t B<sa_timeout>(sa_t *I<sa>, sa_timeout_t I<id>, long I<sec>, long I<usec>);
 
+Assign one or more communication timeouts to the socket abstraction object.
+
+Possible values for I<id> are: C<SA_TIMEOUT_ACCEPT> (affecting
+sa_accept()), C<SA_TIMEOUT_CONNECT> (affecting sa_connect()),
+C<SA_TIMEOUT_READ> (affecting sa_read(), sa_readln() and sa_recv())
+and C<SA_TIMEOUT_WRITE> (affecting sa_write(), sa_writef() and
+sa_send()). Additionally you can set all four timeouts at once by using
+C<SA_TIMEOUT_ALL>. The default is that no communication timeouts are
+used which is equal to I<sec>=C<0>/I<usec>=C<0>.
+
+Example: C<sa_timeout(sa, SA_TIMEOUT_ALL, 30, 0);>
+
 =item sa_rc_t B<sa_buffer>(sa_t *I<sa>, sa_buffer_t I<id>, size_t I<size>);
 
+Assign I/O communication buffers to the socket abstraction object.
+
+Possible values for I<id> are: C<SA_BUFFER_READ> (affecting sa_read()
+and sa_readln()) and C<SA_BUFFER_WRITE> (affecting sa_write() and
+sa_writef()). The default is that no communication buffers are
+used which is equal to I<size>=C<0>.
+
+Example: C<sa_buffer(sa, SA_BUFFER_READ, 16384);>
+
 =item sa_rc_t B<sa_option>(sa_t *I<sa>, sa_option_t I<id>, ...);
 
+Adjust various options of the socket abstraction object.
+
+The adjusted option is controlled by I<id>. The number and type of
+the expected following argument(s) are dependent on the particular
+option. Currently the following options are implement (option arguments
+in parenthesis): C<SA_OPTION_NAGLE> (C<int> I<yesno>) for enabling
+(I<yesno>=C<1>) or disabling (I<yesno>=C<0>) Nagle's Algorithm
+(see RFC898); C<SA_OPTION_NONBLOCK> (C<int> I<yesno>) for enabling
+(I<yesno>=C<1>) or disabling (I<yesno>=C<0>) non-blocking I/O mode (see
+C<O_NONBLOCK> of fcntl(2)).
+
+Example: C<sa_option(sa, SA_OPTION_NONBLOCK, 1);>
+
 =item sa_rc_t B<sa_syscall>(sa_t *I<sa>, sa_syscall_t I<id>, void (*I<fptr>)(), void *I<fctx>);
 
+Divert I/O communication related system calls to user supplied callback functions.
+
+This allows you to override mostly all I/O related system calls B<OSSP
+sa> internally performs while communicating. This can be used to adapt
+B<OSSP sa> to different run-time environments and requirements without
+having to change the source code. Usually this is used to divert the
+system calls to the variants of a user-land multithreading facility like
+B<GNU Pth>.
+
+The function supplied as I<fptr> is required to fulfill the API of
+the replaced system call, i.e., it has to have the same prototype (if
+I<fctx> is C<NULL>). If I<fctx> is not C<NULL>, this prototype has to be
+extended to accept an additional first argument of type C<void *> which
+receives the value of I<fctx>. It is up to the callback function whether
+to pass the call through to the replaced actual system call or not.
+
+Possible values for I<id> are (expected prototypes behind I<fptr> are
+given in parenthesis): 
+C<SA_SYSCALL_CONNECT>  ("C<int (*)([void *,] int, const struct sockaddr *, socklen_t)>", see connect(2)),
+C<SA_SYSCALL_ACCEPT>   ("C<int (*)([void *,] int, struct sockaddr *, socklen_t *)>", see accept(2)),
+C<SA_SYSCALL_SELECT>   ("C<int (*)([void *,] int, fd_set *, fd_set *, fd_set *, struct timeval *)>", see select(2)),
+C<SA_SYSCALL_READ>     ("C<ssize_t (*)([void *,] int, void *, size_t)>", see read(2)), 
+C<SA_SYSCALL_WRITE>    ("C<ssize_t (*)([void *,] int, const void *, size_t)>", see write(2)), 
+C<SA_SYSCALL_RECVFROM> ("C<ssize_t (*)([void *,] int, void *, size_t, int, struct sockaddr *, socklen_t *)>", see recvfrom(2)), 
+C<SA_SYSCALL_SENDTO>   ("C<ssize_t (*)([void *,] int, const void *, size_t, int, const struct sockaddr *, socklen_t)>", see sendto(2)).
+
+Example: 
+
+ FILE *trace_fp = ...;
+
+ ssize_t trace_read(void *ctx, int fd, void *buf, size_t len)
+ {
+     FILE *fp = (FILE *)ctx; 
+     ssize_t rv;
+     int errno_saved;
+
+     rv = read(fd, buf, len);
+     errno_saved = errno;
+     fprintf(fp, "read(%d, %lx, %d) = %d\n", fd, (long)buf, len, rv);
+     errno = errno_saved;
+     return rv;
+ }
+
+ sa_syscall(sa, SA_SC_READ, trace_read, trace_fp);
+
 =back
 
 =head2 Socket Connection Operations

CVSTrac 2.0.1