Revert "Migrate Bio to RefCounted."

This reverts commit 56ab75f53c3c188367bfea8383871ddf33b4609a. It broke
the return value of BIO_free, which existing callers seems to rely on
(even though that return value is pretty horrific).

Reverting for now so we can add tests and reland a fixed version.

Change-Id: Id287aaa1ac0dbe0917ff1ac3bcd75429ebce2474
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89627
Reviewed-by: Lily Chen <chlily@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Xiangfei Ding <xfding@google.com>
Commit-Queue: Xiangfei Ding <xfding@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/bio/bio.cc b/crypto/bio/bio.cc
index e3c3ee3..7f6a052 100644
--- a/crypto/bio/bio.cc
+++ b/crypto/bio/bio.cc
@@ -33,43 +33,51 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class =
     CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
 
-Bio::Bio(const BIO_METHOD *m) : RefCounted(CheckSubClass()), method(m) {
-  CRYPTO_new_ex_data(&ex_data);
-}
-
 BIO *BIO_new(const BIO_METHOD *method) {
-  UniquePtr<Bio> ret(New<Bio>(method));
+  Bio *ret = NewZeroed<Bio>();
   if (ret == nullptr) {
     return nullptr;
   }
 
-  if (method->create != nullptr && !method->create(ret.get())) {
+  ret->method = method;
+  ret->shutdown = 1;
+  ret->references = 1;
+  CRYPTO_new_ex_data(&ret->ex_data);
+
+  if (method->create != nullptr && !method->create(ret)) {
+    Delete(ret);
     return nullptr;
   }
 
-  return ret.release();
-}
-
-Bio::~Bio() {
-  if (method != nullptr && method->destroy != nullptr) {
-    method->destroy(this);
-  }
-  CRYPTO_free_ex_data(&g_ex_data_class, &ex_data);
-  BIO_free(BIO_pop(this));
+  return ret;
 }
 
 int BIO_free(BIO *bio) {
-  if (bio == nullptr) {
-    return 1;
-  }
   auto *impl = FromOpaque(bio);
-  impl->DecRefInternal();
+
+  Bio *next_bio;
+
+  for (; impl != nullptr; impl = next_bio) {
+    if (!CRYPTO_refcount_dec_and_test_zero(&impl->references)) {
+      return 0;
+    }
+
+    next_bio = FromOpaque(BIO_pop(impl));
+
+    if (impl->method != nullptr && impl->method->destroy != nullptr) {
+      impl->method->destroy(impl);
+    }
+
+    CRYPTO_free_ex_data(&g_ex_data_class, &impl->ex_data);
+    Delete(impl);
+  }
   return 1;
 }
 
 int BIO_up_ref(BIO *bio) {
   auto *impl = FromOpaque(bio);
-  impl->UpRefInternal();
+
+  CRYPTO_refcount_inc(&impl->references);
   return 1;
 }
 
diff --git a/crypto/bio/internal.h b/crypto/bio/internal.h
index 77cd8a8..6c9e02e 100644
--- a/crypto/bio/internal.h
+++ b/crypto/bio/internal.h
@@ -20,7 +20,6 @@
 #include <openssl/ex_data.h>
 
 #include "../internal.h"
-#include "../mem_internal.h"
 
 #if !defined(OPENSSL_NO_SOCK)
 #if !defined(OPENSSL_WINDOWS)
@@ -53,10 +52,8 @@
 
 BSSL_NAMESPACE_BEGIN
 
-class Bio : public bio_st, public RefCounted<Bio> {
+class Bio : public bio_st {
  public:
-  explicit Bio(const BIO_METHOD *m);
-
   const BIO_METHOD *method;
   CRYPTO_EX_DATA ex_data;
 
@@ -64,26 +61,23 @@
   // integrated into |flags|, to save memory.
 
   // init is non-zero if this |BIO| has been initialised.
-  int init = 0;
+  int init;
   // shutdown is often used by specific |BIO_METHOD|s to determine whether
   // they own some underlying resource. This flag can often be controlled by
   // |BIO_set_close|. For example, whether an fd BIO closes the underlying fd
   // when it, itself, is closed.
-  int shutdown = 1;
-  int flags = 0;
-  int retry_reason = 0;
+  int shutdown;
+  int flags;
+  int retry_reason;
   // num is a BIO-specific value. For example, in fd BIOs it's used to store a
   // file descriptor.
-  int num = 0;
-  void *ptr = nullptr;
+  int num;
+  bssl::CRYPTO_refcount_t references;
+  void *ptr;
   // next_bio points to the next |BIO| in a chain. This |BIO| owns a reference
   // to |next_bio|.
-  Bio *next_bio = nullptr;  // used by filter BIOs
-  uint64_t num_read = 0, num_write = 0;
-
- private:
-  friend RefCounted;
-  ~Bio();
+  Bio *next_bio;  // used by filter BIOs
+  uint64_t num_read, num_write;
 };
 
 #if !defined(OPENSSL_NO_SOCK)