Add helper functions for info_callback and msg_callback.

This is getting a little repetitive.

Change-Id: Ib0fa8ab10149557c2d728b88648381b9368221d9
Reviewed-on: https://boringssl-review.googlesource.com/8126
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index e101a4f..11c9b65 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -305,12 +305,9 @@
     return ret;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC,
-                      kChangeCipherSpec, sizeof(kChangeCipherSpec), ssl,
-                      ssl->msg_callback_arg);
-  }
-
+  ssl_do_msg_callback(ssl, 1 /* write */, ssl->version,
+                      SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+                      sizeof(kChangeCipherSpec));
   return 1;
 }
 
@@ -388,11 +385,9 @@
     ssl->init_num -= todo;
   } while (ssl->init_num > 0);
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(
-        1 /* write */, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-        (size_t)(ssl->init_off + ssl->init_num), ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_HANDSHAKE,
+                      ssl->init_buf->data,
+                      (size_t)(ssl->init_off + ssl->init_num));
 
   ssl->init_off = 0;
   ssl->init_num = 0;
@@ -637,11 +632,10 @@
   if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
     goto err;
   }
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-                    ssl->init_num + DTLS1_HM_HEADER_LENGTH, ssl,
-                    ssl->msg_callback_arg);
-  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+                      ssl->init_buf->data,
+                      ssl->init_num + DTLS1_HM_HEADER_LENGTH);
 
   pitem_free(item);
   dtls1_hm_fragment_free(frag);
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 0b1701a..b61a139 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -133,28 +133,19 @@
 
 int dtls1_connect(SSL *ssl) {
   BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
   int ret = -1;
-  int new_state, state, skip = 0;
+  int state, skip = 0;
 
   assert(ssl->handshake_func == dtls1_connect);
   assert(!ssl->server);
   assert(SSL_IS_DTLS(ssl));
 
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
   for (;;) {
     state = ssl->state;
 
     switch (ssl->state) {
       case SSL_ST_CONNECT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
 
         if (ssl->init_buf == NULL) {
           buf = BUF_MEM_new();
@@ -439,9 +430,7 @@
 
         ret = 1;
 
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
 
         /* done with handshaking */
         ssl->d1->handshake_read_seq = 0;
@@ -455,22 +444,18 @@
     }
 
     /* did we do anything? */
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if ((cb != NULL) && (ssl->state != state)) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_CONNECT_LOOP, 1);
-        ssl->state = new_state;
-      }
+    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+      int new_state = ssl->state;
+      ssl->state = state;
+      ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1);
+      ssl->state = new_state;
     }
     skip = 0;
   }
 
 end:
   BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_CONNECT_EXIT, ret);
-  }
+  ssl_do_info_callback(ssl, SSL_CB_CONNECT_EXIT, ret);
   return ret;
 }
 
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 2a1017d..c3f03bc 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -223,11 +223,8 @@
     return -1;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
-                      ssl, ssl->msg_callback_arg);
-  }
-
+  ssl_do_msg_callback(ssl, 0 /* read */, ssl->version,
+                      SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1);
   return 1;
 }
 
@@ -257,7 +254,6 @@
   int al, ret;
   unsigned int n;
   SSL3_RECORD *rr;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
 
   if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
        type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
@@ -323,25 +319,16 @@
       goto f_err;
     }
 
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
-                      ssl->msg_callback_arg);
-    }
+    ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_ALERT,
+                        rr->data, 2);
+
     const uint8_t alert_level = rr->data[0];
     const uint8_t alert_descr = rr->data[1];
     rr->length -= 2;
     rr->data += 2;
 
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      uint16_t alert = (alert_level << 8) | alert_descr;
-      cb(ssl, SSL_CB_READ_ALERT, alert);
-    }
+    uint16_t alert = (alert_level << 8) | alert_descr;
+    ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert);
 
     if (alert_level == SSL3_AL_WARNING) {
       if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
@@ -508,22 +495,11 @@
     BIO_flush(ssl->wbio);
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_ALERT,
-                      ssl->s3->send_alert, 2, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT,
+                      ssl->s3->send_alert, 2);
 
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  if (cb != NULL) {
-    int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
-    cb(ssl, SSL_CB_WRITE_ALERT, alert);
-  }
+  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
 
   return 1;
 }
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 5d17415..372ed56 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -130,29 +130,20 @@
 
 int dtls1_accept(SSL *ssl) {
   BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
   uint32_t alg_a;
   int ret = -1;
-  int new_state, state, skip = 0;
+  int state, skip = 0;
 
   assert(ssl->handshake_func == dtls1_accept);
   assert(ssl->server);
   assert(SSL_IS_DTLS(ssl));
 
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
   for (;;) {
     state = ssl->state;
 
     switch (ssl->state) {
       case SSL_ST_ACCEPT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
 
         if (ssl->init_buf == NULL) {
           buf = BUF_MEM_new();
@@ -411,9 +402,7 @@
 
         ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
 
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
 
         ret = 1;
 
@@ -430,21 +419,17 @@
         goto end;
     }
 
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if (cb != NULL && ssl->state != state) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
-        ssl->state = new_state;
-      }
+    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+      int new_state = ssl->state;
+      ssl->state = state;
+      ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1);
+      ssl->state = new_state;
     }
     skip = 0;
   }
 
 end:
   BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
