LCOV - code coverage report
Current view: top level - core/tsi - fake_transport_security.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 257 277 92.8 %
Date: 2015-12-10 22:15:08 Functions: 22 22 100.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2015, Google Inc.
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are
       8             :  * met:
       9             :  *
      10             :  *     * Redistributions of source code must retain the above copyright
      11             :  * notice, this list of conditions and the following disclaimer.
      12             :  *     * Redistributions in binary form must reproduce the above
      13             :  * copyright notice, this list of conditions and the following disclaimer
      14             :  * in the documentation and/or other materials provided with the
      15             :  * distribution.
      16             :  *     * Neither the name of Google Inc. nor the names of its
      17             :  * contributors may be used to endorse or promote products derived from
      18             :  * this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : #include "src/core/tsi/fake_transport_security.h"
      35             : 
      36             : #include <stdlib.h>
      37             : #include <string.h>
      38             : 
      39             : #include <grpc/support/log.h>
      40             : #include <grpc/support/port_platform.h>
      41             : #include <grpc/support/useful.h>
      42             : #include "src/core/tsi/transport_security.h"
      43             : 
      44             : /* --- Constants. ---*/
      45             : #define TSI_FAKE_FRAME_HEADER_SIZE 4
      46             : #define TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE 64
      47             : #define TSI_FAKE_DEFAULT_FRAME_SIZE 16384
      48             : 
      49             : /* --- Structure definitions. ---*/
      50             : 
      51             : /* a frame is encoded like this:
      52             :    | size |     data    |
      53             :    where the size field value is the size of the size field plus the size of
      54             :    the data encoded in little endian on 4 bytes.  */
      55             : typedef struct {
      56             :   unsigned char *data;
      57             :   size_t size;
      58             :   size_t allocated_size;
      59             :   size_t offset;
      60             :   int needs_draining;
      61             : } tsi_fake_frame;
      62             : 
      63             : typedef enum {
      64             :   TSI_FAKE_CLIENT_INIT = 0,
      65             :   TSI_FAKE_SERVER_INIT = 1,
      66             :   TSI_FAKE_CLIENT_FINISHED = 2,
      67             :   TSI_FAKE_SERVER_FINISHED = 3,
      68             :   TSI_FAKE_HANDSHAKE_MESSAGE_MAX = 4
      69             : } tsi_fake_handshake_message;
      70             : 
      71             : typedef struct {
      72             :   tsi_handshaker base;
      73             :   int is_client;
      74             :   tsi_fake_handshake_message next_message_to_send;
      75             :   int needs_incoming_message;
      76             :   tsi_fake_frame incoming;
      77             :   tsi_fake_frame outgoing;
      78             :   tsi_result result;
      79             : } tsi_fake_handshaker;
      80             : 
      81             : typedef struct {
      82             :   tsi_frame_protector base;
      83             :   tsi_fake_frame protect_frame;
      84             :   tsi_fake_frame unprotect_frame;
      85             :   size_t max_frame_size;
      86             : } tsi_fake_frame_protector;
      87             : 
      88             : /* --- Utils. ---*/
      89             : 
      90             : static const char *tsi_fake_handshake_message_strings[] = {
      91             :     "CLIENT_INIT", "SERVER_INIT", "CLIENT_FINISHED", "SERVER_FINISHED"};
      92             : 
      93         430 : static const char *tsi_fake_handshake_message_to_string(int msg) {
      94         430 :   if (msg < 0 || msg >= TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
      95           0 :     gpr_log(GPR_ERROR, "Invalid message %d", msg);
      96           0 :     return "UNKNOWN";
      97             :   }
      98         430 :   return tsi_fake_handshake_message_strings[msg];
      99             : }
     100             : 
     101         428 : static tsi_result tsi_fake_handshake_message_from_string(
     102             :     const char *msg_string, tsi_fake_handshake_message *msg) {
     103             :   tsi_fake_handshake_message i;
     104        1070 :   for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) {
     105        1070 :     if (strncmp(msg_string, tsi_fake_handshake_message_strings[i],
     106             :                 strlen(tsi_fake_handshake_message_strings[i])) == 0) {
     107         428 :       *msg = i;
     108         428 :       return TSI_OK;
     109             :     }
     110             :   }
     111           0 :   gpr_log(GPR_ERROR, "Invalid handshake message.");
     112           0 :   return TSI_DATA_CORRUPTED;
     113             : }
     114             : 
     115      370998 : static gpr_uint32 load32_little_endian(const unsigned char *buf) {
     116     1112994 :   return ((gpr_uint32)(buf[0]) | (gpr_uint32)(buf[1] << 8) |
     117      741996 :           (gpr_uint32)(buf[2] << 16) | (gpr_uint32)(buf[3] << 24));
     118             : }
     119             : 
     120      370324 : static void store32_little_endian(gpr_uint32 value, unsigned char *buf) {
     121      370324 :   buf[3] = (unsigned char)((value >> 24) & 0xFF);
     122      370324 :   buf[2] = (unsigned char)((value >> 16) & 0xFF);
     123      370324 :   buf[1] = (unsigned char)((value >> 8) & 0xFF);
     124      370324 :   buf[0] = (unsigned char)((value)&0xFF);
     125      370324 : }
     126             : 
     127      558311 : static void tsi_fake_frame_reset(tsi_fake_frame *frame, int needs_draining) {
     128      558311 :   frame->offset = 0;
     129      558311 :   frame->needs_draining = needs_draining;
     130      558311 :   if (!needs_draining) frame->size = 0;
     131      558311 : }
     132             : 
     133             : /* Returns 1 if successful, 0 otherwise. */
     134      371428 : static int tsi_fake_frame_ensure_size(tsi_fake_frame *frame) {
     135      371428 :   if (frame->data == NULL) {
     136         216 :     frame->allocated_size = frame->size;
     137         216 :     frame->data = malloc(frame->allocated_size);
     138         216 :     if (frame->data == NULL) return 0;
     139      371212 :   } else if (frame->size > frame->allocated_size) {
     140         858 :     unsigned char *new_data = realloc(frame->data, frame->size);
     141         858 :     if (new_data == NULL) {
     142           0 :       free(frame->data);
     143           0 :       frame->data = NULL;
     144           0 :       return 0;
     145             :     }
     146         858 :     frame->data = new_data;
     147         858 :     frame->allocated_size = frame->size;
     148             :   }
     149      371428 :   return 1;
     150             : }
     151             : 
     152             : /* This method should not be called if frame->needs_framing is not 0.  */
     153     2664774 : static tsi_result fill_frame_from_bytes(const unsigned char *incoming_bytes,
     154             :                                         size_t *incoming_bytes_size,
     155             :                                         tsi_fake_frame *frame) {
     156     2664774 :   size_t available_size = *incoming_bytes_size;
     157     2664774 :   size_t to_read_size = 0;
     158     2664774 :   const unsigned char *bytes_cursor = incoming_bytes;
     159             : 
     160     2664774 :   if (frame->needs_draining) return TSI_INTERNAL_ERROR;
     161     2664774 :   if (frame->data == NULL) {
     162         708 :     frame->allocated_size = TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE;
     163         708 :     frame->data = malloc(frame->allocated_size);
     164         708 :     if (frame->data == NULL) return TSI_OUT_OF_RESOURCES;
     165             :   }
     166             : 
     167     2664774 :   if (frame->offset < TSI_FAKE_FRAME_HEADER_SIZE) {
     168      676197 :     to_read_size = TSI_FAKE_FRAME_HEADER_SIZE - frame->offset;
     169      676197 :     if (to_read_size > available_size) {
     170             :       /* Just fill what we can and exit. */
     171      305199 :       memcpy(frame->data + frame->offset, bytes_cursor, available_size);
     172      305199 :       bytes_cursor += available_size;
     173      305199 :       frame->offset += available_size;
     174      305199 :       *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
     175      305199 :       return TSI_INCOMPLETE_DATA;
     176             :     }
     177      370998 :     memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
     178      370998 :     bytes_cursor += to_read_size;
     179      370998 :     frame->offset += to_read_size;
     180      370998 :     available_size -= to_read_size;
     181      370998 :     frame->size = load32_little_endian(frame->data);
     182      370998 :     if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
     183             :   }
     184             : 
     185     2359575 :   to_read_size = frame->size - frame->offset;
     186     2359575 :   if (to_read_size > available_size) {
     187     2173122 :     memcpy(frame->data + frame->offset, bytes_cursor, available_size);
     188     2173122 :     frame->offset += available_size;
     189     2173122 :     bytes_cursor += available_size;
     190     2173122 :     *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
     191     2173122 :     return TSI_INCOMPLETE_DATA;
     192             :   }
     193      186453 :   memcpy(frame->data + frame->offset, bytes_cursor, to_read_size);
     194      186453 :   bytes_cursor += to_read_size;
     195      186453 :   *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes);
     196      186453 :   tsi_fake_frame_reset(frame, 1 /* needs_draining */);
     197      186453 :   return TSI_OK;
     198             : }
     199             : 
     200             : /* This method should not be called if frame->needs_framing is 0.  */
     201      375888 : static tsi_result drain_frame_to_bytes(unsigned char *outgoing_bytes,
     202             :                                        size_t *outgoing_bytes_size,
     203             :                                        tsi_fake_frame *frame) {
     204      375888 :   size_t to_write_size = frame->size - frame->offset;
     205      375888 :   if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
     206      375888 :   if (*outgoing_bytes_size < to_write_size) {
     207        4888 :     memcpy(outgoing_bytes, frame->data + frame->offset, *outgoing_bytes_size);
     208        4888 :     frame->offset += *outgoing_bytes_size;
     209        4888 :     return TSI_INCOMPLETE_DATA;
     210             :   }
     211      371000 :   memcpy(outgoing_bytes, frame->data + frame->offset, to_write_size);
     212      371000 :   *outgoing_bytes_size = to_write_size;
     213      371000 :   tsi_fake_frame_reset(frame, 0 /* needs_draining */);
     214      371000 :   return TSI_OK;
     215             : }
     216             : 
     217         430 : static tsi_result bytes_to_frame(unsigned char *bytes, size_t bytes_size,
     218             :                                  tsi_fake_frame *frame) {
     219         430 :   frame->offset = 0;
     220         430 :   frame->size = bytes_size + TSI_FAKE_FRAME_HEADER_SIZE;
     221         430 :   if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES;
     222         430 :   store32_little_endian((gpr_uint32)frame->size, frame->data);
     223         430 :   memcpy(frame->data + TSI_FAKE_FRAME_HEADER_SIZE, bytes, bytes_size);
     224         430 :   tsi_fake_frame_reset(frame, 1 /* needs draining */);
     225         430 :   return TSI_OK;
     226             : }
     227             : 
     228         998 : static void tsi_fake_frame_destruct(tsi_fake_frame *frame) {
     229         998 :   if (frame->data != NULL) free(frame->data);
     230         998 : }
     231             : 
     232             : /* --- tsi_frame_protector methods implementation. ---*/
     233             : 
     234      855162 : static tsi_result fake_protector_protect(tsi_frame_protector *self,
     235             :                                          const unsigned char *unprotected_bytes,
     236             :                                          size_t *unprotected_bytes_size,
     237             :                                          unsigned char *protected_output_frames,
     238             :                                          size_t *protected_output_frames_size) {
     239      855162 :   tsi_result result = TSI_OK;
     240      855162 :   tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
     241             :   unsigned char frame_header[TSI_FAKE_FRAME_HEADER_SIZE];
     242      855162 :   tsi_fake_frame *frame = &impl->protect_frame;
     243      855162 :   size_t saved_output_size = *protected_output_frames_size;
     244      855162 :   size_t drained_size = 0;
     245      855162 :   size_t *num_bytes_written = protected_output_frames_size;
     246      855162 :   *num_bytes_written = 0;
     247             : 
     248             :   /* Try to drain first. */
     249      855162 :   if (frame->needs_draining) {
     250        1590 :     drained_size = saved_output_size - *num_bytes_written;
     251        1590 :     result =
     252             :         drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
     253        1590 :     *num_bytes_written += drained_size;
     254        1590 :     protected_output_frames += drained_size;
     255        1590 :     if (result != TSI_OK) {
     256         786 :       if (result == TSI_INCOMPLETE_DATA) {
     257         786 :         *unprotected_bytes_size = 0;
     258         786 :         result = TSI_OK;
     259             :       }
     260         786 :       return result;
     261             :     }
     262             :   }
     263             : 
     264             :   /* Now process the unprotected_bytes. */
     265      854376 :   if (frame->needs_draining) return TSI_INTERNAL_ERROR;
     266      854376 :   if (frame->size == 0) {
     267             :     /* New frame, create a header. */
     268      185349 :     size_t written_in_frame_size = 0;
     269      185349 :     store32_little_endian((gpr_uint32)impl->max_frame_size, frame_header);
     270      185349 :     written_in_frame_size = TSI_FAKE_FRAME_HEADER_SIZE;
     271      185349 :     result = fill_frame_from_bytes(frame_header, &written_in_frame_size, frame);
     272      185349 :     if (result != TSI_INCOMPLETE_DATA) {
     273           0 :       gpr_log(GPR_ERROR, "fill_frame_from_bytes returned %s",
     274             :               tsi_result_to_string(result));
     275           0 :       return result;
     276             :     }
     277             :   }
     278      854376 :   result =
     279             :       fill_frame_from_bytes(unprotected_bytes, unprotected_bytes_size, frame);
     280      854376 :   if (result != TSI_OK) {
     281      853572 :     if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
     282      853572 :     return result;
     283             :   }
     284             : 
     285             :   /* Try to drain again. */
     286         804 :   if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
     287         804 :   if (frame->offset != 0) return TSI_INTERNAL_ERROR;
     288         804 :   drained_size = saved_output_size - *num_bytes_written;
     289         804 :   result = drain_frame_to_bytes(protected_output_frames, &drained_size, frame);
     290         804 :   *num_bytes_written += drained_size;
     291         804 :   if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
     292         804 :   return result;
     293             : }
     294             : 
     295      185446 : static tsi_result fake_protector_protect_flush(
     296             :     tsi_frame_protector *self, unsigned char *protected_output_frames,
     297             :     size_t *protected_output_frames_size, size_t *still_pending_size) {
     298      185446 :   tsi_result result = TSI_OK;
     299      185446 :   tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
     300      185446 :   tsi_fake_frame *frame = &impl->protect_frame;
     301      185446 :   if (!frame->needs_draining) {
     302             :     /* Create a short frame. */
     303      184545 :     frame->size = frame->offset;
     304      184545 :     frame->offset = 0;
     305      184545 :     frame->needs_draining = 1;
     306      184545 :     store32_little_endian((gpr_uint32)frame->size,
     307             :                           frame->data); /* Overwrite header. */
     308             :   }
     309      185446 :   result = drain_frame_to_bytes(protected_output_frames,
     310             :                                 protected_output_frames_size, frame);
     311      185446 :   if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
     312      185446 :   *still_pending_size = frame->size - frame->offset;
     313      185446 :   return result;
     314             : }
     315             : 
     316     1625405 : static tsi_result fake_protector_unprotect(
     317             :     tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
     318             :     size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
     319             :     size_t *unprotected_bytes_size) {
     320     1625405 :   tsi_result result = TSI_OK;
     321     1625405 :   tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
     322     1625405 :   tsi_fake_frame *frame = &impl->unprotect_frame;
     323     1625405 :   size_t saved_output_size = *unprotected_bytes_size;
     324     1625405 :   size_t drained_size = 0;
     325     1625405 :   size_t *num_bytes_written = unprotected_bytes_size;
     326     1625405 :   *num_bytes_written = 0;
     327             : 
     328             :   /* Try to drain first. */
     329     1625405 :   if (frame->needs_draining) {
     330             :     /* Go past the header if needed. */
     331        2397 :     if (frame->offset == 0) frame->offset = TSI_FAKE_FRAME_HEADER_SIZE;
     332        2397 :     drained_size = saved_output_size - *num_bytes_written;
     333        2397 :     result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
     334        2397 :     unprotected_bytes += drained_size;
     335        2397 :     *num_bytes_written += drained_size;
     336        2397 :     if (result != TSI_OK) {
     337         784 :       if (result == TSI_INCOMPLETE_DATA) {
     338         784 :         *protected_frames_bytes_size = 0;
     339         784 :         result = TSI_OK;
     340             :       }
     341         784 :       return result;
     342             :     }
     343             :   }
     344             : 
     345             :   /* Now process the protected_bytes. */
     346     1624621 :   if (frame->needs_draining) return TSI_INTERNAL_ERROR;
     347     1624621 :   result = fill_frame_from_bytes(protected_frames_bytes,
     348             :                                  protected_frames_bytes_size, frame);
     349     1624621 :   if (result != TSI_OK) {
     350     1439400 :     if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
     351     1439400 :     return result;
     352             :   }
     353             : 
     354             :   /* Try to drain again. */
     355      185221 :   if (!frame->needs_draining) return TSI_INTERNAL_ERROR;
     356      185221 :   if (frame->offset != 0) return TSI_INTERNAL_ERROR;
     357      185221 :   frame->offset = TSI_FAKE_FRAME_HEADER_SIZE; /* Go past the header. */
     358      185221 :   drained_size = saved_output_size - *num_bytes_written;
     359      185221 :   result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame);
     360      185221 :   *num_bytes_written += drained_size;
     361      185221 :   if (result == TSI_INCOMPLETE_DATA) result = TSI_OK;
     362      185221 :   return result;
     363             : }
     364             : 
     365         282 : static void fake_protector_destroy(tsi_frame_protector *self) {
     366         282 :   tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self;
     367         282 :   tsi_fake_frame_destruct(&impl->protect_frame);
     368         282 :   tsi_fake_frame_destruct(&impl->unprotect_frame);
     369         282 :   free(self);
     370         282 : }
     371             : 
     372             : static const tsi_frame_protector_vtable frame_protector_vtable = {
     373             :     fake_protector_protect, fake_protector_protect_flush,
     374             :     fake_protector_unprotect, fake_protector_destroy,
     375             : };
     376             : 
     377             : /* --- tsi_handshaker methods implementation. ---*/
     378             : 
     379         537 : static tsi_result fake_handshaker_get_bytes_to_send_to_peer(
     380             :     tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) {
     381         537 :   tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
     382         537 :   tsi_result result = TSI_OK;
     383         537 :   if (impl->needs_incoming_message || impl->result == TSI_OK) {
     384         107 :     *bytes_size = 0;
     385         107 :     return TSI_OK;
     386             :   }
     387         430 :   if (!impl->outgoing.needs_draining) {
     388         430 :     tsi_fake_handshake_message next_message_to_send =
     389         430 :         impl->next_message_to_send + 2;
     390         430 :     const char *msg_string =
     391         430 :         tsi_fake_handshake_message_to_string(impl->next_message_to_send);
     392         430 :     result = bytes_to_frame((unsigned char *)msg_string, strlen(msg_string),
     393             :                             &impl->outgoing);
     394         430 :     if (result != TSI_OK) return result;
     395         430 :     if (next_message_to_send > TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
     396         107 :       next_message_to_send = TSI_FAKE_HANDSHAKE_MESSAGE_MAX;
     397             :     }
     398         430 :     if (tsi_tracing_enabled) {
     399           0 :       gpr_log(GPR_INFO, "%s prepared %s.",
     400           0 :               impl->is_client ? "Client" : "Server",
     401           0 :               tsi_fake_handshake_message_to_string(impl->next_message_to_send));
     402             :     }
     403         430 :     impl->next_message_to_send = next_message_to_send;
     404             :   }
     405         430 :   result = drain_frame_to_bytes(bytes, bytes_size, &impl->outgoing);
     406         430 :   if (result != TSI_OK) return result;
     407         644 :   if (!impl->is_client &&
     408         214 :       impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
     409             :     /* We're done. */
     410         107 :     if (tsi_tracing_enabled) {
     411           0 :       gpr_log(GPR_INFO, "Server is done.");
     412             :     }
     413         107 :     impl->result = TSI_OK;
     414             :   } else {
     415         323 :     impl->needs_incoming_message = 1;
     416             :   }
     417         430 :   return TSI_OK;
     418             : }
     419             : 
     420         428 : static tsi_result fake_handshaker_process_bytes_from_peer(
     421             :     tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
     422         428 :   tsi_result result = TSI_OK;
     423         428 :   tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
     424         428 :   tsi_fake_handshake_message expected_msg = impl->next_message_to_send - 1;
     425             :   tsi_fake_handshake_message received_msg;
     426             : 
     427         428 :   if (!impl->needs_incoming_message || impl->result == TSI_OK) {
     428           0 :     *bytes_size = 0;
     429           0 :     return TSI_OK;
     430             :   }
     431         428 :   result = fill_frame_from_bytes(bytes, bytes_size, &impl->incoming);
     432         428 :   if (result != TSI_OK) return result;
     433             : 
     434             :   /* We now have a complete frame. */
     435         428 :   result = tsi_fake_handshake_message_from_string(
     436         428 :       (const char *)impl->incoming.data + TSI_FAKE_FRAME_HEADER_SIZE,
     437             :       &received_msg);
     438         428 :   if (result != TSI_OK) {
     439           0 :     impl->result = result;
     440           0 :     return result;
     441             :   }
     442         428 :   if (received_msg != expected_msg) {
     443           0 :     gpr_log(GPR_ERROR, "Invalid received message (%s instead of %s)",
     444             :             tsi_fake_handshake_message_to_string(received_msg),
     445             :             tsi_fake_handshake_message_to_string(expected_msg));
     446             :   }
     447         428 :   if (tsi_tracing_enabled) {
     448           0 :     gpr_log(GPR_INFO, "%s received %s.", impl->is_client ? "Client" : "Server",
     449             :             tsi_fake_handshake_message_to_string(received_msg));
     450             :   }
     451         428 :   tsi_fake_frame_reset(&impl->incoming, 0 /* needs_draining */);
     452         428 :   impl->needs_incoming_message = 0;
     453         428 :   if (impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) {
     454             :     /* We're done. */
     455         107 :     if (tsi_tracing_enabled) {
     456           0 :       gpr_log(GPR_INFO, "%s is done.", impl->is_client ? "Client" : "Server");
     457             :     }
     458         107 :     impl->result = TSI_OK;
     459             :   }
     460         428 :   return TSI_OK;
     461             : }
     462             : 
     463        1823 : static tsi_result fake_handshaker_get_result(tsi_handshaker *self) {
     464        1823 :   tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
     465        1823 :   return impl->result;
     466             : }
     467             : 
     468         214 : static tsi_result fake_handshaker_extract_peer(tsi_handshaker *self,
     469             :                                                tsi_peer *peer) {
     470         214 :   tsi_result result = tsi_construct_peer(1, peer);
     471         214 :   if (result != TSI_OK) return result;
     472         214 :   result = tsi_construct_string_peer_property_from_cstring(
     473             :       TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_FAKE_CERTIFICATE_TYPE,
     474             :       &peer->properties[0]);
     475         214 :   if (result != TSI_OK) tsi_peer_destruct(peer);
     476         214 :   return result;
     477             : }
     478             : 
     479         214 : static tsi_result fake_handshaker_create_frame_protector(
     480             :     tsi_handshaker *self, size_t *max_protected_frame_size,
     481             :     tsi_frame_protector **protector) {
     482         214 :   *protector = tsi_create_fake_protector(max_protected_frame_size);
     483         214 :   if (*protector == NULL) return TSI_OUT_OF_RESOURCES;
     484         214 :   return TSI_OK;
     485             : }
     486             : 
     487         217 : static void fake_handshaker_destroy(tsi_handshaker *self) {
     488         217 :   tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self;
     489         217 :   tsi_fake_frame_destruct(&impl->incoming);
     490         217 :   tsi_fake_frame_destruct(&impl->outgoing);
     491         217 :   free(self);
     492         217 : }
     493             : 
     494             : static const tsi_handshaker_vtable handshaker_vtable = {
     495             :     fake_handshaker_get_bytes_to_send_to_peer,
     496             :     fake_handshaker_process_bytes_from_peer, fake_handshaker_get_result,
     497             :     fake_handshaker_extract_peer, fake_handshaker_create_frame_protector,
     498             :     fake_handshaker_destroy,
     499             : };
     500             : 
     501         217 : tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
     502         217 :   tsi_fake_handshaker *impl = calloc(1, sizeof(tsi_fake_handshaker));
     503         217 :   impl->base.vtable = &handshaker_vtable;
     504         217 :   impl->is_client = is_client;
     505         217 :   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
     506         217 :   if (is_client) {
     507         109 :     impl->needs_incoming_message = 0;
     508         109 :     impl->next_message_to_send = TSI_FAKE_CLIENT_INIT;
     509             :   } else {
     510         108 :     impl->needs_incoming_message = 1;
     511         108 :     impl->next_message_to_send = TSI_FAKE_SERVER_INIT;
     512             :   }
     513         217 :   return &impl->base;
     514             : }
     515             : 
     516         282 : tsi_frame_protector *tsi_create_fake_protector(
     517             :     size_t *max_protected_frame_size) {
     518         282 :   tsi_fake_frame_protector *impl = calloc(1, sizeof(tsi_fake_frame_protector));
     519         282 :   if (impl == NULL) return NULL;
     520         282 :   impl->max_frame_size = (max_protected_frame_size == NULL)
     521             :                              ? TSI_FAKE_DEFAULT_FRAME_SIZE
     522         282 :                              : *max_protected_frame_size;
     523         282 :   impl->base.vtable = &frame_protector_vtable;
     524         282 :   return &impl->base;
     525             : }

Generated by: LCOV version 1.11