def call(self, func, *api_args, **api_kwargs):
        """Send API call to SDK server and return results"""
        if not isinstance(func, str) or (func == ''):
            msg = ('Invalid input for API name, should be a'
                   'string, type: %s specified.') % type(func)
            return self._construct_api_name_error(msg)

        # Create client socket
        try:
            cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        except socket.error as err:
            return self._construct_socket_error(1, error=six.text_type(err))

        try:
            # Set socket timeout
            cs.settimeout(self.timeout)
            # Connect SDK server
            try:
                cs.connect((self.addr, self.port))
            except socket.error as err:
                return self._construct_socket_error(2, addr=self.addr,
                                                    port=self.port,
                                                    error=six.text_type(err))

            # Prepare the data to be sent and switch to bytes if needed
            api_data = json.dumps((func, api_args, api_kwargs))
            api_data = api_data.encode()

            # Send the API call data to SDK server
            sent = 0
            total_len = len(api_data)
            got_error = False
            try:
                while (sent < total_len):
                    this_sent = cs.send(api_data[sent:])
                    if this_sent == 0:
                        got_error = True
                        break
                    sent += this_sent
            except socket.error as err:
                return self._construct_socket_error(5,
                                                    error=six.text_type(err))

            if got_error or sent != total_len:
                return self._construct_socket_error(3, sent=sent,
                                                    api=api_data)

            # Receive data from server
            return_blocks = []
            try:
                while True:
                    block = cs.recv(4096)
                    if not block:
                        break
                    block = bytes.decode(block)
                    return_blocks.append(block)
            except socket.error as err:
                # When the sdkserver cann't handle all the client request,
                # some client request would be rejected.
                # Under this case, the client socket can successfully
                # connect/send, but would get exception in recv with error:
                # "error: [Errno 104] Connection reset by peer"
                return self._construct_socket_error(6,
                                                    error=six.text_type(err))
        finally:
            # Always close the client socket to avoid too many hanging
            # socket left.
            cs.close()

        # Transform the received stream to standard result form
        # This client assumes that the server would return result in
        # the standard result form, so client just return the received
        # data
        if return_blocks:
            results = json.loads(''.join(return_blocks))
        else:
            results = self._construct_socket_error(4)
        return results
Send API call to SDK server and return results