Hello fellow Boost friends,

I am looking into some advice on implementing rate-limiting using using Boost ASIO with async_write. I am working on a Enterprise File Backup solution named Vessel @ https://github.com/VesselEnterprise/vessel-backup. My project uses Boost through and through.

The use case is as follows:
  • Many users on the same network/subnet may be transferring files at once
  • I want to add the feature of being able to limit upload speed to the storage provider (AWS, Azure, etc)
The request starts as follows: (pseudo code)

Let's say we have a string of 1000 bytes we want to send to a server:

const std::string& request //Passed to member function and make_shared<>() to member var on stack to ensure lifetime of async operation

Let's also say we want to limit the transfer speed to 100 bytes/second

size_t transfer_max = 100;

 Should we start the request with async_write() on the socket?

 //Ensure that no more than transfer_max bytes are sent during the first write
boost::asio::async_write(*m_socket, boost::asio::buffer(http_request, transfer_max), boost::bind(&HttpClient::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred )) ;

Here is where I have questions. In the completion handler handle_write(...), we need to continue to call async_write() until all bytes have been written and determine the current transfer rate, and sleep the thread if necessary. When sending the next set of bytes, is it best to explicitly declare a buffer and consume or use a pointer to the char array?

void HttpClient::handle_write( const boost::system::error_code& e, size_t bytes_transferred )
{
  /**
  ** Do some stuff here to determine transfer rate, and sleep if necessary...
 */
  
  //Pseudocode
  if ( transfer_rate > transfer_max )
  {
    //Possibility 1?
    auto buffer = boost::asio::buffer(request, transfer_max);
    buffer.consume(total_bytes_transferred_so_far);
    boost::asio::async_write(*m_socket, buffer, boost::bind(&HttpClient::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred )) ;
 
    //Possibility 2?
    boost::asio::async_write(*m_socket, boost::asio::buffer(&request[total_bytes_transferred_so_far], transfer_max), boost::bind(&HttpClient::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred )) ;
    return;
  
  }
  //...eof
}

Advice on the topic is greatly appreciated. If I am way off, just let me know :)

Thanks!
--
Kyle Ketterer