Index: ossp-pkg/sa/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/sa/ChangeLog,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/sa/ChangeLog,v' 2>/dev/null --- ChangeLog 2002/10/30 19:01:31 1.3 +++ ChangeLog 2002/10/30 19:09:35 1.4 @@ -13,6 +13,16 @@ Changes between 0.9.2 and 0.9.3 (11-Oct-2002 to xx-Oct-2002) + o Added a function sa_sendf(3) which is a convience wrapper + to sa_send(3) for sending formatted data. This is similar to what + sa_writef(3) does for sa_write(3). The difference is just that + sa_writef(3) does not need a temporary buffer (because can use the + stream I/O write buffer) while sa_sendf(3) requires a temporary + buffer for its operation. Nevertheless the temporary buffer is + allocated only if the formatted data is large. For small formatted + data a fast stack-based buffer is used for higher performance. + [Ralf S. Engelschall] + o Finished implementation of test suite in order to cover mostly all functionality of the API. [Ralf S. Engelschall] Index: ossp-pkg/sa/sa.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.c,v rcsdiff -q -kk '-r1.64' '-r1.65' -u '/v/ossp/cvs/ossp-pkg/sa/sa.c,v' 2>/dev/null --- sa.c 2002/10/30 09:21:52 1.64 +++ sa.c 2002/10/30 19:09:35 1.65 @@ -2183,6 +2183,46 @@ return SA_OK; } +/* send formatted string to socket (convinience function) */ +sa_rc_t sa_sendf(sa_t *sa, sa_addr_t *raddr, const char *cpFmt, ...) +{ + va_list ap; + size_t nBuf; + char *cpBuf; + sa_rc_t rv; + char caBuf[1024]; + + /* argument sanity check(s) */ + if (sa == NULL || raddr == NULL || cpFmt == NULL) + return SA_RC(SA_ERR_ARG); + + /* format string into temporary buffer */ + va_start(ap, cpFmt); + nBuf = sa_mvsnprintf(NULL, NULL, cpFmt, ap); + va_end(ap); + if ((nBuf+1) > sizeof(caBuf)) { + /* requires a larger buffer, so allocate dynamically */ + if ((cpBuf = (char *)malloc(nBuf+1)) == NULL) + return SA_RC(SA_ERR_SYS); + } + else { + /* fits into small buffer, so allocate statically */ + cpBuf = caBuf; + } + va_start(ap, cpFmt); + sa_mvsnprintf(cpBuf, nBuf+1, cpFmt, ap); + va_end(ap); + + /* pass-through to sa_send() */ + rv = sa_send(sa, cpBuf, nBuf, NULL, raddr); + + /* cleanup dynamically allocated buffer */ + if ((nBuf+1) > sizeof(caBuf)) + free(cpBuf); + + return rv; +} + /* return error string */ char *sa_error(sa_rc_t rv) { Index: ossp-pkg/sa/sa.h RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.h,v rcsdiff -q -kk '-r1.32' '-r1.33' -u '/v/ossp/cvs/ossp-pkg/sa/sa.h,v' 2>/dev/null --- sa.h 2002/10/30 08:42:16 1.32 +++ sa.h 2002/10/30 19:09:35 1.33 @@ -200,6 +200,7 @@ /* socket input/output operations (datagram communication) */ sa_rc_t sa_recv (sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t **raddr); sa_rc_t sa_send (sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *raddr); +sa_rc_t sa_sendf (sa_t *sa, sa_addr_t *raddr, const char *fmt, ...); /* error handling operations */ char *sa_error (sa_rc_t rv); Index: ossp-pkg/sa/sa.pod RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.pod,v rcsdiff -q -kk '-r1.35' '-r1.36' -u '/v/ossp/cvs/ossp-pkg/sa/sa.pod,v' 2>/dev/null --- sa.pod 2002/10/30 18:43:08 1.35 +++ sa.pod 2002/10/30 19:09:35 1.36 @@ -96,7 +96,8 @@ =item B: sa_recv, -sa_send. +sa_send, +sa_sendf. =item B: @@ -428,10 +429,10 @@ Possible values for I are: C (affecting sa_accept(3)), C (affecting sa_connect(3)), C (affecting sa_read(3), sa_readln(3) and sa_recv(3)) -and C (affecting sa_write(3), sa_writef(3) and -sa_send(3)). 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>. +and C (affecting sa_write(3), sa_writef(3), +sa_send(3), and sa_sendf(3)). 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 @@ -774,6 +775,26 @@ Example: C +=item sa_rc_t B(sa_t *I, sa_addr_t *I, const char *I, ...) + +Send formatted data data to remote address via socket. + +This formats a string according to the printf(3)-style format +specification I and sends the result to the socket as a single +piece of data chunk. In case of a partial socket write, the not written +data of the formatted string is internally discarded. + +The underlying string formatting engine is just a minimal one and for +security and independence reasons intentionally not directly based on +s[n]printf(3). It understands only the following format specifications: +"C<%%>", "C<%c>" (C), "C<%s>" (C) and "C<%d>" (C) +without any precision and padding possibilities. It is intended for +minimal formatting only. If you need more sophisticated formatting, you +have to format first into an own buffer via s[n]printf(3) and then send +this to the remote address via sa_send(3) instead. + +Example: C + =back =head2 Socket Error Handling Index: ossp-pkg/sa/sa_test.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa_test.c,v rcsdiff -q -kk '-r1.19' '-r1.20' -u '/v/ossp/cvs/ossp-pkg/sa/sa_test.c,v' 2>/dev/null --- sa_test.c 2002/10/30 18:46:22 1.19 +++ sa_test.c 2002/10/30 19:09:35 1.20 @@ -289,8 +289,7 @@ if (strncmp(buf_srv, MSG_UDP_CLT_REQUEST, l) != 0) ts_test_fail(TS_CTX, "server: got \"%s\", expected \"%s\"", buf_srv, MSG_UDP_CLT_REQUEST); - ex(SRV, sa_send(sa_srv, MSG_UDP_SRV_RESPONSE, - strlen(MSG_UDP_SRV_RESPONSE), &l, saa_clt)); + ex(SRV, sa_sendf(sa_srv, saa_clt, "%s", MSG_UDP_SRV_RESPONSE)); ex(SRV, sa_addr_destroy(saa_clt)); /* destroy server socket and die */ @@ -311,8 +310,7 @@ /* communicate with server */ ex(CLT, sa_addr_create(&saa_srv)); ex(CLT, sa_addr_u2a(saa_srv, "inet://127.0.0.1:12345#udp")); - ex(CLT, sa_send(sa_clt, MSG_UDP_CLT_REQUEST, - strlen(MSG_UDP_CLT_REQUEST), &l, saa_srv)); + ex(CLT, sa_sendf(sa_clt, saa_srv, "%s", MSG_UDP_CLT_REQUEST)); ex(CLT, sa_addr_destroy(saa_srv)); ex(CLT, sa_recv(sa_clt, buf_clt, sizeof(buf_clt), &l, &saa_srv)); if (strncmp(buf_clt, MSG_UDP_SRV_RESPONSE, l) != 0)