int handShake()

in nanofi/src/sitetosite/CRawSocketProtocol.c [99:263]


int handShake(struct CRawSiteToSiteClient * client) {
  if (client->_peer_state != ESTABLISHED) {
    return -1;
  }

  CIDGenerator gen;
  gen.implementation_ = CUUID_DEFAULT_IMPL;
  generate_uuid(&gen, client->_commsIdentifier);
  client->_commsIdentifier[36]='\0';

  int ret = writeUTF(client->_commsIdentifier, strlen(client->_commsIdentifier), False, client->_peer->_stream);

  if (ret <= 0) {
    return -1;
  }

  uint32_t prop_size;
  PropertyValue *current, *tmp, * properties = NULL;

  current = (PropertyValue *)malloc(sizeof(PropertyValue));

  current->name = HandShakePropertyStr[GZIP];
  strncpy(current->value, "false", sizeof(current->value));
  current->value[sizeof(current->value) - 1] = '\0';

  HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

  current = (PropertyValue *)malloc(sizeof(PropertyValue));

  current->name = HandShakePropertyStr[PORT_IDENTIFIER];
  strncpy(current->value, client->_port_id_str, sizeof(current->value));
  current->value[sizeof(current->value) - 1] = '\0';

  HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

  current = (PropertyValue *)malloc(sizeof(PropertyValue));

  current->name = HandShakePropertyStr[REQUEST_EXPIRATION_MILLIS];
  sprintf(current->value, "%"PRIu64, client->_timeout);

  HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

  prop_size = 3;

  if (client->_currentVersion >= 5) {
    if (client->_batch_count > 0) {
      current = (PropertyValue *)malloc(sizeof(PropertyValue));

      current->name = HandShakePropertyStr[BATCH_COUNT];
      sprintf(current->value, "%"PRIu64, client->_batch_count);

      HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

      prop_size++;
    }
    if (client->_batch_size > 0) {
      current = (PropertyValue *)malloc(sizeof(PropertyValue));

      current->name = HandShakePropertyStr[BATCH_SIZE];
      sprintf(current->value, "%"PRIu64, client->_batch_size);

      HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

      prop_size++;
    }
    if (client->_batch_duration > 0) {
      current = (PropertyValue *)malloc(sizeof(PropertyValue));

      current->name = HandShakePropertyStr[BATCH_DURATION];
      sprintf(current->value, "%"PRIu64, client->_batch_duration);

      HASH_ADD_KEYPTR(hh, properties, current->name, strlen(current->name), current);

      prop_size++;
    }
  }

  int ret_val = 0;

  if (client->_currentVersion >= 3) {
    const char * urlstr = getURL(client->_peer);
    ret = writeUTF(urlstr, strlen(urlstr), False, client->_peer->_stream);
    if (ret <= 0) {
      ret_val = -1;
    }
  }

  if (ret_val == 0) {
    ret = write_uint32_t(prop_size, client->_peer->_stream);
  }
  if (ret <= 0) {
    ret_val = -1;
  }

  HASH_ITER(hh, properties, current, tmp) {
    if (ret_val == 0 && writeUTF(current->name, strlen(current->name), False, client->_peer->_stream) <= 0) {
      ret_val = -1;
    }
    if (ret_val == 0 && writeUTF(current->value, strlen(current->value), False, client->_peer->_stream) <= 0) {
      ret_val = -1;
    }
    logc(debug, "Site2Site Protocol Send handshake properties %s %s", current->name, current->value);
    HASH_DEL(properties, current);
    free(current);
  }

  if (ret_val < 0) {
    logc(err, "%s", "Failed to transfer handshake properties");
    return -1;
  }

  RespondCode code;

  ret = readResponse(client, &code);

  if (ret <= 0) {
    logc(err, "failed to receive response code from server");
    return -1;
  }

  RespondCodeContext *resCode = getRespondCodeContext(code);

  if (resCode == NULL) {
    logc(err, "Received invalid respond code: %d", code);
    return -1;
  }

  if (resCode->hasDescription) {
    uint32_t utflen;
    ret = readUTFLen(&utflen, client->_peer->_stream);
    if (ret <= 0)
      return -1;

    memset(client->_description_buffer, 0, utflen+1);
    ret = readUTF(client->_description_buffer, utflen, client->_peer->_stream);
    if (ret <= 0)
      return -1;
  }

  const char * error = "";

  switch (code) {
    case PROPERTIES_OK:
      logc(debug, "%s", "Site2Site HandShake Completed");
      client->_peer_state = HANDSHAKED;
      return 0;
    case PORT_NOT_IN_VALID_STATE:
      error = "in invalid state";
      break;
    case UNKNOWN_PORT:
      error = "an unknown port";
      break;
    case PORTS_DESTINATION_FULL:
      error = "full";
      break;
    // Unknown error
    default:
      logc(err, "HandShake Failed because of unknown respond code %d", code);
      return -1;
  }

  // All known error cases handled here
  logc(err, "Site2Site HandShake Failed because destination port, %s, is %s", client->_port_id_str, error);
  return -2;
}