Permalink
Browse files

I think this fixes the coredumps in https clients when the caller tim…

…es out and cancels. Fixed some compilation problems with gcc 4.6.1 on Linux. Version bump up to 3.1.14. Fix okws-test-touch-all so that it works when pub/pubd launches successfully (due to an OKWS_PUB_JAIL env set) --- this fix, is really just to break it better :). Add some features to static and to okwc3 for helping to debug.

git-svn-id: svn://okws.org/okws2/devel/3.1@5787 7d287422-6eea-da11-b677-00123f2a783a
  • Loading branch information...
1 parent 096fde0 commit 0e38dc1343c63bea42e5e42e9dcfef8f2bab342f max committed Oct 25, 2011
Showing with 144 additions and 69 deletions.
  1. +34 −24 client/okwcmain3.T
  2. +2 −2 configure.in
  3. +1 −1 contrib/okws-test-touch-all.sh
  4. +1 −1 libokssl/proxy.T
  5. +87 −35 libokssl/sslcon.T
  6. +1 −1 libpub/okws_sfs.h
  7. +1 −1 ssld/okssld.T
  8. +4 −0 test/system/static.T
  9. +13 −4 xmlrpcc/gencfile.C
View
@@ -21,7 +21,7 @@ void
usage ()
{
warn << "usage: okwc [-c] [-t <timeout>] [-o <status>] [-p <proxy>] "
- << "<url> [<post-file>]\n";
+ << "[-n <n-attempts>] <url> [<post-file>]\n";
exit (1);
}
@@ -95,12 +95,13 @@ main3 (int argc, char **argv, evi_t ev)
int tmp;
ptr<my_factory_t> factory;
bool show_cookies (false);
+ size_t i (0), n (1);
}
okssl::init_ssl_internals ();
okwc_def_contlen *= 10;
- while ((ch = getopt (argc, argv, "ct:p:h:o:")) != -1) {
+ while ((ch = getopt (argc, argv, "ct:p:h:o:n:")) != -1) {
switch (ch) {
case 'c':
show_cookies = true;
@@ -115,6 +116,12 @@ main3 (int argc, char **argv, evi_t ev)
case 'h':
extra_headers.push_back (optarg);
break;
+ case 'n':
+ if (!convertint (optarg, &n)) {
+ warn << "bad number of attempts: " << n << "\n";
+ usage ();
+ }
+ break;
case 'o':
if (!convertint (optarg, &tmp)) {
warn << "Bad status " << optarg << ": must be an int!\n";
@@ -179,28 +186,31 @@ main3 (int argc, char **argv, evi_t ev)
cli = New refcounted<okwc3::agent_get_direct_t> (hostname, port, https,
factory);
}
-
- twait {
- cli->get (filename,
- connector::timeout (mkevent (status, resp), timeout),
- 1, NULL,
- post, &extra_headers);
- }
-
- aout << "status: " << status << "\n";
- if (status == HTTP_MOVEDTEMP || status == HTTP_MOVEDPERM) {
- aout << "Redirect to: " << (* resp->hdr () )["location"] << "\n";
- } else if (resp) {
- if (resp->body ()) {
- aout << "\nbody: " << resp->body () << "\n";
- }
- const okwc_cookie_set_t &cs = resp->incookies ();
- for (size_t i = 0; show_cookies && i < cs.size (); i++) {
- const cgi_t *c = cs[i];
- aout << "\nInCookie[" << i << "]:\n";
- for (const pair_t *p = c->lfirst (); p; p = c->lnext (p)) {
- str s = my_join (p->vals, ":");
- aout << " " << p->key << " -> " << s << "\n";
+
+ for (i = 0; i < n; i++) {
+
+ twait {
+ cli->get (filename,
+ connector::timeout (mkevent (status, resp), timeout),
+ 1, NULL,
+ post, &extra_headers);
+ }
+
+ aout << "status: " << status << "\n";
+ if (status == HTTP_MOVEDTEMP || status == HTTP_MOVEDPERM) {
+ aout << "Redirect to: " << (* resp->hdr () )["location"] << "\n";
+ } else if (resp) {
+ if (resp->body ()) {
+ aout << "\nbody: " << resp->body () << "\n";
+ }
+ const okwc_cookie_set_t &cs = resp->incookies ();
+ for (size_t i = 0; show_cookies && i < cs.size (); i++) {
+ const cgi_t *c = cs[i];
+ aout << "\nInCookie[" << i << "]:\n";
+ for (const pair_t *p = c->lfirst (); p; p = c->lnext (p)) {
+ str s = my_join (p->vals, ":");
+ aout << " " << p->key << " -> " << s << "\n";
+ }
}
}
}
View
@@ -4,10 +4,10 @@ dnl Process this file with autoconf to produce a configure script.
dnl
AC_INIT(config.h.in)
-AM_INIT_AUTOMAKE(okws, 3.1.14pre2)
+AM_INIT_AUTOMAKE(okws, 3.1.14)
AM_CONFIG_HEADER(config.h)
-SFS_INIT_LDVERSION(2700, SFSLITE_ABI_VERSION)
+SFS_INIT_LDVERSION(2800, SFSLITE_ABI_VERSION)
AC_CONFIG_MACRO_DIR([m4])
@@ -13,6 +13,6 @@ PROGS="okd/okd
for p in $PROGS
do
if [ -e $p ] ; then
- $p > /dev/null 2>&1
+ $p -? > /dev/null 2>&1
fi
done
View
@@ -299,7 +299,7 @@ namespace okssl {
// Older versions of SSL don't take a const SSL_CIPHER
// for get_bits and get_version, etc. So we need to use
// a non-const cipher to work around that issue.
- SSL_CIPHER *cipher;
+ const SSL_CIPHER *cipher;
strbuf b;
if (_ssl && (cipher = SSL_get_current_cipher(_ssl))) {
View
@@ -47,6 +47,7 @@ namespace okssl {
con_t::~con_t ()
{
SSL_free (_ssl);
+ _ssl = NULL;
}
@@ -55,7 +56,7 @@ namespace okssl {
factory_t::factory_t ()
{
SSLeay_add_ssl_algorithms ();
- SSL_METHOD *meth = SSLv23_client_method ();
+ const SSL_METHOD *meth = SSLv23_client_method ();
SSL_load_error_strings ();
_ctx = SSL_CTX_new (meth);
SSL_CTX_set_default_verify_paths (_ctx);
@@ -157,15 +158,22 @@ namespace okssl {
tvars {
suio *uio (bp->tosuio ());
bool ret (true);
- bool go (true);
+ bool go (false);
int rc;
bool need_read (false);
bool wait_for_write (true);
char buf[BUFSZ];
int err;
outcome_t oc;
+
+ // This is overkill, but in case there's a bug, we won't scribble
+ // over memory this way.
+ holdvar ptr<con_t> hold (mkref (_self));
}
+ // Key to set go=false, in case we're canceled while trying
+ // to establish an SSL connection. In that case, we want
+ // to early-out of this function!
twait { ssl_connect (connector::cnc (mkevent (go), ev)); }
if (!go) { ret = false; }
@@ -249,56 +257,100 @@ namespace okssl {
char buf[BUFSZ];
int err;
size_t tot (0);
+ outcome_t oc (OUTCOME_SUCC);
}
- twait { ssl_connect (connector::cnc (mkevent (go), ev)); }
+ twait { ssl_connect (connector::cnc (mkevent (go), ev, &oc)); }
+
+ // Just for sanity checking, don't go if we were cancelled.
+ if (oc != OUTCOME_SUCC) { assert (!go); }
+
+ // We loop for a read, not because we're going to do multiple reads,
+ // but because we might need to write before we can read. Also,
+ // only bother to enter this loop if there is data to read and room
+ // in the buffer. I'm not sure why we'd be called with a len=0, but
+ // guard against it here.
+ while (go && len > 0) {
+
+ go = false;
- while (go) {
if (need_write) {
- twait { _wfd->on (mkevent ()); }
- SSL_write (_ssl, buf, 0);
- } else if (len > 0) {
- if (wait_for_read) {
- twait { _rfd->on (mkevent ()); }
+ twait { _wfd->on (connector::cnc (mkevent (), ev, &oc)); }
+
+ // We always need to check that the outcome is not a cancel.
+ // In the case of cancel we shouldn't touch the buffer we're
+ // reading to ("out");
+ if (oc == OUTCOME_SUCC) {
+ SSL_write (_ssl, buf, 0);
+ go = true; // it's worth another trip through the loop!
}
- ret = SSL_read (_ssl, out, len);
- if (ret == 0) { _eof = true; }
- if (ret > 0) { tot += ret; }
+ } else {
- if (OKDBG2 (SSL_INDATA)) {
- if (ret > 0) {
- strbuf b;
- str s (reinterpret_cast<const char *> (out), ret);
- b << "++ SSL read: " << s << "\n";
- b.tosuio ()->output (2);
- }
+ // This should always stay so!
+ // Anyways, now we need to read something from the network.
+ assert (len > 0);
+
+ // In certain error cases, the SSL socket told us to wait
+ // so in this case, we do just that.
+ if (wait_for_read) {
+ twait { _rfd->on (connector::cnc (mkevent (), ev, &oc)); }
}
- if (ret < 0) {
- err = SSL_get_error (_ssl, ret);
- switch (err) {
- case SSL_ERROR_WANT_READ:
- wait_for_read = true;
- break;
- case SSL_ERROR_WANT_WRITE:
- need_write = true;
- break;
- default:
- ssl_complain ("SSL_write encountered an error: ");
- errno = EIO;
- go = false;
- break;
+ // Again, protect all forward progress by worrying about
+ // cancelation by our caller. If we were canceled, then
+ // don't do anything further.
+ if (oc == OUTCOME_SUCC) {
+
+ // This is the actual read.
+ ret = SSL_read (_ssl, out, len);
+
+ if (ret == 0) {
+ // On EOF, we're done reading, and nothing doin' here
+ _eof = true;
+
+ } else if (ret > 0) {
+ tot += ret; // keep this just for debugging.
+
+ // Debug output... say what data is actually read.
+ if (OKDBG2 (SSL_INDATA)) {
+ strbuf b;
+ str s (reinterpret_cast<const char *> (out), ret);
+ b << "++ SSL read: " << s << "\n";
+ b.tosuio ()->output (2);
+ }
+
+ } else {
+
+ // Handle various errors -- a lot of them are retryable
+ // and allow us to keep going in our network I/O.
+ err = SSL_get_error (_ssl, ret);
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ wait_for_read = true;
+ go = true;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ need_write = true;
+ go = true;
+ break;
+ default:
+ ssl_complain ("SSL_write encountered an error: ");
+ errno = EIO;
+ break;
+ }
}
- } else {
- go = false;
}
}
}
OKDBG4 (SSL_INDATA, CHATTER,
"leaving sslcon::read; rc=%zd; bytes=%zu\n", ret, tot);
+ if (oc != OUTCOME_SUCC) {
+ OKDBG3 (SSL_INDATA, CHATTER, "sslcon::read cancelled by caller");
+ }
+
ev->trigger (ret);
}
#undef BUFSZ
View
@@ -52,7 +52,7 @@
#define OKWS_VERSION_MAJOR 3
#define OKWS_VERSION_MINOR 1
#define OKWS_VERSION_PATCHLEVEL 14
-#define OKWS_VERSION_PRE 2
+#define OKWS_VERSION_PRE 100
#define OKWS_AT_VERSION(Maj,Min,Pat,Pre) \
(VERSION_FLATTEN(Maj,Min,Pat,Pre) <= \
View
@@ -498,7 +498,7 @@ namespace okssl {
bool
okssld_t::init_ssl ()
{
- SSL_METHOD *meth;
+ const SSL_METHOD *meth;
bool ret = false;
if (!init_ssl_internals ()) {
View
@@ -132,6 +132,7 @@ okclnt_static_t::process_T (okclnt2_t::proc_ev_t ev)
pub3::opts_t oe;
bool dump_stats (false);
bool html (true);
+ time_t delay (0);
}
static bool first_time = true;
@@ -155,8 +156,11 @@ okclnt_static_t::process_T (okclnt2_t::proc_ev_t ev)
if (cgi.blookup ("errobj")) { opts |= oe; }
if (cgi.blookup ("warninline")) { opts |= pub3::P_WARN_INLINE_NULL; }
if (cgi.blookup ("utf8json")) { opts |= pub3::P_UTF8_JSON; }
+ cgi.lookup ("delay", &delay);
dump_stats = cgi.blookup ("stats");
+ if (delay) { twait { delaycb (delay, 0, mkevent ()); } }
+
if (wss) { opts |= pub3::P_WSS; }
rc = true;
View
@@ -536,6 +536,8 @@ print_enum (const rpc_enum *s)
static void
print_struct (const rpc_struct *s)
{
+ const rpc_decl *dp = s->decls.base (), *ep = s->decls.lim ();
+ size_t num = ep - dp;
aout <<
"const strbuf &\n"
"rpc_print (const strbuf &sb, const " << s->id << " &obj, "
@@ -547,18 +549,25 @@ print_struct (const rpc_struct *s)
" sb << prefix;\n"
" sb << \"" << s->id << " \" << name << \" = \";\n"
" };\n"
- " const char *sep;\n"
" str npref;\n"
" if (prefix) {\n"
" npref = strbuf (\"%s \", prefix);\n"
- " sep = \"\";\n"
" sb << \"{\\n\";\n"
" }\n"
" else {\n"
- " sep = \", \";\n"
" sb << \"{ \";\n"
" }\n";
- const rpc_decl *dp = s->decls.base (), *ep = s->decls.lim ();
+
+ if (num > 1) {
+ aout <<
+ " const char *sep = NULL;\n"
+ " if (prefix) {\n"
+ " sep = \"\";\n"
+ " } else {\n"
+ " sep = \", \";\n"
+ " }\n" ;
+ }
+
if (dp < ep)
aout <<
" rpc_print (sb, obj." << dp->id << ", recdepth, "

0 comments on commit 0e38dc1

Please sign in to comment.