Remove send_bin_buffer().
[paraslash.git] / client_common.c
index 865a1797bd81bbd7e6308278c08249890c1bf241..5ac1cdb77ced80efe804c7017d9f4ec7a03bc940 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2012 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #define CLIENT_BUFSIZE 4000
 
 /**
- * Close the connection to para_server and free all resources.
+ * Close the connection to para_server and deallocate per-command ressources.
  *
- * \param ct Pointer to the client data.
+ * \param ct The client task.
  *
- * \sa client_open.
+ * This frees all ressources of the current command but keeps the configuration
+ * in \p ct->conf.
+ *
+ * \sa \ref client_close().
  */
-void client_close(struct client_task *ct)
+void client_disconnect(struct client_task *ct)
 {
        if (!ct)
                return;
        if (ct->scc.fd >= 0)
                close(ct->scc.fd);
        sc_free(ct->scc.recv);
+       ct->scc.recv = NULL;
        sc_free(ct->scc.send);
+       ct->scc.send = NULL;
+       btr_free_node(ct->btrn);
+       ct->btrn = NULL;
+}
+
+/**
+ * Close the connection to para_server and free all resources.
+ *
+ * \param ct Pointer to the client data.
+ *
+ * \sa \ref client_open(), \ref client_disconnect().
+ */
+void client_close(struct client_task *ct)
+{
+       if (!ct)
+               return;
+       client_disconnect(ct);
        free(ct->user);
        free(ct->config_file);
        free(ct->key_file);
@@ -197,8 +218,7 @@ static void client_post_select(struct sched *s, struct task *t)
                        SESSION_KEY_LEN);
                hash_to_asc(challenge_hash, buf);
                PARA_INFO_LOG("--> %s\n", buf);
-               ret = send_bin_buffer(ct->scc.fd, (char *)challenge_hash,
-                       HASH_SIZE);
+               ret = write_all(ct->scc.fd, (char *)challenge_hash, HASH_SIZE);
                if (ret < 0)
                        goto out;
                ct->status = CL_SENT_CH_RESPONSE;
@@ -308,25 +328,43 @@ out:
        }
 }
 
-/* connect to para_server and register the client task */
-static int client_connect(struct client_task *ct)
+/**
+ * Connect to para_server and register the client task.
+ *
+ * \param ct The initialized client task structure.
+ * \param s The scheduler instance to register the client task to.
+ * \param parent The parent node of the client btr node.
+ * \param child The child node of the client node.
+ *
+ * The client task structure given by \a ct  must be allocated and initialized
+ * by \ref client_parse_config() before this function is called.
+ *
+ * \return Standard.
+ */
+int client_connect(struct client_task *ct, struct sched *s,
+               struct btr_node *parent, struct btr_node *child)
 {
        int ret;
 
+       PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
+               ct->conf.server_port_arg);
        ct->scc.fd = -1;
        ret = para_connect_simple(IPPROTO_TCP, ct->conf.hostname_arg,
                                               ct->conf.server_port_arg);
        if (ret < 0)
                return ret;
        ct->scc.fd = ret;
-       ct->status = CL_CONNECTED;
        ret = mark_fd_nonblocking(ct->scc.fd);
        if (ret < 0)
                goto err_out;
+       ct->status = CL_CONNECTED;
+       ct->btrn = btr_new_node(&(struct btr_node_description)
+               EMBRACE(.name = "client", .parent = parent, .child = child));
        ct->task.pre_select = client_pre_select;
        ct->task.post_select = client_post_select;
+       ct->task.error = 0;
        sprintf(ct->task.status, "client");
-       register_task(&ct->task);
+       register_task(s, &ct->task);
        return 1;
 err_out:
        close(ct->scc.fd);
