Support setting the gRPC maximum message size
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.lock b/cmake/tomls/Cargo.sgx_trusted_lib.lock
index e128ec1..05e0201 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.lock
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.lock
@@ -2864,6 +2864,7 @@
  "serde_json",
  "sgx_cov",
  "sgx_types",
+ "teaclave_config",
  "teaclave_crypto",
  "teaclave_types",
  "tonic",
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.lock b/cmake/tomls/Cargo.sgx_untrusted_app.lock
index 78d216f..9f41081 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.lock
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.lock
@@ -2506,6 +2506,7 @@
  "serde_json",
  "sgx_cov",
  "sgx_types",
+ "teaclave_config",
  "teaclave_crypto",
  "teaclave_types",
  "tonic",
diff --git a/cmake/tomls/Cargo.unix_app.lock b/cmake/tomls/Cargo.unix_app.lock
index c5f79ff..442561c 100644
--- a/cmake/tomls/Cargo.unix_app.lock
+++ b/cmake/tomls/Cargo.unix_app.lock
@@ -2267,6 +2267,7 @@
  "serde_json",
  "sgx_cov",
  "sgx_types",
+ "teaclave_config",
  "teaclave_crypto",
  "teaclave_types",
  "tonic",
diff --git a/config/build.config.toml b/config/build.config.toml
index ecb392d..d5b086e 100644
--- a/config/build.config.toml
+++ b/config/build.config.toml
@@ -29,12 +29,15 @@
     { path = "config/keys/auditors/albus_dumbledore/albus_dumbledore.public.pem"},
 ]
 
-# RPC max message size
-rpc_max_message_size = 409600
-
 # Validity in seconds for a remote attestation report and endorsed attested TLS config
 attestation_validity_secs = 3600
 
+# gRPC configuration
+[grpc_config]
+# Limits the maximum size of an encoded/decoded message.
+max_encoding_message_size = 4194304
+max_decoding_message_size = 4194304
+
 # Refer to docs/service-internals.md for the service topology
 [inbound]
 access_control = ["teaclave_frontend_service", "teaclave_management_service"]
diff --git a/config/config_gen/main.rs b/config/config_gen/main.rs
index 37dec34..f69e973 100644
--- a/config/config_gen/main.rs
+++ b/config/config_gen/main.rs
@@ -29,7 +29,7 @@
 struct BuildConfigToml {
     as_root_ca_cert: ConfigSource,
     auditor_public_keys: Vec<ConfigSource>,
-    rpc_max_message_size: u64,
+    grpc_config: GrpcConfig,
     attestation_validity_secs: u64,
     inbound: Inbound,
 }
@@ -45,6 +45,13 @@
 
 #[derive(Debug, Serialize, Deserialize)]
 #[serde(rename_all(serialize = "snake_case", deserialize = "snake_case"))]
+struct GrpcConfig {
+    max_encoding_message_size: usize,
+    max_decoding_message_size: usize,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all(serialize = "snake_case", deserialize = "snake_case"))]
 enum ConfigSource {
     Path(PathBuf),
 }
@@ -74,7 +81,7 @@
 struct ConfigTemplate {
     as_root_ca_cert: String,
     auditor_public_keys: Vec<String>,
-    rpc_max_message_size: u64,
+    grpc_config: GrpcConfig,
     attestation_validity_secs: u64,
     inbound: Inbound,
 }
@@ -93,7 +100,7 @@
     let config_template = ConfigTemplate {
         as_root_ca_cert,
         auditor_public_keys,
-        rpc_max_message_size: config.rpc_max_message_size,
+        grpc_config: config.grpc_config,
         attestation_validity_secs: config.attestation_validity_secs,
         inbound: config.inbound,
     };
diff --git a/config/config_gen/templates/config.j2 b/config/config_gen/templates/config.j2
index 6337675..65fdeaf 100644
--- a/config/config_gen/templates/config.j2
+++ b/config/config_gen/templates/config.j2
@@ -21,12 +21,18 @@
 pub struct BuildConfig {
     pub as_root_ca_cert: &'static [u8],
     pub auditor_public_keys: &'static [&'static [u8]; {{ auditor_public_keys.len() }}],
-    pub rpc_max_message_size: u64,
+    pub grpc_config: GrpcConfig,
     pub attestation_validity_secs: u64,
     pub inbound: Inbounds,
 }
 
 #[derive(Debug)]