-  }
+  ssl_do_info_callback(ssl, SSL_CB_ACCEPT_EXIT, ret);
   return ret;
 }
diff --git a/ssl/dtls_record.c b/ssl/dtls_record.c
index eaf6df7..71d7ba5 100644
--- a/ssl/dtls_record.c
+++ b/ssl/dtls_record.c
@@ -195,10 +195,8 @@
     return ssl_open_record_discard;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
-                      DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in,
+                      DTLS1_RT_HEADER_LENGTH);
 
   uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1];
   if (epoch != ssl->d1->r_epoch ||
@@ -299,10 +297,8 @@
 
   *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len;
 
-  if (ssl->msg_callback) {
-    ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
-                      DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out,
+                      DTLS1_RT_HEADER_LENGTH);
 
   return 1;
 }
diff --git a/ssl/internal.h b/ssl/internal.h
index 20cf1cb..b35ccc5 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -626,6 +626,16 @@
 size_t ssl_max_handshake_message_len(const SSL *ssl);
 
 
+/* Callbacks. */
+
+/* ssl_do_info_callback calls |ssl|'s info callback, if set. */
+void ssl_do_info_callback(const SSL *ssl, int type, int value);
+
+/* ssl_do_msg_callback calls |ssl|'s message callback, if set. */
+void ssl_do_msg_callback(SSL *ssl, int is_write, int version, int content_type,
+                         const void *buf, size_t len);
+
+
 /* Transport buffers. */
 
 /* ssl_read_buffer returns a pointer to contents of the read buffer. */
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index d5e304d..3c1e619 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -142,11 +142,9 @@
   }
 
   if (n == ssl->init_num) {
-    if (ssl->msg_callback) {
-      ssl->msg_callback(1, ssl->version, type, ssl->init_buf->data,
-                      (size_t)(ssl->init_off + ssl->init_num), ssl,
-                      ssl->msg_callback_arg);
-    }
+    ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, type,
+                        ssl->init_buf->data,
+                        (size_t)(ssl->init_off + ssl->init_num));
     return 1;
   }
 
@@ -382,10 +380,8 @@
 
   /* We have now received a complete message. */
   ssl->s3->tmp.message_complete = 1;
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-                      ssl->init_buf->length, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+                      ssl->init_buf->data, ssl->init_buf->length);
 
   static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
   if (!ssl->server && ssl->init_buf->length == sizeof(kHelloRequest) &&
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index c341b2e..84322a9 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -172,28 +172,19 @@
 
 int ssl3_connect(SSL *ssl) {
   BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
   int ret = -1;
-  int new_state, state, skip = 0;
+  int state, skip = 0;
 
   assert(ssl->handshake_func == ssl3_connect);
   assert(!ssl->server);
   assert(!SSL_IS_DTLS(ssl));
 
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
   for (;;) {
     state = ssl->state;
 
     switch (ssl->state) {
       case SSL_ST_CONNECT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
 
         if (ssl->init_buf == NULL) {
           buf = BUF_MEM_new();
@@ -513,11 +504,8 @@
         }
 
         ret = 1;
-        /* ssl->server=0; */
 
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
 
         goto end;
 
@@ -527,22 +515,18 @@
         goto end;
     }
 
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if (cb != NULL && ssl->state != state) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_CONNECT_LOOP, 1);
-        ssl->state = new_state;
-      }
+    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+      int new_state = ssl->state;
+      ssl->state = state;
+      ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1);
+      ssl->state = new_state;
     }
     skip = 0;
   }
 
 end:
   BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_CONNECT_EXIT, ret);
-  }
+  ssl_do_info_callback(ssl, SSL_CB_CONNECT_EXIT, ret);
   return ret;
 }
 
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 5d8435e..4b5138e 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -334,11 +334,8 @@
     return -1;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
-                      ssl, ssl->msg_callback_arg);
-  }
-
+  ssl_do_msg_callback(ssl, 0 /* read */, ssl->version,
+                      SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1);
   return 1;
 }
 
@@ -379,7 +376,6 @@
   int al, i, ret;
   unsigned int n;
   SSL3_RECORD *rr;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
 
   if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
        type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
