[core] Add SgxTrustedServer in RPC (#194)

diff --git a/mesatee_core/src/rpc/mod.rs b/mesatee_core/src/rpc/mod.rs
index 7e39b1d..8a85a76 100644
--- a/mesatee_core/src/rpc/mod.rs
+++ b/mesatee_core/src/rpc/mod.rs
@@ -44,7 +44,7 @@
 {
     type Config;
 
-    fn start(config: Self::Config) -> Result<Self>;
+    fn start(config: &Self::Config) -> Result<Self>;
 
     // This call would block -- contains main loop
     // Returns error on socket close or any exceptions.
@@ -128,6 +128,8 @@
 // Please reivse this later if we have a dedicated rpc for mesalock_sgx.
 
 pub mod channel;
+#[cfg(feature = "mesalock_sgx")]
+pub mod server;
 
 pub mod sgx;
 pub mod unix;
diff --git a/mesatee_core/src/rpc/server.rs b/mesatee_core/src/rpc/server.rs
new file mode 100644
index 0000000..be09738
--- /dev/null
+++ b/mesatee_core/src/rpc/server.rs
@@ -0,0 +1,56 @@
+// 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.
+
+use crate::rpc::sgx;
+use crate::rpc::sgx::EnclaveAttr;
+use crate::rpc::EnclaveService;
+use crate::rpc::RpcServer;
+use crate::Result;
+use serde::{de::DeserializeOwned, Serialize};
+use sgx_types::c_int;
+
+pub struct SgxTrustedServer<U, V, X>
+where
+    U: DeserializeOwned + std::fmt::Debug,
+    V: Serialize + std::fmt::Debug,
+    X: EnclaveService<U, V>,
+{
+    config: sgx::PipeConfig,
+    service: X,
+    marker: std::marker::PhantomData<(U, V)>,
+}
+
+impl<U, V, X> SgxTrustedServer<U, V, X>
+where
+    U: DeserializeOwned + std::fmt::Debug,
+    V: Serialize + std::fmt::Debug,
+    X: EnclaveService<U, V>,
+{
+    pub fn new(service: X, fd: c_int, client_attr: Option<EnclaveAttr>) -> Result<Self> {
+        let config = sgx::PipeConfig { fd, client_attr };
+        Ok(Self {
+            config,
+            service,
+            marker: std::marker::PhantomData,
+        })
+    }
+
+    pub fn start(self) -> Result<()> {
+        let mut server = sgx::Pipe::start(&self.config)?;
+        server.serve(self.service)
+    }
+}
diff --git a/mesatee_core/src/rpc/sgx/mod.rs b/mesatee_core/src/rpc/sgx/mod.rs
index 7c46da5..5bed990 100644
--- a/mesatee_core/src/rpc/sgx/mod.rs
+++ b/mesatee_core/src/rpc/sgx/mod.rs
@@ -166,7 +166,6 @@
 #[cfg(feature = "mesalock_sgx")]
 pub struct PipeConfig {
     pub fd: c_int,
-    pub retry: u32,
     // the SGX server can optionally verify the identity of the client
     pub client_attr: Option<EnclaveAttr>,
 }
@@ -205,7 +204,7 @@
     X: EnclaveService<U, V>,
 {
     type Config = PipeConfig;
-    fn start(config: Self::Config) -> Result<Self> {
+    fn start(config: &Self::Config) -> Result<Self> {
         let tcp = TcpStream::new(config.fd)?;
 
         // TCP set nodelay should not affect the success of this function
@@ -216,7 +215,7 @@
         // TODO: Due to switching to the SDK-style design, performing an
         // initial RA at enclave start is not longer a viable design. Need
         // to refactor the related API.
-        let rustls_server_cfg = server::get_tls_config(config.client_attr)?;
+        let rustls_server_cfg = server::get_tls_config(&config.client_attr)?;
         let sess = rustls::ServerSession::new(&rustls_server_cfg);
 
         Ok(Pipe {
diff --git a/mesatee_core/src/rpc/sgx/server.rs b/mesatee_core/src/rpc/sgx/server.rs
index c687fc3..b9c8bfd 100644
--- a/mesatee_core/src/rpc/sgx/server.rs
+++ b/mesatee_core/src/rpc/sgx/server.rs
@@ -40,14 +40,14 @@
 }
 
 pub(crate) fn get_tls_config(
-    client_attr: Option<EnclaveAttr>,
+    client_attr: &Option<EnclaveAttr>,
 ) -> Result<Arc<rustls::ServerConfig>> {
     use crate::rpc::sgx::ra::get_current_ra_credential;
 
     let ra_credential = get_current_ra_credential();
 
     let client_attr = match client_attr {
-        Some(attr) => Arc::new(attr),
+        Some(attr) => Arc::new(attr.clone()),
         None => {
             let certs = vec![rustls::Certificate(ra_credential.cert)];
             let privkey = rustls::PrivateKey(ra_credential.private_key);
diff --git a/mesatee_core/src/rpc/unix/mod.rs b/mesatee_core/src/rpc/unix/mod.rs
index bd9c585..e030f75 100644
--- a/mesatee_core/src/rpc/unix/mod.rs
+++ b/mesatee_core/src/rpc/unix/mod.rs
@@ -115,7 +115,7 @@
     // type X = Box<EnclaveService<U, V>>;
     // The `TcpStream::new()` function is different from Rust's design.
     // The SGX version takes a fd as a input and return an `Option`.
-    fn start(config: Self::Config) -> Result<Self> {
+    fn start(config: &Self::Config) -> Result<Self> {
         Ok(Pipe {
             #[cfg(feature = "mesalock_sgx")]
             inner: TcpStream::new(config.get())?,
diff --git a/mesatee_services/acs/sgx_trusted_lib/src/sgx.rs b/mesatee_services/acs/sgx_trusted_lib/src/sgx.rs
index 88e84df..a43a990 100644
--- a/mesatee_services/acs/sgx_trusted_lib/src/sgx.rs
+++ b/mesatee_services/acs/sgx_trusted_lib/src/sgx.rs
@@ -24,6 +24,7 @@
 
 use mesatee_core::config;
 use mesatee_core::prelude::*;
+use mesatee_core::rpc::server::SgxTrustedServer;
 use mesatee_core::{Error, ErrorKind, Result};
 
 use crate::acs::ACSEnclave;
@@ -43,30 +44,22 @@
 fn handle_serve_connection(args: &ServeConnectionInput) -> Result<ServeConnectionOutput> {
     debug!("Enclave [ACS]: Serve Connection.");
 
-    let server_instance = ACSEnclave::default();
     let acs_config = config::Internal::acs();
     assert_eq!(args.port, acs_config.addr.port());
 
     let enclave_attr = match acs_config.inbound_desc {
-        config::InboundDesc::Sgx(enclave_attr) => enclave_attr,
+        config::InboundDesc::Sgx(enclave_attr) => Some(enclave_attr),
         _ => unreachable!(),
     };
 
-    let config = PipeConfig {
-        fd: args.socket_fd,
-        retry: 0,
-        client_attr: Some(enclave_attr),
-    };
-
-    let mut server = match Pipe::start(config) {
+    let server = match SgxTrustedServer::new(ACSEnclave::default(), args.socket_fd, enclave_attr) {
         Ok(s) => s,
         Err(e) => {
-            error!("Start Pipe failed: {}", e);
+            error!("New server failed: {:?}.", e);
             return Ok(ServeConnectionOutput::default());
         }
     };
-
-    let _ = server.serve(server_instance);
+    let _ = server.start();
 
     // We discard all enclave internal errors here.
     Ok(ServeConnectionOutput::default())
diff --git a/mesatee_services/fns/sgx_trusted_lib/src/sgx/mod.rs b/mesatee_services/fns/sgx_trusted_lib/src/sgx/mod.rs
index 351e3f4..a8ea997 100644
--- a/mesatee_services/fns/sgx_trusted_lib/src/sgx/mod.rs
+++ b/mesatee_services/fns/sgx_trusted_lib/src/sgx/mod.rs
@@ -21,6 +21,7 @@
 
 use mesatee_core::config;
 use mesatee_core::prelude::*;
+use mesatee_core::rpc::server::SgxTrustedServer;
 use mesatee_core::Result;
 
 use crate::fns::FNSEnclave;
@@ -54,8 +55,6 @@
 fn handle_serve_connection(args: &ServeConnectionInput) -> Result<ServeConnectionOutput> {
     debug!("Enclave [FNS]: Serve Connection.");
 
-    let server_instance = FNSEnclave::default();
-
     let fns_config = config::External::fns();
     assert_eq!(args.port, fns_config.addr.port());
 
@@ -63,23 +62,15 @@
         config::InboundDesc::External => None,
         _ => unreachable!(),
     };
-
-    let config = PipeConfig {
-        fd: args.socket_fd,
-        retry: 0,
-        client_attr: enclave_attr,
-    };
-
-    let mut server = match Pipe::start(config) {
+    let server = match SgxTrustedServer::new(FNSEnclave::default(), args.socket_fd, enclave_attr) {
         Ok(s) => s,
         Err(e) => {
-            error!("Start Pipe failed: {}", e);
+            error!("New server failed: {:?}.", e);
             return Ok(ServeConnectionOutput::default());
         }
     };
+    let _ = server.start();
 
     // We discard all enclave internal errors here.
-    let _ = server.serve(server_instance);
-
     Ok(ServeConnectionOutput::default())
 }
diff --git a/mesatee_services/kms/sgx_trusted_lib/src/sgx.rs b/mesatee_services/kms/sgx_trusted_lib/src/sgx.rs
index 491fe5b..57b77c6 100644
--- a/mesatee_services/kms/sgx_trusted_lib/src/sgx.rs
+++ b/mesatee_services/kms/sgx_trusted_lib/src/sgx.rs
@@ -21,6 +21,7 @@
 
 use mesatee_core::config;
 use mesatee_core::prelude::*;
+use mesatee_core::rpc::server::SgxTrustedServer;
 use mesatee_core::Result;
 
 use crate::kms::KMSEnclave;
@@ -36,30 +37,21 @@
 fn handle_serve_connection(args: &ServeConnectionInput) -> Result<ServeConnectionOutput> {
     debug!("Enclave [KMS]: Serve Connection.");
 
-    let server_instance = KMSEnclave::default();
     let kms_config = config::Internal::kms();
     assert_eq!(args.port, kms_config.addr.port());
 
     let enclave_attr = match kms_config.inbound_desc {
-        config::InboundDesc::Sgx(enclave_attr) => enclave_attr,
+        config::InboundDesc::Sgx(enclave_attr) => Some(enclave_attr),
         _ => unreachable!(),
     };
-
-    let config = PipeConfig {
-        fd: args.socket_fd,
-        retry: 0,
-        client_attr: Some(enclave_attr),
-    };
-
-    let mut server = match Pipe::start(config) {
+    let server = match SgxTrustedServer::new(KMSEnclave::default(), args.socket_fd, enclave_attr) {
         Ok(s) => s,
         Err(e) => {
-            error!("Start Pipe failed: {}", e);
+            error!("New server failed: {:?}.", e);
             return Ok(ServeConnectionOutput::default());
         }
     };
-
-    let _ = server.serve(server_instance);
+    let _ = server.start();
 
     // We discard all enclave internal errors here.
     Ok(ServeConnectionOutput::default())
diff --git a/mesatee_services/tdfs/sgx_trusted_lib/src/sgx.rs b/mesatee_services/tdfs/sgx_trusted_lib/src/sgx.rs
index e3bf309..0a916ac 100644
--- a/mesatee_services/tdfs/sgx_trusted_lib/src/sgx.rs
+++ b/mesatee_services/tdfs/sgx_trusted_lib/src/sgx.rs
@@ -19,6 +19,7 @@
 
 use mesatee_core::config;
 use mesatee_core::prelude::*;
+use mesatee_core::rpc::server::SgxTrustedServer;
 use mesatee_core::Result;
 
 use crate::data_store::add_test_infomation;
@@ -38,48 +39,35 @@
     let internal = config::Internal::tdfs();
     let external = config::External::tdfs();
 
+    let fd = args.socket_fd;
     if args.port == internal.addr.port() {
         let enclave_attr = match internal.inbound_desc {
             config::InboundDesc::Sgx(enclave_attr) => Some(enclave_attr),
             _ => unreachable!(),
         };
 
-        let config = PipeConfig {
-            fd: args.socket_fd,
-            retry: 0,
-            client_attr: enclave_attr,
-        };
-
-        let mut server = match Pipe::start(config) {
+        let server = match SgxTrustedServer::new(DFSInternalEnclave::default(), fd, enclave_attr) {
             Ok(s) => s,
             Err(e) => {
-                error!("Start Pipe failed: {}", e);
+                error!("New server failed: {:?}.", e);
                 return Ok(ServeConnectionOutput::default());
             }
         };
-
-        let _ = server.serve(DFSInternalEnclave::default());
+        let _ = server.start();
     } else if args.port == external.addr.port() {
         let enclave_attr = match external.inbound_desc {
             config::InboundDesc::External => None,
             _ => unreachable!(),
         };
 
-        let config = PipeConfig {
-            fd: args.socket_fd,
-            retry: 0,
-            client_attr: enclave_attr,
-        };
-
-        let mut server = match Pipe::start(config) {
+        let server = match SgxTrustedServer::new(DFSExternalEnclave::default(), fd, enclave_attr) {
             Ok(s) => s,
             Err(e) => {
-                error!("Start Pipe failed: {}", e);
+                error!("New server failed: {:?}.", e);
                 return Ok(ServeConnectionOutput::default());
             }
         };
-
-        let _ = server.serve(DFSExternalEnclave::default());
+        let _ = server.start();
     } else {
         unreachable!()
     }
diff --git a/mesatee_services/tms/sgx_trusted_lib/src/sgx.rs b/mesatee_services/tms/sgx_trusted_lib/src/sgx.rs
index 6d8378d..fd350bc 100644
--- a/mesatee_services/tms/sgx_trusted_lib/src/sgx.rs
+++ b/mesatee_services/tms/sgx_trusted_lib/src/sgx.rs
@@ -20,6 +20,7 @@
 
 use mesatee_core::config;
 use mesatee_core::prelude::*;
+use mesatee_core::rpc::server::SgxTrustedServer;
 use mesatee_core::Result;
 
 use crate::tms_external::TMSExternalEnclave;
@@ -65,41 +66,36 @@
             _ => unreachable!(),
         };
 
-        let config = PipeConfig {
-            fd: args.socket_fd,
-            retry: 0,
-            client_attr: enclave_attr,
-        };
-
-        let mut server = match Pipe::start(config) {
+        let server = match SgxTrustedServer::new(
+            TMSInternalEnclave::default(),
+            args.socket_fd,
+            enclave_attr,
+        ) {
             Ok(s) => s,
             Err(e) => {
-                error!("Start Pipe failed: {}", e);
+                error!("New server failed: {:?}.", e);
                 return Ok(ServeConnectionOutput::default());
             }
         };
-        let _ = server.serve(TMSInternalEnclave::default());
+        let _ = server.start();
     } else if args.port == external.addr.port() {
         let enclave_attr = match external.inbound_desc {
             config::InboundDesc::External => None,
             _ => unreachable!(),
         };
 
-        let config = PipeConfig {
-            fd: args.socket_fd,
-            retry: 0,
-            client_attr: enclave_attr,
-        };
-
-        let mut server = match Pipe::start(config) {
+        let server = match SgxTrustedServer::new(
+            TMSExternalEnclave::default(),
+            args.socket_fd,
+            enclave_attr,
+        ) {
             Ok(s) => s,
             Err(e) => {
-                error!("Start Pipe failed: {}", e);
+                error!("New server failed: {:?}.", e);
                 return Ok(ServeConnectionOutput::default());
             }
         };
-
-        let _ = server.serve(TMSExternalEnclave::default());
+        let _ = server.start();
     } else {
         unreachable!()
     }