+pub struct GrpcConfig {
+    pub max_encoding_message_size: usize,
+    pub max_decoding_message_size: usize,
+}
+
+#[derive(Debug)]
 pub struct Inbounds {
     pub access_control: &'static [&'static str; {{ inbound.access_control.len() }}],
     pub authentication: &'static [&'static str; {{ inbound.authentication.len() }}],
@@ -42,7 +48,10 @@
         &{{ k }},
         {%- endfor %}
     ],
-    rpc_max_message_size: {{ rpc_max_message_size }},
+    grpc_config:  GrpcConfig {
+        max_encoding_message_size: {{ grpc_config.max_encoding_message_size }},
+        max_decoding_message_size: {{ grpc_config.max_decoding_message_size }},
+    },
     attestation_validity_secs: {{ attestation_validity_secs }},
     inbound: Inbounds {
         access_control: &[
diff --git a/config/src/build.rs b/config/src/build.rs
index 8257589..9c51047 100644
--- a/config/src/build.rs
+++ b/config/src/build.rs
@@ -30,6 +30,9 @@
 /// The valid duration of one attestation report in seconds.
 pub const ATTESTATION_VALIDITY_SECS: u64 = BUILD_CONFIG.attestation_validity_secs;
 
+/// gRPC configuration
+pub const GRPC_CONFIG: GrpcConfig = BUILD_CONFIG.grpc_config;
+
 macro_rules! def_inbound_services {
     ($name: tt, $service: tt) => {
         /// Array of predefined inbound services, usually used for validate
diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml
index 31fc8d4..01b6827 100644
--- a/sdk/rust/Cargo.toml
+++ b/sdk/rust/Cargo.toml
@@ -30,7 +30,7 @@
 teaclave_types        = { path = "../../types", features = ["app"] }
 teaclave_attestation  = { path = "../../attestation" }
 teaclave_rpc          = { path = "../../rpc" }
-teaclave_proto        = { path = "../../services/proto" }
+teaclave_proto        = { path = "../../services/proto", features = ["app"]  }
 anyhow                = { version = "1.0.26" }
 url                   = { version = "2.1.1" }
 serde_json            = { version = "1.0.39" }
diff --git a/services/access_control/enclave/src/lib.rs b/services/access_control/enclave/src/lib.rs
index 8809780..3aa8ca3 100644
--- a/services/access_control/enclave/src/lib.rs
+++ b/services/access_control/enclave/src/lib.rs
@@ -81,7 +81,9 @@
     Server::builder()
         .tls_config(server_config)
         .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
-        .add_service(TeaclaveAccessControlServer::new(service))
+        .add_service(TeaclaveAccessControlServer::new_with_builtin_config(
+            service,
+        ))
         .serve(listen_address)
         .await?;
     Ok(())
diff --git a/services/authentication/enclave/src/lib.rs b/services/authentication/enclave/src/lib.rs
index 921a10a..bacf4cd 100644
--- a/services/authentication/enclave/src/lib.rs
+++ b/services/authentication/enclave/src/lib.rs
@@ -65,7 +65,7 @@
     Server::builder()
         .tls_config(server_config)
         .map_err(|_| anyhow!("TeaclaveFrontendServer tls config error"))?
-        .add_service(TeaclaveAuthenticationInternalServer::new(service))
+        .add_service(TeaclaveAuthenticationInternalServer::new_with_builtin_config(service))
         .serve(addr)
         .await?;
     Ok(())
@@ -84,7 +84,9 @@
     Server::builder()
         .tls_config(tls_config)
         .map_err(|_| anyhow!("TeaclaveAuthenticationApiServer tls config error"))?
-        .add_service(TeaclaveAuthenticationApiServer::new(service))
+        .add_service(TeaclaveAuthenticationApiServer::new_with_builtin_config(
+            service,
+        ))
         .serve(addr)
         .await?;
     Ok(())
diff --git a/services/execution/enclave/src/service.rs b/services/execution/enclave/src/service.rs
index ace342a..4ba0abd 100644
--- a/services/execution/enclave/src/service.rs
+++ b/services/execution/enclave/src/service.rs
@@ -22,13 +22,12 @@
 use std::thread;
 
 use crate::task_file_manager::TaskFileManager;
+use anyhow::Result;
 use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_rpc::transport::{channel::Endpoint, Channel};
 use teaclave_types::*;
 use teaclave_worker::Worker;
-
-use anyhow::Result;
 use uuid::Uuid;
 
 static WORKER_BASE_DIR: &str = "/tmp/teaclave_agent/";
@@ -49,7 +48,7 @@
         fusion_base: impl AsRef<Path>,
     ) -> Result<Self> {
         let channel = scheduler_service_endpoint.connect().await?;
-        let scheduler_client = TeaclaveSchedulerClient::new(channel);
+        let scheduler_client = TeaclaveSchedulerClient::new_with_builtin_config(channel);
 
         Ok(TeaclaveExecutionService {
             worker: Arc::new(Worker::default()),
diff --git a/services/frontend/enclave/src/lib.rs b/services/frontend/enclave/src/lib.rs
index d0845d9..52dcd00 100644
--- a/services/frontend/enclave/src/lib.rs
+++ b/services/frontend/enclave/src/lib.rs
@@ -79,9 +79,9 @@
         .connect()
         .await
         .map_err(|e| anyhow!("Failed to connect to authentication service, retry {:?}", e))?;
-    let authentication_client = Arc::new(Mutex::new(TeaclaveAuthenticationInternalClient::new(
-        authentication_channel,
-    )));
+    let authentication_client = Arc::new(Mutex::new(
+        TeaclaveAuthenticationInternalClient::new_with_builtin_config(authentication_channel),
+    ));
 
     info!(" Starting FrontEnd: setup authentication client finished ...");
 
@@ -97,9 +97,9 @@
         .connect()
         .await
         .map_err(|e| anyhow!("Failed to connect to management service, {:?}", e))?;
-    let management_client = Arc::new(Mutex::new(TeaclaveManagementClient::new(
-        management_channel,
-    )));
+    let management_client = Arc::new(Mutex::new(
+        TeaclaveManagementClient::new_with_builtin_config(management_channel),
+    ));
 
     info!(" Starting FrontEnd: setup management client finished ...");
 
@@ -139,7 +139,7 @@
     Server::builder()
         .tls_config(server_config)
         .map_err(|_| anyhow!("TeaclaveFrontendServer tls config error"))?
-        .add_service(TeaclaveFrontendServer::new(service))
+        .add_service(TeaclaveFrontendServer::new_with_builtin_config(service))
         .serve(listen_address)
         .await?;
 
diff --git a/services/management/enclave/src/lib.rs b/services/management/enclave/src/lib.rs
index f33ead0..f5e8f04 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -92,7 +92,7 @@
     teaclave_rpc::transport::Server::builder()
         .tls_config(server_config)
         .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
-        .add_service(TeaclaveManagementServer::new(service))
+        .add_service(TeaclaveManagementServer::new_with_builtin_config(service))
         .serve(listen_address)
         .await?;
     Ok(())
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index a29ff69..1ed9d79 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -938,7 +938,9 @@
             .connect()
             .await
             .map_err(|e| anyhow!("Failed to connect to storage service, {:?}", e))?;
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new_with_builtin_config(
+            channel,
+        )));
         let client_clone = storage_client.clone();
         let auditor = task::spawn_blocking(move || Auditor::try_new(client_clone)).await??;
         let service = Self {
diff --git a/services/proto/Cargo.toml b/services/proto/Cargo.toml
index e8661df..af9239e 100644
--- a/services/proto/Cargo.toml
+++ b/services/proto/Cargo.toml
@@ -28,10 +28,13 @@
 app = [
     "teaclave_types/app",
     "teaclave_crypto/app",
+    "teaclave_config/build_config"
 ]
 mesalock_sgx = [
     "teaclave_types/mesalock_sgx",
     "teaclave_crypto/mesalock_sgx",
+    "teaclave_config/mesalock_sgx",
+    "teaclave_config/build_config",
 ]
 cov = ["sgx_cov"]
 
@@ -44,8 +47,10 @@
 tonic           = { version = "0.9.2", features = ["tls", "gzip"]}
 url             = { version = "2.1.1" }
 uuid            = { version = "0.8.1", features = ["v4"] }
-teaclave_types  = { path = "../../types" }
+
+teaclave_config = { path = "../../config" }
 teaclave_crypto = { path = "../../crypto" }
+teaclave_types  = { path = "../../types" }
 
 sgx_cov         = { version = "2.0.0", optional = true }
 
diff --git a/services/proto/src/lib.rs b/services/proto/src/lib.rs
index 4b422b6..2503d28 100644
--- a/services/proto/src/lib.rs
+++ b/services/proto/src/lib.rs
@@ -17,6 +17,9 @@
 
 extern crate sgx_types;
 
+#[macro_use]
+mod macros;
+
 pub mod teaclave_access_control_service;
 pub mod teaclave_authentication_service;
 pub mod teaclave_common;
@@ -25,12 +28,6 @@
 pub mod teaclave_scheduler_service;
 pub mod teaclave_storage_service;
 
-macro_rules! include_proto {
-    ($package: tt) => {
-        include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
-    };
-}
-
 pub mod teaclave_authentication_service_proto {
     include_proto!("teaclave_authentication_service_proto");
 }
diff --git a/services/proto/src/macros.rs b/services/proto/src/macros.rs
new file mode 100644
index 0000000..7c9957b
--- /dev/null
+++ b/services/proto/src/macros.rs
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+macro_rules! include_proto {
+    ($package: tt) => {
+        include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
+    };
+}
+
+macro_rules! impl_custom_client {
+    ($target: ident) => {
+        impl<T> $target<T>
+        where
+            T: tonic::client::GrpcService<tonic::body::BoxBody>,
+            T::Error: Into<tonic::codegen::StdError>,
+            T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
+            <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
+        {
+            pub fn new_with_builtin_config(inner: T) -> Self {
+                Self::new(inner)
+                    .max_decoding_message_size(
+                        teaclave_config::build::GRPC_CONFIG.max_decoding_message_size,
+                    )
+                    .max_encoding_message_size(
+                        teaclave_config::build::GRPC_CONFIG.max_encoding_message_size,
+                    )
+            }
+        }
+    };
+}
+
+macro_rules! impl_custom_server {
+    ($target: ident, $trait: ident) => {
+        impl<T: $trait> $target<T> {
+            pub fn new_with_builtin_config(inner: T) -> Self {
+                Self::new(inner)
+                    .max_decoding_message_size(
+                        teaclave_config::build::GRPC_CONFIG.max_decoding_message_size,
+                    )
+                    .max_encoding_message_size(
+                        teaclave_config::build::GRPC_CONFIG.max_encoding_message_size,
+                    )
+            }
+        }
+    };
+}
diff --git a/services/proto/src/teaclave_access_control_service.rs b/services/proto/src/teaclave_access_control_service.rs
index 87b8a83..b727f0e 100644
--- a/services/proto/src/teaclave_access_control_service.rs
+++ b/services/proto/src/teaclave_access_control_service.rs
@@ -21,3 +21,6 @@
     TeaclaveAccessControl, TeaclaveAccessControlServer,
 };
 pub use proto::*;
+
+impl_custom_server!(TeaclaveAccessControlServer, TeaclaveAccessControl);
+impl_custom_client!(TeaclaveAccessControlClient);
diff --git a/services/proto/src/teaclave_authentication_service.rs b/services/proto/src/teaclave_authentication_service.rs
index d0357b7..59d2cab 100644
--- a/services/proto/src/teaclave_authentication_service.rs
+++ b/services/proto/src/teaclave_authentication_service.rs
@@ -29,6 +29,14 @@
 pub use proto::*;
 use teaclave_types::UserAuthClaims;
 
+impl_custom_server!(TeaclaveAuthenticationApiServer, TeaclaveAuthenticationApi);
+impl_custom_client!(TeaclaveAuthenticationApiClient);
+impl_custom_server!(
+    TeaclaveAuthenticationInternalServer,
+    TeaclaveAuthenticationInternal
+);
+impl_custom_client!(TeaclaveAuthenticationInternalClient);
+
 impl UserRegisterRequest {
     pub fn new(
         id: impl Into<String>,
diff --git a/services/proto/src/teaclave_frontend_service.rs b/services/proto/src/teaclave_frontend_service.rs
index d26d40c..ce81d7b 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -30,6 +30,9 @@
 pub use proto::teaclave_frontend_server::TeaclaveFrontendServer;
 pub use proto::*;
 
+impl_custom_server!(TeaclaveFrontendServer, TeaclaveFrontend);
+impl_custom_client!(TeaclaveFrontendClient);
+
 impl RegisterInputFileRequest {
     pub fn new(url: Url, cmac: FileAuthTag, crypto: impl Into<FileCrypto>) -> Self {
         Self {
diff --git a/services/proto/src/teaclave_management_service.rs b/services/proto/src/teaclave_management_service.rs
index 0d29fdb..fd4b5a3 100644
--- a/services/proto/src/teaclave_management_service.rs
+++ b/services/proto/src/teaclave_management_service.rs
@@ -82,3 +82,6 @@
         Self { logs }
     }
 }
+
+impl_custom_server!(TeaclaveManagementServer, TeaclaveManagement);
+impl_custom_client!(TeaclaveManagementClient);
diff --git a/services/proto/src/teaclave_scheduler_service.rs b/services/proto/src/teaclave_scheduler_service.rs
index a8c4339..e3c24f1 100644
--- a/services/proto/src/teaclave_scheduler_service.rs
+++ b/services/proto/src/teaclave_scheduler_service.rs
@@ -30,6 +30,9 @@
 use teaclave_types::{StagedTask, TaskFailure, TaskOutputs, TaskResult, TaskStatus};
 use uuid::Uuid;
 
+impl_custom_server!(TeaclaveSchedulerServer, TeaclaveScheduler);
+impl_custom_client!(TeaclaveSchedulerClient);
+
 impl HeartbeatRequest {
     pub fn new(executor_id: Uuid, status: ExecutorStatus) -> Self {
         Self {
diff --git a/services/proto/src/teaclave_storage_service.rs b/services/proto/src/teaclave_storage_service.rs
index 817b85c..f38e69a 100644
--- a/services/proto/src/teaclave_storage_service.rs
+++ b/services/proto/src/teaclave_storage_service.rs
@@ -24,6 +24,9 @@
     GetKeysByPrefixResponse, GetRequest, GetResponse, PutRequest,
 };
 
+impl_custom_server!(TeaclaveStorageServer, TeaclaveStorage);
+impl_custom_client!(TeaclaveStorageClient);
+
 impl GetRequest {
     pub fn new(key: impl Into<Vec<u8>>) -> Self {
         Self { key: key.into() }
diff --git a/services/scheduler/enclave/src/publisher.rs b/services/scheduler/enclave/src/publisher.rs
index c4d3afe..b9499ca 100644
--- a/services/scheduler/enclave/src/publisher.rs
+++ b/services/scheduler/enclave/src/publisher.rs
@@ -46,10 +46,14 @@
         scheduler_service_endpoint: Endpoint,
     ) -> Result<Self> {
         let channel = storage_service_endpoint.connect().await?;
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new_with_builtin_config(
+            channel,
+        )));
         let channel = scheduler_service_endpoint.connect().await?;
 
-        let scheduler_client = Arc::new(Mutex::new(TeaclaveSchedulerClient::new(channel)));
+        let scheduler_client = Arc::new(Mutex::new(
+            TeaclaveSchedulerClient::new_with_builtin_config(channel),
+        ));
 
         let service = Self {
             storage_client,
diff --git a/services/scheduler/enclave/src/service.rs b/services/scheduler/enclave/src/service.rs
index 07aa7b1..d208646 100644
--- a/services/scheduler/enclave/src/service.rs
+++ b/services/scheduler/enclave/src/service.rs
@@ -25,6 +25,7 @@
 use std::untrusted::time::SystemTimeEx;
 use tokio::sync::Mutex;
 
+use anyhow::{anyhow, Result};
 use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_proto::teaclave_storage_service::*;
@@ -33,9 +34,6 @@
 use teaclave_types::*;
 use uuid::Uuid;
 
-use anyhow::anyhow;
-use anyhow::Result;
-
 const EXECUTOR_TIMEOUT_SECS: u64 = 30;
 
 #[derive(Clone)]
@@ -142,7 +140,9 @@
             .connect()
             .await
             .map_err(|e| anyhow!("Failed to connect to storage service.{:?}", e))?;
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new_with_builtin_config(
+            channel,
+        )));
         let task_queue = VecDeque::new();
         let executors_tasks = HashMap::new();
         let executors_status = HashMap::new();
diff --git a/services/storage/enclave/src/lib.rs b/services/storage/enclave/src/lib.rs
index 8d443f8..33efe4d 100644
--- a/services/storage/enclave/src/lib.rs
+++ b/services/storage/enclave/src/lib.rs
@@ -98,7 +98,7 @@
     teaclave_rpc::transport::Server::builder()
         .tls_config(server_config)
         .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
-        .add_service(TeaclaveStorageServer::new(service))
+        .add_service(TeaclaveStorageServer::new_with_builtin_config(service))
         .serve(listen_address)
         .await?;
     storage_handle.join().unwrap();