docs: def serve_API(self, client, addr):
          """ Read client request and call target SDK API"""
          self.log_debug("(%s:%s) Handling new request from client." %
                         (addr[0], addr[1]))
          results = None
          try:
              data = client.recv(4096)
              data = bytes.decode(data)
              # When client failed to send the data or quit before sending the
              # data, server side would receive null data.
              # In such case, server would not send back any info and just
              # terminate this thread.
              if not data:
                  self.log_warn("(%s:%s) Failed to receive data from client." %
                                (addr[0], addr[1]))
                  return
              api_data = json.loads(data)
  
              # API_data should be in the form [funcname, args_list, kwargs_dict]
              if not isinstance(api_data, list) or len(api_data) != 3:
                  msg = ("(%s:%s) SDK server got wrong input: '%s' from client."
                         % (addr[0], addr[1], data))
                  results = self.construct_internal_error(msg)
                  return
  
              # Check called API is supported by SDK
              (func_name, api_args, api_kwargs) = api_data
              self.log_debug("(%s:%s) Request func: %s, args: %s, kwargs: %s" %
                             (addr[0], addr[1], func_name, str(api_args),
                              str(api_kwargs)))
              try:
                  api_func = getattr(self.sdkapi, func_name)
              except AttributeError:
                  msg = ("(%s:%s) SDK server got wrong API name: %s from"
                         "client." % (addr[0], addr[1], func_name))
                  results = self.construct_api_name_error(msg)
                  return
  
              # invoke target API function
              return_data = api_func(*api_args, **api_kwargs)
          except exception.SDKBaseException as e:
              self.log_error("(%s:%s) %s" % (addr[0], addr[1],
                                             traceback.format_exc()))
              # get the error info from exception attribute
              # All SDKbaseexception should eventually has a
              # results attribute defined which can be used by
              # sdkserver here
              if e.results is None:
                  msg = ("(%s:%s) SDK server got exception without results "
                         "defined, error: %s" % (addr[0], addr[1],
                                                 e.format_message()))
                  results = self.construct_internal_error(msg)
              else:
                  results = {'overallRC': e.results['overallRC'],
                             'modID': e.results['modID'],
                             'rc': e.results['rc'],
                             'rs': e.results['rs'],
                             'errmsg': e.format_message(),
                             'output': ''}
          except Exception as e:
              self.log_error("(%s:%s) %s" % (addr[0], addr[1],
                                             traceback.format_exc()))
              msg = ("(%s:%s) SDK server got unexpected exception: "
                     "%s" % (addr[0], addr[1], repr(e)))
              results = self.construct_internal_error(msg)
          else:
              if return_data is None:
                  return_data = ''
              results = {'overallRC': 0, 'modID': None,
                         'rc': 0, 'rs': 0,
                         'errmsg': '',
                         'output': return_data}
          # Send back the final results
          try:
              if results is not None:
                  self.send_results(client, addr, results)
          except Exception as e:
              # This should not happen in normal case.
              # A special case is the server side socket is closed/removed
              # before the send() action.
              self.log_error("(%s:%s) %s" % (addr[0], addr[1], repr(e)))
          finally:
              # Close the connection to make sure the thread socket got
              # closed even when it got unexpected exceptions.
              self.log_debug("(%s:%s) Finish handling request, closing "
                             "socket." % (addr[0], addr[1]))
              client.close()