ossp-pkg/srpc/BRES
BASIC RESEARCH AND BRAIN-STORMING
=================================
- Architecture:
- Abstracted Message Passing Library: libamp
- eXtendable Data Serialization Library: libxds
- Simple Remote Procedure Call Library: libsrpc
- libxds does intentionally NOT support the concept of arrays and
structures ("sequence" and "record" in ASN.1-speak), because not all
encoding systems support structured data. Hence, someone who'd want
to decode the serialized buffer cannot rely on this information
actually being included in the encoded data.
The only use of having these capabilities nonetheles would be that
the decode function could type-check the specification of what has
been received against the actual contents of the data. While this is
nice to have, we did not consider this to be reason enough to add
complexity to our interface and implementation.
- The server actually performing the function call has to interpret
the transferred data according to the functions prototype. This may
be done in one of the following ways:
- All functions have the same prototype. The function may then be a
stub calling the actual function. These stubs can be generated
manually or semi-automatically.
- Allow only a finite set of prototypes and switch according to the
function tye, like in eAPI in Apache.
- Build function call dynamically using the Foreign Function Call
library.
- reduce "int foo(int, foo_t *)"
to "rpc_t foo(rpc_t)" mit
rpc_t: void *, size_t
because
o constant function prototype on server-side
(foreign function call problem!)
o only application knows how to convert
complex data structures (foo_t) into
serialized octet-stream
o greater flexibility in data transfer
o rpc library complexity is reduced
(on cost of application complexity)
instead remote procedure call
only message passing
- auditing/logging:
in XDS: nicht noetig
in AMP: 3 levels: in API von MP und in backends und I/O dump
mit Hilfe von Callbacks (L2!)
- message passing / procedure call
sepatered from data serialization
- error semantics:
transaction, ACID
o exactly-once (== 1) bank transaction
o at-least-once (>= 1) muss passieren, mehrfach tut nicht weh (seiteneffekte) SunRPC
o at-most-once (<= 1) logging of not important data, video conferneces
o reduncancy (> 1) data replication (rundancy)
o quatsch (< 1 == 0)
o cachable im Proxy
- flexibility:
o I/O functions overloading (Pth)
o accept+handle, ... application handles
server functionality and can fork, spawn, etc.
- asynchronous vs. synchronous
Ideee: intern immer asynchrouns
aber in API wrapper function
rpc_call == rpc_send+rpc_wait+rpc_result
und auch rpc_abort
trotzdem wird beide male ein timeout vorgesehen
- AMP:
backends
local
shm
pipe
unix socket
network
udp
tcp
ttcp
- Fragmentation?
- entweder AMP high-level aufgrund von backend-infos (MTU!) + Defragnmentierung
- oder error aufgrund backend
- Optimales Backend Protocol:
- server akzepotiert N protocols
- client requested M (<= N) protocols
- library sucht optimalen raus (ev. abhaengig von der Message-Size)
- Backend Protocols:
- eventuell connection caching?
- bei network problems reconnect
- bei idle time shutdown + reconnect later
- AMP:
o optional authentication
o optional packet signing
- AMP+XDS:
o optional encryption
o optional compression
- wo ist encryption und compression?
in beiden mit callbacks vorsehen, da beide
unabhaengig von einander imn Einsatz sein koennen!
- XDS:
o functionality:
encoding
decoding
o Representation Differences
- byte order (little vs. big endian)
- character set (ASCII, Latin-1, Unicode, EBCDIC)
- floating point (IEEEE ...)
o Description:
- self-describing (ASN.1) type+value
- overhead
+ bei decode eine verification machen
- non self-describing
+ no overhead
+ tut nicht weh, da xds_decode() sowieso parameter aufzaehlen muss
o Welche Seite tut was:
- send: into fixed set
recv: from fixed set
+ filter/minitoring moeglich auf netzwerk seite
- eventuell doppleter overhead (C+S:little endian, fixed set: big endian)
- send: nothing, but append own type
recv: into own set if type different
+ no overhead
- no filtering easily possible
o callbacks erlauben encoding/decoding of own data structures/types
o backends:
XDR (SunRPC)
ASN.1 (X.509)
XXX (CORBA)
XML (XML-RPC)
- Firewalls? Sollen die Filtern koennen
Encryption nur von Data, nicht von Meta-Data
- Proxies?
- Sowohl AMP als auch XDR muessen backends von
Application implementieren lassen!
- bei AMP muessen Statistiken verfuegbar sein!
- Rround-Trip-Time
- Datandurchsatz (Throughput)
siehe auch SNMP, Multilink PPP (MP+)
- Denial Of Service auf Server Seite?
- High-Level Library basierende auf AMP:
- Service Location
- Load Balancing
- Fail Over
- IPv6 in AMP unterstuetzen
- Multicasting in AMP unterstuetzen (trivial I/O seitig,
aber muss bei error semantics beruecksichtig werden)
=========================================================================================
Examples:
amp.h:
typedef struct {
void *data;
size_t len;
} amp_data_t;
Server:
#include "amp.h"
#include "xds.h"
#include "pth.h"
amp_data_t foo(void *ctx, amp_data_t in)
{
amp_data_t out;
xds_ctx_t *xds = (xds_ctx_t *)ctx;
int i;
char *cp;
int rv;
xds_decode(xds, in.data, in.len, "%d%s", &i, &cp);
/* i und cp verarbeiten -> rv */
xds_encode(xds, &out, "%d", rv);
return out;
}
amp_server_t *s;
amp_connection_t *c;
xds_ctx_t *xds;
xds = xds_create(XDS_ASN1);
s = amp_server_create();
amp_server_configure(s, AMP_LISTEN, "udp", "server1.de.cw.net", 12345);
amp_server_configure(s, AMP_LISTEN, "tcp", "any" 12345);
amp_server_configure(s, AMP_LISTEN, "unix", 12345);
amp_server_configure(s, AMP_LISTEN, "shm", vp, vplen);
amp_server_configure(s, AMP_ERROR_SEMANTIC, AMP_ATLEASTONCE);
amp_server_configure(s, AMP_IOCB_ACCEPT, pth_accept);
amp_server_configure(s, AMP_IOCB_LISTEN, pth_listen);
amp_server_configure(s, AMP_IOCB_READ, pth_read);
amp_server_configure(s, AMP_IOCB_WRITE, pth_write);
:
amp_server_register(s, "foo", foo, xds);
amp_server_register(s, "bar", bar, NULL);
amp_server_register(s, "baz", baz, NULL);
amp_server_register(s, "quux", quux, NULL);
amp_server_listen(s);
/* synchronous */
amp_server_loop(s);
/* asynchronous */
while ((c = amp_server_accept(s))) {
pth_t *t;
if ((t = pth_spawn(...)) == NULL) {
amp_server_dispatch(c);
}
pth_wait(t);
}
amp_server_unlisten(s);
amp_server_destroy(s);
xds_destroy(xds);
Client:
amp_client_t *c;
amp_connection_t *co;
xds_ctx_t *xds;
amp_data_t in, out;
int i = ...;
char *cp = ...;
int rv;
c = amp_client_create();
xds = xds_create(XDS_ASN1);
amp_client_configure(c, AMP_CONNECT, "udp", "server1.de.cw.net", 12345);
amp_client_configure(c, AMP_CONNECT, "tcp", "server1.de.cw.net", 12345);
co = amp_client_connect(c);
xds_encode(xds, in, "%d%s", i, cp);
out = amp_client_call(co, "foo", in);
xds_decode(xds, out, "%d", &rv);
/* ... rv ... */
amp_client_disconnect(co);
xds_destroy(xds);
amp_client_destroy(c);