Index: ossp-pkg/sa/sa.pod RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.pod,v rcsdiff -q -kk '-r1.18' '-r1.19' -u '/v/ossp/cvs/ossp-pkg/sa/sa.pod,v' 2>/dev/null --- 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: sa_create, sa_destroy. - + =item B: sa_type, @@ -69,7 +69,7 @@ sa_buffer, sa_option, sa_syscall. - + =item B: sa_bind, @@ -82,7 +82,7 @@ sa_shutdown. =item B: - + sa_read, sa_readln, sa_write, @@ -103,8 +103,9 @@ =head1 DESCRIPTION B is an abstraction library for the Unix I networking -interface featuring stream and datagram oriented communication over -I and I (TCP and UDP) sockets. +application programming interface (API), featuring stream and datagram +oriented communication over I and I (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 hides most of this in its API and for C provides a backward-compatibility definition. -Instead of C it uses C because B does not use +Instead of C it can use C because B does not use traditional Unix return code semantics. =item B @@ -167,11 +168,11 @@ If B 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 is used for stream communication, for +operations on larger aggregated messages and with less required system +calls. Additionally if B 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 (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 (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 provides a bunch of API functions, all modelled after the +same prototype: "C CIC<(sa_>[C]C<_t *,> +...C<)>". This means every function returns C to indicate its +success (C) or failure (C) by returning a return code +(the corresponding describing text can be determined by passing this +return code to C). Each function name starts with the common +prefix C and receives a C (or C) object on which +it operates as its first argument. + =head2 Address Object Operations =over 4 =item sa_rc_t B(sa_addr_t **I); -Create a socket address abstraction object. +Create a socket address abstraction object. +The object is stored in I on success. + +Example: C =item sa_rc_t B(sa_addr_t *I); Destroy a socket address abstraction object. +The object I is invalid after this call succeeded. + +Example: C =back @@ -230,55 +247,120 @@ =item sa_rc_t B(sa_addr_t *I, const char *I, ...); -Import an address by converting from an URI specification -to the corresponding address abstraction. The supported URI -syntax is: CI for I addresses and -CIC<:>I[C<#>I] for I -addresses. - -I can be an absolute or relative file path to an existing or -not-existing file. I 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). I has to be either a decimal port in -the range C<1>...C<65535> or a port name. If I is specified as a -name, it is resolved as a TCP port by default. To force resolving via a -particular protocol, I can be specified as either C or -C. +Import an address into by converting from an URI specification to the +corresponding address abstraction. + +The supported syntax for I is: "CI" for I +addresses and "CIC<:>I[C<#>I]" for +I addresses. + +In the URI, I can be an absolute or relative filesystem path +to an existing or not-existing file. I 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"). I has +to be either a decimal port in the range C<1>...C<65535> or a port +name ("C"). If I is specified as a name, it is resolved as +a TCP port by default. To force resolving a I name via a +particular protocol, I can be specified as either "C" or +"C". + +The result is stored in I on success. + +Example: C =item sa_rc_t B(sa_addr_t *I, const struct sockaddr *I, socklen_t I); -Import an address by converting from a tranditional C object -to the corresponding address abstraction. The accepted addresses are: C (C), C (C) and C (C). +Import an address by converting from a tranditional C +object to the corresponding address abstraction. + +The accepted addresses for I are: C +(C), C (C) and C (C). The I is the corresponding +C of the underlying structure. + +The result is stored in I on success. + +Example: C =item sa_rc_t B(sa_addr_t *I, char **I); Export an address by converting from the address abstraction to the -corresponding URI specification. The result is a string of the form -CI for I addresses and (unresolved/numerical) -CIC<:>I for I addresses. The -caller has to free(3) the I later. +corresponding URI specification. + +The result is a string of the form "CI" for I addresses and "CIC<:>I" for I addresses. Notice that I and I 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 on success. +The caller has to free(3) the I buffer later. + +Example: C =item sa_rc_t B(sa_addr_t *I, struct sockaddr **I, socklen_t *I); Export an address by converting from the address abstraction to the -corresponding traditional C object. The result -is one of the following underlying address structures: C (C), C (C) and -C (C). The caller has to free(3) the -I later. +corresponding traditional C object. + +The result is one of the following underlying address structures: C (C), C (C) and C (C). + +The result is stored in I and I on success. +The caller has to free(3) the I buffer later. + +Example: C =item sa_rc_t B(sa_addr_t *I, sa_addr_t *I, size_t I); -Match two address abstractions by only taking the prefix part of length -I into account. I is number of path characters -for I addresses and number of bits for I -addresses. +Match two address abstractions up to a specified prefix. + +This compares the addresses I and I by only taking the +prefix part of length I into account. I is number +of filesystem path characters for I addresses and number +of bits for I addresses. In case of I +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 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 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 the to be checked address and I plus +I 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_t **I); Create a socket abstraction object. +The object is stored in I on success. + +Example: C =item sa_rc_t B(sa_t *I); Destroy a socket abstraction object. +The object I is invalid after this call succeeded. + +Example: C =back @@ -299,14 +387,108 @@ =item sa_rc_t B(sa_t *I, sa_type_t I); +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 are C (stream communication) +and C (datagram communication). The default +communication protocol type is C. + +Example: C + =item sa_rc_t B(sa_t *I, sa_timeout_t I, long I, long I); +Assign one or more communication timeouts to the socket abstraction object. + +Possible values for I are: C (affecting +sa_accept()), C (affecting sa_connect()), +C (affecting sa_read(), sa_readln() and sa_recv()) +and C (affecting sa_write(), sa_writef() and +sa_send()). Additionally you can set all four timeouts at once by using +C. The default is that no communication timeouts are +used which is equal to I=C<0>/I=C<0>. + +Example: C + =item sa_rc_t B(sa_t *I, sa_buffer_t I, size_t I); +Assign I/O communication buffers to the socket abstraction object. + +Possible values for I are: C (affecting sa_read() +and sa_readln()) and C (affecting sa_write() and +sa_writef()). The default is that no communication buffers are +used which is equal to I=C<0>. + +Example: C + =item sa_rc_t B(sa_t *I, sa_option_t I, ...); +Adjust various options of the socket abstraction object. + +The adjusted option is controlled by I. 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 (C I) for enabling +(I=C<1>) or disabling (I=C<0>) Nagle's Algorithm +(see RFC898); C (C I) for enabling +(I=C<1>) or disabling (I=C<0>) non-blocking I/O mode (see +C of fcntl(2)). + +Example: C + =item sa_rc_t B(sa_t *I, sa_syscall_t I, void (*I)(), void *I); +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 internally performs while communicating. This can be used to adapt +B 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. + +The function supplied as I is required to fulfill the API of +the replaced system call, i.e., it has to have the same prototype (if +I is C). If I is not C, this prototype has to be +extended to accept an additional first argument of type C which +receives the value of I. 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 are (expected prototypes behind I are +given in parenthesis): +C ("C", see connect(2)), +C ("C", see accept(2)), +C ("C", see select(2)), +C ("C", see read(2)), +C ("C", see write(2)), +C ("C", see recvfrom(2)), +C ("C", 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