@@ -466,10 +462,8 @@
     }
     ssl->s3->hello_request_len = 0;
 
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, kHelloRequest,
-                      sizeof(kHelloRequest), ssl, ssl->msg_callback_arg);
-    }
+    ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+                        kHelloRequest, sizeof(kHelloRequest));
 
     if (ssl->renegotiate_mode == ssl_renegotiate_ignore) {
       goto start;
@@ -510,25 +504,16 @@
       goto f_err;
     }
 
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
-                        ssl->msg_callback_arg);
-    }
+    ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_ALERT,
+                        rr->data, 2);
+
     const uint8_t alert_level = rr->data[0];
     const uint8_t alert_descr = rr->data[1];
     rr->length -= 2;
     rr->data += 2;
 
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      uint16_t alert = (alert_level << 8) | alert_descr;
-      cb(ssl, SSL_CB_READ_ALERT, alert);
-    }
+    uint16_t alert = (alert_level << 8) | alert_descr;
+    ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert);
 
     if (alert_level == SSL3_AL_WARNING) {
       if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
@@ -618,22 +603,11 @@
     BIO_flush(ssl->wbio);
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_ALERT,
-                      ssl->s3->send_alert, 2, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT,
+                      ssl->s3->send_alert, 2);
 
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  if (cb != NULL) {
-    int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
-    cb(ssl, SSL_CB_WRITE_ALERT, alert);
-  }
+  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
 
   return 1;
 }
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 0bac8ba..d7c0d0a 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -176,28 +176,19 @@
 int ssl3_accept(SSL *ssl) {
   BUF_MEM *buf = NULL;
   uint32_t alg_a;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
   int ret = -1;
-  int new_state, state, skip = 0;
+  int state, skip = 0;
 
   assert(ssl->handshake_func == ssl3_accept);
   assert(ssl->server);
   assert(!SSL_IS_DTLS(ssl));
 
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
   for (;;) {
     state = ssl->state;
 
     switch (ssl->state) {
       case SSL_ST_ACCEPT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
 
         if (ssl->init_buf == NULL) {
           buf = BUF_MEM_new();
@@ -520,9 +511,7 @@
 
         ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
 
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
 
         ret = 1;
         goto end;
@@ -533,11 +522,10 @@
         goto end;
     }
 
-    if (!ssl->s3->tmp.reuse_message && !skip && cb != NULL &&
-        ssl->state != state) {
-      new_state = ssl->state;
+    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+      int new_state = ssl->state;
       ssl->state = state;
-      cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
+      ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1);
       ssl->state = new_state;
     }
     skip = 0;
@@ -545,9 +533,7 @@
 
 end:
   BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
-  }
+  ssl_do_info_callback(ssl, SSL_CB_ACCEPT_EXIT, ret);
   return ret;
 }
 
@@ -630,10 +616,9 @@
                                   CBS_len(&v2_client_hello))) {
     return -1;
   }
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello),
-                    CBS_len(&v2_client_hello), ssl, ssl->msg_callback_arg);
-  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL2_VERSION, 0,
+                      CBS_data(&v2_client_hello), CBS_len(&v2_client_hello));
 
   if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
       !CBS_get_u16(&v2_client_hello, &version) ||
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index ec30dcf..9c8e723 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2711,6 +2711,27 @@
   return 1;
 }
 
+void ssl_do_info_callback(const SSL *ssl, int type, int value) {
+  void (*cb)(const SSL *ssl, int type, int value) = NULL;
+  if (ssl->info_callback != NULL) {
+    cb = ssl->info_callback;
+  } else if (ssl->ctx->info_callback != NULL) {
+    cb = ssl->ctx->info_callback;
+  }
+
+  if (cb != NULL) {
+    cb(ssl, type, value);
+  }
+}
+
+void ssl_do_msg_callback(SSL *ssl, int is_write, int version, int content_type,
+                         const void *buf, size_t len) {
+  if (ssl->msg_callback != NULL) {
+    ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+                      ssl->msg_callback_arg);
+  }
+}
+
 int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; }
diff --git a/ssl/tls_record.c b/ssl/tls_record.c
index 45d9940..7036c87 100644
--- a/ssl/tls_record.c
+++ b/ssl/tls_record.c
@@ -226,10 +226,8 @@
     return ssl_open_record_partial;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
-                      SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in,
+                      SSL3_RT_HEADER_LENGTH);
 
   /* Decrypt the body. */
   size_t plaintext_len;
@@ -335,11 +333,8 @@
 
   *out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len;
 
-  if (ssl->msg_callback) {
-    ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
-                      SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
-
+  ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out,
+                      SSL3_RT_HEADER_LENGTH);
   return 1;
 }