@@ -335,40 +373,36 @@ err_out:
 }
 
 /**
- * Open connection to para_server.
+ * Parse a client configuration.
  *
  * \param argc Usual argument count.
  * \param argv Usual argument vector.
- * \param ct_ptr Points to dynamically allocated and initialized client task
- * struct upon successful return.
+ * \param ct_ptr Filled in by this function.
  * \param loglevel If not \p NULL, the number of the loglevel is stored here.
- * \param parent Add the new buffer tree node as a child of this node.
- * \param child Add the new buffer tree node as a parent of this node.
  *
- * Check the command line options given by \a argc and argv, set default values
- * for user name and rsa key file, read further option from the config file.
- * Finally, establish a connection to para_server.
+ * This checks the command line options given by \a argc and \a argv, sets
+ * default values for the user name and the name of the rsa key file and reads
+ * further options from the config file.
  *
- * \return Standard.
+ * Upon successful return, \a ct_ptr points to a dynamically allocated and
+ * initialized client task struct.
+ *
+ * \return The number of non-option arguments in \a argc/argv on success,
+ * negative on errors.
  */
-int client_open(int argc, char *argv[], struct client_task **ct_ptr,
-               int *loglevel, struct btr_node *parent, struct btr_node *child)
+int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
+               int *loglevel)
 {
        char *home = para_homedir();
        int ret;
        struct client_task *ct = para_calloc(sizeof(struct client_task));
 
-       ct->btrn = btr_new_node(&(struct btr_node_description)
-               EMBRACE(.name = "client", .parent = parent, .child = child));
        *ct_ptr = ct;
        ct->scc.fd = -1;
        ret = -E_CLIENT_SYNTAX;
        if (client_cmdline_parser(argc, argv, &ct->conf))
                goto out;
        HANDLE_VERSION_FLAG("client", ct->conf);
-       ret = -E_CLIENT_SYNTAX;
-       if (!ct->conf.inputs_num)
-               goto out;
 
        ct->config_file = ct->conf.config_file_given?
                para_strdup(ct->conf.config_file_arg) :
@@ -410,17 +444,52 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr,
        PARA_INFO_LOG("loglevel: %s\n", ct->conf.loglevel_arg);
        PARA_INFO_LOG("config_file: %s\n", ct->config_file);
        PARA_INFO_LOG("key_file: %s\n", ct->key_file);
-       PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
-               ct->conf.server_port_arg);
-       ret = client_connect(ct);
+       ret = ct->conf.inputs_num;
 out:
        free(home);
        if (ret < 0) {
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-               btr_remove_node(ct->btrn);
-               btr_free_node(ct->btrn);
                client_close(ct);
                *ct_ptr = NULL;
        }
        return ret;
 }
+
+/**
+ * Parse the client configuration and open a connection to para_server.
+ *
+ * \param argc See \ref client_parse_config.
+ * \param argv See \ref client_parse_config.
+ * \param ct_ptr See \ref client_parse_config.
+ * \param loglevel See \ref client_parse_config.
+ * \param parent See \ref client_connect().
+ * \param child See \ref client_connect().
+ * \param sched See \ref client_connect().
+ *
+ * This function combines client_parse_config() and client_connect(). It is
+ * considered a syntax error if no command was given, i.e. if the number
+ * of non-option arguments is zero.
+ *
+ * \return Standard.
+ */
+int client_open(int argc, char *argv[], struct client_task **ct_ptr,
+               int *loglevel, struct btr_node *parent, struct btr_node *child,
+               struct sched *sched)
+{
+       int ret = client_parse_config(argc, argv, ct_ptr, loglevel);
+
+       if (ret < 0)
+               return ret;
+       if (ret == 0) {
+               ret = -E_CLIENT_SYNTAX;
+               goto fail;
+       }
+       ret = client_connect(*ct_ptr, sched, parent, child);
+       if (ret < 0)
+               goto fail;
+       return 1;
+fail:
+       client_close(*ct_ptr);
+       *ct_ptr = NULL;
+       return ret;
+}