Changeset: d7ad96722fc6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d7ad96722fc6
Modified Files:
clients/mapilib/connect.c
clients/mapilib/connect_openssl.c
clients/mapilib/mapi_intern.h
common/stream/openssl_stream.c
common/stream/stream.h
Branch: monetdburl
Log Message:
It almost works
diffs (192 lines):
diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c
--- a/clients/mapilib/connect.c
+++ b/clients/mapilib/connect.c
@@ -469,7 +469,7 @@ mapi_handshake(Mapi mid)
/* consume server challenge */
len = mnstr_read_block(mid->from, buf, 1, sizeof(buf));
- check_stream(mid, mid->from, "Connection terminated while starting",
(mid->blk.eos = true, mid->error));
+ check_stream(mid, mid->from, "Connection terminated while starting
handshake", (mid->blk.eos = true, mid->error));
assert(len < sizeof(buf));
buf[len] = 0;
diff --git a/clients/mapilib/connect_openssl.c
b/clients/mapilib/connect_openssl.c
--- a/clients/mapilib/connect_openssl.c
+++ b/clients/mapilib/connect_openssl.c
@@ -181,18 +181,18 @@ wrap_tls(Mapi mid, SOCKET sock)
return croak(mid, __func__, "BIO_up_ref bio");
}
// On error: free 'bio' twice
- stream *rstream = openssl_stream(hostcolonport, bio);
+ stream *rstream = openssl_rstream(hostcolonport, bio);
if (rstream == NULL || mnstr_errnr(rstream) != MNSTR_NO__ERROR) {
BIO_free_all(bio); // drops first ref
BIO_free_all(bio); // drops second ref
- return croak(mid, __func__, "openssl_stream: %s",
mnstr_peek_error(rstream));
+ return croak(mid, __func__, "openssl_rstream: %s",
mnstr_peek_error(rstream));
}
// On error: free 'bio' and close 'rstream'.
- stream *wstream = openssl_stream(hostcolonport, bio);
+ stream *wstream = openssl_wstream(hostcolonport, bio);
if (wstream == NULL || mnstr_errnr(wstream) != MNSTR_NO__ERROR) {
BIO_free_all(bio);
mnstr_close(rstream);
- return croak(mid, __func__, "openssl_stream: %s",
mnstr_peek_error(wstream));
+ return croak(mid, __func__, "openssl_wstream: %s",
mnstr_peek_error(wstream));
}
// On error: free 'rstream' and 'wstream'.
msg = mapi_set_streams(mid, rstream, wstream);
diff --git a/clients/mapilib/mapi_intern.h b/clients/mapilib/mapi_intern.h
--- a/clients/mapilib/mapi_intern.h
+++ b/clients/mapilib/mapi_intern.h
@@ -271,8 +271,11 @@ void mapi_log_record(Mapi mid, const cha
if (msg != NULL) mapi_log_record(mid, msg); \
mapi_log_record(mid, mnstr_peek_error(s)); \
mapi_log_record(mid, __func__); \
+ if (mnstr_peek_error(s)) \
+ mapi_printError((mid), __func__, MTIMEOUT, "%s:
%s", (msg), mnstr_peek_error(s)); \
+ else \
+ mapi_printError((mid), __func__, MTIMEOUT,
"%s", (msg)); \
close_connection(mid); \
- mapi_setError((mid), (msg), __func__, MTIMEOUT); \
return (e); \
} \
} while (0)
diff --git a/common/stream/openssl_stream.c b/common/stream/openssl_stream.c
--- a/common/stream/openssl_stream.c
+++ b/common/stream/openssl_stream.c
@@ -13,11 +13,117 @@
#include "stream_internal.h"
#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+static ssize_t ostream_read(stream *restrict s, void *restrict buf, size_t
elmsize, size_t cnt);
+static ssize_t ostream_write(stream *restrict s, const void *restrict buf,
size_t elmsize, size_t cnt);
+static void ostream_close(stream *s);
+static int ostream_flush(stream *s, mnstr_flush_level flush_level);
stream *
-openssl_stream(const char *hostname, BIO *bio)
+openssl_rstream(const char *host_colon_port, BIO *bio)
+{
+ stream *s = openssl_wstream(host_colon_port, bio);
+ if (s != NULL)
+ s->readonly = true;
+ return s;
+}
+stream *
+openssl_wstream(const char *host_colon_port, BIO *bio)
+{
+ assert(bio);
+
+ stream *s = create_stream(host_colon_port);
+ if (s == NULL)
+ return NULL;
+
+ s->stream_data.p = bio;
+ s->readonly = false;
+ s->binary = true;
+ s->read = ostream_read;
+ s->write = ostream_write;
+ s->close = ostream_close;
+ s->flush = ostream_flush;
+
+ return s;
+}
+
+static ssize_t
+ostream_error(stream *s, mnstr_error_kind kind)
+{
+ unsigned long err = ERR_get_error();
+ const char *msg = ERR_reason_error_string(err);
+ mnstr_set_error(s, kind, "%s", msg);
+ return -1;
+}
+
+
+ssize_t
+ostream_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t
cnt)
{
- (void)bio;
- mnstr_set_open_error(hostname, 0, "not implemented yet");
- return NULL;
+ BIO *bio = (BIO*)s->stream_data.p;
+
+ char *start = (char*)buf;
+ size_t size = elmsize * cnt;
+ if (size == 0)
+ return 0;
+
+ // iterate in order to read a complete number of items
+ size_t pos = 0;
+ do {
+ size_t nread;
+ if (!BIO_read_ex(bio, start + pos, size - pos, &nread))
+ return ostream_error(s, MNSTR_READ_ERROR);
+ if (nread == 0) {
+ s->eof = 0;
+ break;
+ }
+ pos += nread;
+
+ // adjust pos to the smallest multiple of elmsize.
+ // example 1: size=4 pos=7 (-7)%4=1, newsize=8
+ size_t delta = (-pos) % size;
+ if (size - pos > delta)
+ size = pos + delta;
+ } while (pos < size);
+
+ return (ssize_t) (pos / elmsize);
}
+
+ssize_t
+ostream_write(stream *restrict s, const void *restrict buf, size_t elmsize,
size_t cnt)
+{
+ BIO *bio = (BIO*)s->stream_data.p;
+
+ char *start = (char*)buf;
+ size_t size = elmsize * cnt;
+ size_t pos = 0;
+ while (pos < size) {
+ size_t nwritten;
+ if (!BIO_write_ex(bio, start + pos, size - pos, &nwritten))
+ return ostream_error(s, MNSTR_WRITE_ERROR);
+ if (nwritten == 0 && !BIO_should_retry(bio))
+ break;
+ pos += nwritten;
+ }
+
+ return (ssize_t) (pos / elmsize);
+}
+
+void
+ostream_close(stream *s)
+{
+ BIO *bio = (BIO*) s->stream_data.p;
+ BIO_free(bio);
+ s->stream_data.p = NULL;
+}
+
+int
+ostream_flush(stream *s, mnstr_flush_level flush_level)
+{
+ (void)s;
+ (void)flush_level;
+ mnstr_set_error(s, MNSTR_WRITE_ERROR, "flush not implemented");
+ return -1;
+}
+
diff --git a/common/stream/stream.h b/common/stream/stream.h
--- a/common/stream/stream.h
+++ b/common/stream/stream.h
@@ -278,7 +278,8 @@ stream_export stream *mapi_request_downl
stream_export stream *byte_counting_stream(stream *wrapped, uint64_t *counter);
#ifdef HAVE_OPENSSL
-stream_export stream *openssl_stream(const char *hostname, BIO *bio);
+stream_export stream *openssl_rstream(const char *hostname, BIO *bio);
+stream_export stream *openssl_wstream(const char *hostname, BIO *bio);
#endif
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]