int main()

in wdtCmdLine.cpp [175:384]


int main(int argc, char *argv[]) {
#ifdef WDTFBINIT
  WDTFBINIT
#endif

  FLAGS_logtostderr = true;
  // Ugliness in gflags' api; to be able to use program name
  GFLAGS_NAMESPACE::SetArgv(argc, const_cast<const char **>(argv));
  GFLAGS_NAMESPACE::SetVersionString(Protocol::getFullVersion());
  usage.assign("WDT Warp-speed Data Transfer. v ");
  usage.append(GFLAGS_NAMESPACE::VersionString());
  usage.append(". Sample usage:\nTo transfer from srchost to desthost:\n\t");
  usage.append("ssh dsthost ");
  usage.append(GFLAGS_NAMESPACE::ProgramInvocationShortName());
  usage.append(" -directory destdir | ssh srchost ");
  usage.append(GFLAGS_NAMESPACE::ProgramInvocationShortName());
  usage.append(" -directory srcdir -");
  usage.append(
      "\nPassing - as the argument to wdt means start the sender and"
      " read the");
  usage.append(
      "\nconnection URL produced by the receiver, including encryption"
      " key, from stdin.");
  usage.append("\nUse --help to see all the options.");
  GFLAGS_NAMESPACE::SetUsageMessage(usage);
  GFLAGS_NAMESPACE::gflags_exitfunc = [](int code) {
    if (code == 0 || FLAGS_help) {
      // By default gflags exit 1 with --help and 0 for --version (good)
      // let's also exit(0) for --help to be like most gnu command line
      exit(0);
    }
    // error cases:
    if (FLAGS_exit_on_bad_flags) {
      printUsage();
      exit(code);
    }
    badGflagFound = true;
  };
  GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  if (badGflagFound) {
    // will only work for receivers
    WLOG(ERROR) << "Continuing despite bad flags";
  } else {
    // Only non -flag argument allowed so far is "-" meaning
    // Read url from stdin and start a sender
    if (argc > 2 || (argc == 2 && (argv[1][0] != '-' || argv[1][1] != '\0'))) {
      printUsage();
      std::cerr << "Error: argument should be - (to read url from stdin) "
                << "or no arguments" << std::endl;
      exit(1);
    }
  }
  signal(SIGPIPE, SIG_IGN);
  signal(SIGUSR1, sigUSR1Handler);

  std::string connectUrl;
  if (!badGflagFound && argc == 2) {
    std::getline(std::cin, connectUrl);
    if (connectUrl.empty()) {
      WLOG(ERROR)
          << "Sender unable to read connection url from stdin - exiting";
      return URI_PARSE_ERROR;
    }
  } else {
    connectUrl = FLAGS_connection_url;
  }

  // Might be a sub class (fbonly wdtCmdLine.cpp)
  Wdt &wdt = WDTCLASS::initializeWdt(FLAGS_app_name);
  if (FLAGS_print_options) {
    wdt.printWdtOptions(std::cout);
    return 0;
  }
  WdtOptions &options = wdt.getWdtOptions();

  ErrorCode retCode = OK;

  // Odd ball case of log parsing
  if (FLAGS_parse_transfer_log) {
    // Log parsing mode
    options.enable_download_resumption = true;
    TransferLogManager transferLogManager(options, FLAGS_directory);
    transferLogManager.openLog();
    bool success = transferLogManager.parseAndPrint();
    WLOG_IF(ERROR, !success) << "Transfer log parsing failed";
    transferLogManager.closeLog();
    return success ? OK : ERROR;
  }

  // General case : Sender or Receiver
  std::unique_ptr<WdtTransferRequest> reqPtr;
  if (connectUrl.empty()) {
    reqPtr = std::make_unique<WdtTransferRequest>(
        options.start_port, options.num_ports, FLAGS_directory);
    reqPtr->hostName = FLAGS_destination;
    reqPtr->transferId = FLAGS_transfer_id;
    if (!FLAGS_test_only_encryption_secret.empty()) {
      reqPtr->encryptionData =
          EncryptionParams(parseEncryptionType(options.encryption_type),
                           FLAGS_test_only_encryption_secret);
    }
    reqPtr->ivChangeInterval = options.iv_change_interval_mb * kMbToB;
    reqPtr->tls = wdt.isTlsEnabled();
  } else {
    reqPtr = std::make_unique<WdtTransferRequest>(connectUrl);
    if (reqPtr->errorCode != OK) {
      WLOG(ERROR) << "Invalid url \"" << connectUrl
                  << "\" : " << errorCodeToStr(reqPtr->errorCode);
      return ERROR;
    }
    reqPtr->directory = FLAGS_directory;
    WLOG(INFO) << "Parsed url as " << reqPtr->getLogSafeString();
  }
  WdtTransferRequest &req = *reqPtr;
  req.wdtNamespace = FLAGS_namespace;
  if (!FLAGS_dest_id.empty()) {
    req.destIdentifier = FLAGS_dest_id;
  }
  if (FLAGS_protocol_version > 0) {
    req.protocolVersion = FLAGS_protocol_version;
  }
  if (!FLAGS_hostname.empty()) {
    reqPtr->hostName = FLAGS_hostname;
  }
  if (FLAGS_destination.empty() && connectUrl.empty()) {
    Receiver receiver(req);
    WdtOptions &recOptions = receiver.getWdtOptions();
    if (FLAGS_run_as_daemon) {
      // Backward compatible with static ports, you can still get dynamic
      // daemon ports using -start_port 0 like before
      recOptions.static_ports = true;
    }
    if (!FLAGS_recovery_id.empty()) {
      // TODO: add a test for this
      recOptions.enable_download_resumption = true;
      receiver.setRecoveryId(FLAGS_recovery_id);
    }
    wdt.wdtSetReceiverSocketCreator(receiver);
    WdtTransferRequest augmentedReq = receiver.init();
    retCode = augmentedReq.errorCode;
    if (retCode == FEWER_PORTS) {
      if (FLAGS_treat_fewer_port_as_error) {
        WLOG(ERROR) << "Receiver could not bind to all the ports";
        return FEWER_PORTS;
      }
      retCode = OK;
    } else if (augmentedReq.errorCode != OK) {
      WLOG(ERROR) << "Error setting up receiver " << errorCodeToStr(retCode);
      return retCode;
    }
    // In the log:
    WLOG(INFO) << "Starting receiver with connection url "
               << augmentedReq.getLogSafeString();  // The url without secret
    // on stdout: the one with secret:
    std::cout << augmentedReq.genWdtUrlWithSecret() << std::endl;
    std::cout.flush();
    if (FLAGS_fork) {
      pid_t cpid = fork();
      if (cpid == -1) {
        perror("Failed to fork()");
        exit(1);
      }
      if (cpid > 0) {
        WLOG(INFO) << "Detaching receiver";
        exit(0);
      }
      close(0);
      close(1);
    }
    setAbortChecker(receiver);
    if (!FLAGS_run_as_daemon) {
      retCode = receiver.transferAsync();
      if (retCode == OK) {
        std::unique_ptr<TransferReport> report = receiver.finish();
        retCode = report->getSummary().getErrorCode();
      }
    } else {
      retCode = receiver.runForever();
      // not reached
    }
  } else {
    // Sender mode
    if (!FLAGS_manifest.empty()) {
      // Each line should have the filename and optionally
      // the filesize separated by a single space
      if (FLAGS_manifest == "-") {
        readManifest(std::cin, req, options.odirect_reads);
      } else {
        std::ifstream fin(FLAGS_manifest);
        readManifest(fin, req, options.odirect_reads);
        fin.close();
      }
      WLOG(INFO) << "Using files lists, number of files "
                 << req.fileInfo.size();
    }
    WLOG(INFO) << "Making Sender with encryption set = "
               << req.encryptionData.isSet();

    retCode = wdt.wdtSend(req, setupAbortChecker());
  }
  cancelAbort();
  if (retCode == OK) {
    WLOG(INFO) << "Returning with OK exit code";
  } else {
    WLOG(ERROR) << "Returning with code " << retCode << " "
                << errorCodeToStr(retCode);
  }
  return retCode;
}