Allow setting max send message size via C++ ServerBuilder API.
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index dfac177..7a8f846 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -175,7 +175,7 @@
 class CallNoOp {
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {}
-  void FinishOp(bool* status, int max_message_size) {}
+  void FinishOp(bool* status, int max_receive_message_size) {}
 };
 
 class CallOpSendInitialMetadata {
@@ -213,7 +213,7 @@
     op->data.send_initial_metadata.maybe_compression_level.level =
         maybe_compression_level_.level;
   }
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (!send_) return;
     g_core_codegen_interface->gpr_free(initial_metadata_);
     send_ = false;
@@ -253,7 +253,7 @@
     // Flags are per-message: clear them after use.
     write_options_.Clear();
   }
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
     send_buf_ = nullptr;
   }
@@ -301,13 +301,14 @@
     op->data.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (message_ == nullptr) return;
     if (recv_buf_) {
       if (*status) {
-        got_message = *status = SerializationTraits<R>::Deserialize(
-                                    recv_buf_, message_, max_message_size)
-                                    .ok();
+        got_message = *status =
+            SerializationTraits<R>::Deserialize(recv_buf_, message_,
+                                                max_receive_message_size)
+                .ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -330,7 +331,8 @@
 namespace CallOpGenericRecvMessageHelper {
 class DeserializeFunc {
  public:
-  virtual Status Deserialize(grpc_byte_buffer* buf, int max_message_size) = 0;
+  virtual Status Deserialize(grpc_byte_buffer* buf,
+                             int max_receive_message_size) = 0;
   virtual ~DeserializeFunc() {}
 };
 
@@ -339,8 +341,9 @@
  public:
   DeserializeFuncType(R* message) : message_(message) {}
   Status Deserialize(grpc_byte_buffer* buf,
-                     int max_message_size) GRPC_OVERRIDE {
-    return SerializationTraits<R>::Deserialize(buf, message_, max_message_size);
+                     int max_receive_message_size) GRPC_OVERRIDE {
+    return SerializationTraits<R>::Deserialize(buf, message_,
+                                               max_receive_message_size);
   }
 
   ~DeserializeFuncType() GRPC_OVERRIDE {}
@@ -379,12 +382,13 @@
     op->data.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (!deserialize_) return;
     if (recv_buf_) {
       if (*status) {
         got_message = true;
-        *status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
+        *status =
+            deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -418,7 +422,7 @@
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_message_size) { send_ = false; }
+  void FinishOp(bool* status, int max_receive_message_size) { send_ = false; }
 
  private:
   bool send_;
@@ -453,7 +457,7 @@
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (!send_status_available_) return;
     g_core_codegen_interface->gpr_free(trailing_metadata_);
     send_status_available_ = false;
@@ -486,7 +490,7 @@
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (recv_initial_metadata_ == nullptr) return;
     FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
     recv_initial_metadata_ = nullptr;
@@ -525,7 +529,7 @@
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_message_size) {
+  void FinishOp(bool* status, int max_receive_message_size) {
     if (recv_status_ == nullptr) return;
     FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
     *recv_status_ = Status(
@@ -562,13 +566,13 @@
 /// API.
 class CallOpSetInterface : public CompletionQueueTag {
  public:
-  CallOpSetInterface() : max_message_size_(0) {}
+  CallOpSetInterface() : max_receive_message_size_(0) {}
   /// Fills in grpc_op, starting from ops[*nops] and moving
   /// upwards.
   virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
 
-  void set_max_message_size(int max_message_size) {
-    max_message_size_ = max_message_size;
+  void set_max_receive_message_size(int max_receive_message_size) {
+    max_receive_message_size_ = max_receive_message_size;
   }
 
   /// Mark this as belonging to a collection if needed
@@ -577,7 +581,7 @@
   }
 
  protected:
-  int max_message_size_;
+  int max_receive_message_size_;
   std::shared_ptr<CallOpSetCollectionInterface> collection_;
 };
 
@@ -609,12 +613,12 @@
   }
 
   bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
-    this->Op1::FinishOp(status, max_message_size_);
-    this->Op2::FinishOp(status, max_message_size_);
-    this->Op3::FinishOp(status, max_message_size_);
-    this->Op4::FinishOp(status, max_message_size_);
-    this->Op5::FinishOp(status, max_message_size_);
-    this->Op6::FinishOp(status, max_message_size_);
+    this->Op1::FinishOp(status, max_receive_message_size_);
+    this->Op2::FinishOp(status, max_receive_message_size_);
+    this->Op3::FinishOp(status, max_receive_message_size_);
+    this->Op4::FinishOp(status, max_receive_message_size_);
+    this->Op5::FinishOp(status, max_receive_message_size_);
+    this->Op6::FinishOp(status, max_receive_message_size_);
     *tag = return_tag_;
     collection_.reset();  // drop the ref at this point
     return true;
@@ -646,18 +650,21 @@
  public:
   /* call is owned by the caller */
   Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
-      : call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
-
-  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
-       int max_message_size)
       : call_hook_(call_hook),
         cq_(cq),
         call_(call),
-        max_message_size_(max_message_size) {}
+        max_receive_message_size_(-1) {}
+
+  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
+       int max_receive_message_size)
+      : call_hook_(call_hook),
+        cq_(cq),
+        call_(call),
+        max_receive_message_size_(max_receive_message_size) {}
 
   void PerformOps(CallOpSetInterface* ops) {
-    if (max_message_size_ > 0) {
-      ops->set_max_message_size(max_message_size_);
+    if (max_receive_message_size_ > 0) {
+      ops->set_max_receive_message_size(max_receive_message_size_);
     }
     call_hook_->PerformOpsOnCall(ops, this);
   }
@@ -665,13 +672,13 @@
   grpc_call* call() { return call_; }
   CompletionQueue* cq() { return cq_; }
 
-  int max_message_size() { return max_message_size_; }
+  int max_receive_message_size() { return max_receive_message_size_; }
 
  private:
   CallHook* call_hook_;
   CompletionQueue* cq_;
   grpc_call* call_;
-  int max_message_size_;
+  int max_receive_message_size_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index 2f4be64..749924e 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -53,7 +53,7 @@
   void RunHandler(const HandlerParameter& param) GRPC_FINAL {
     RequestType req;
     Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_message_size);
+        param.request, &req, param.max_receive_message_size);
     ResponseType rsp;
     if (status.ok()) {
       status = func_(service_, param.server_context, &req, &rsp);
@@ -139,7 +139,7 @@
   void RunHandler(const HandlerParameter& param) GRPC_FINAL {
     RequestType req;
     Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_message_size);
+        param.request, &req, param.max_receive_message_size);
 
     if (status.ok()) {
       ServerWriter<ResponseType> writer(param.call, param.server_context);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index d4599c5..e91e0b7 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -205,7 +205,7 @@
 
   static Status Deserialize(grpc_byte_buffer* buffer,
                             grpc::protobuf::Message* msg,
-                            int max_message_size) {
+                            int max_receive_message_size) {
     if (buffer == nullptr) {
       return Status(StatusCode::INTERNAL, "No payload");
     }
@@ -216,8 +216,9 @@
         return reader.status();
       }
       ::grpc::protobuf::io::CodedInputStream decoder(&reader);
-      if (max_message_size > 0) {
-        decoder.SetTotalBytesLimit(max_message_size, max_message_size);
+      if (max_receive_message_size > 0) {
+        decoder.SetTotalBytesLimit(max_receive_message_size,
+                                   max_receive_message_size);
       }
       if (!msg->ParseFromCodedStream(&decoder)) {
         result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 8b1f026..01999ee 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -59,12 +59,12 @@
         : call(c),
           server_context(context),
           request(req),
-          max_message_size(max_size) {}
+          max_receive_message_size(max_size) {}
     Call* call;
     ServerContext* server_context;
     // Handler required to grpc_byte_buffer_destroy this
     grpc_byte_buffer* request;
-    int max_message_size;
+    int max_receive_message_size;
   };
   virtual void RunHandler(const HandlerParameter& param) = 0;
 };
diff --git a/include/grpc++/impl/codegen/serialization_traits.h b/include/grpc++/impl/codegen/serialization_traits.h
index fa99dbf..54e5d47 100644
--- a/include/grpc++/impl/codegen/serialization_traits.h
+++ b/include/grpc++/impl/codegen/serialization_traits.h
@@ -43,10 +43,10 @@
 /// functions:
 ///   static Status Serialize(const Message& msg,
 ///                           grpc_byte_buffer** buffer,
-//                            bool* own_buffer);
+///                           bool* own_buffer);
 ///   static Status Deserialize(grpc_byte_buffer* buffer,
 ///                             Message* msg,
-///                             int max_message_size);
+///                             int max_receive_message_size);
 ///
 /// Serialize is required to convert message to a grpc_byte_buffer, and
 /// to store a pointer to that byte buffer at *buffer. *own_buffer should
@@ -54,8 +54,8 @@
 /// ownership is retained elsewhere.
 ///
 /// Deserialize is required to convert buffer into the message stored at
-/// msg. max_message_size is passed in as a bound on the maximum number of
-/// message bytes Deserialize should accept.
+/// msg. max_receive_message_size is passed in as a bound on the maximum
+/// number of message bytes Deserialize should accept.
 ///
 /// Both functions return a Status, allowing them to explain what went
 /// wrong if required.
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 3a3e052..20e418d 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -129,7 +129,7 @@
 
   virtual void ShutdownInternal(gpr_timespec deadline) = 0;
 
-  virtual int max_message_size() const = 0;
+  virtual int max_receive_message_size() const = 0;
 
   virtual grpc_server* server() = 0;
 
@@ -200,8 +200,8 @@
     bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
       bool serialization_status =
           *status && payload_ &&
-          SerializationTraits<Message>::Deserialize(payload_, request_,
-                                                    server_->max_message_size())
+          SerializationTraits<Message>::Deserialize(
+              payload_, request_, server_->max_receive_message_size())
               .ok();
       bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
       *status = serialization_status && *status;
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 6876961..6e15035 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -116,10 +116,10 @@
   ///
   /// \param thread_pool The threadpool instance to use for call processing.
   /// \param thread_pool_owned Does the server own the \a thread_pool instance?
-  /// \param max_message_size Maximum message length that the channel can
-  /// receive.
+  /// \param max_receive_message_size Maximum message length that the channel
+  /// can receive.
   Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
-         int max_message_size, ChannelArguments* args);
+         int max_receive_message_size, ChannelArguments* args);
 
   /// Register a service. This call does not take ownership of the service.
   /// The service must exist for the lifetime of the Server instance.
@@ -164,13 +164,15 @@
 
   void ShutdownInternal(gpr_timespec deadline) GRPC_OVERRIDE;
 
-  int max_message_size() const GRPC_OVERRIDE { return max_message_size_; };
+  int max_receive_message_size() const GRPC_OVERRIDE {
+    return max_receive_message_size_;
+  };
 
   grpc_server* server() GRPC_OVERRIDE { return server_; };
 
   ServerInitializer* initializer();
 
-  const int max_message_size_;
+  const int max_receive_message_size_;
 
   // Completion queue.
   CompletionQueue cq_;
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index b9c49f0..326962b 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -78,12 +78,23 @@
   /// Only matches requests with :authority \a host
   ServerBuilder& RegisterService(const grpc::string& host, Service* service);
 
-  /// Set max message size in bytes.
-  ServerBuilder& SetMaxMessageSize(int max_message_size) {
-    max_message_size_ = max_message_size;
+  /// Set max receive message size in bytes.
+  ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) {
+    max_receive_message_size_ = max_receive_message_size;
     return *this;
   }
 
+  /// Set max send message size in bytes.
+  ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) {
+    max_send_message_size_ = max_send_message_size;
+    return *this;
+  }
+
+  /// For backward compatibility.
+  ServerBuilder& SetMaxMessageSize(int max_message_size) {
+    return SetMaxReceiveMessageSize(max_message_size);
+  }
+
   /// Set the support status for compression algorithms. All algorithms are
   /// enabled by default.
   ///
@@ -168,7 +179,8 @@
     Service* service;
   };
 
-  int max_message_size_;
+  int max_receive_message_size_;
+  int max_send_message_size_;
   std::vector<std::unique_ptr<ServerBuilderOption>> options_;
   std::vector<std::unique_ptr<NamedService>> services_;
   std::vector<Port> ports_;
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 01249a0..06f8969 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -96,7 +96,7 @@
 class SerializationTraits<ByteBuffer, void> {
  public:
   static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest,
-                            int max_message_size) {
+                            int max_receive_message_size) {
     dest->set_buffer(byte_buffer);
     return Status::OK;
   }