summaryrefslogtreecommitdiffstats
path: root/lib/clplumbing/ipctransientserver.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/clplumbing/ipctransientserver.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/lib/clplumbing/ipctransientserver.c b/lib/clplumbing/ipctransientserver.c
new file mode 100644
index 0000000..d7ee61d
--- /dev/null
+++ b/lib/clplumbing/ipctransientserver.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <ipctransient.h>
+
+gboolean transient_server_callback(IPC_Channel *client, gpointer user_data);
+gboolean transient_server_connect(IPC_Channel *client_channel, gpointer user_data);
+int init_server_ipc_comms(const char *child,
+ gboolean (*channel_client_connect)(IPC_Channel *newclient, gpointer user_data),
+ void (*channel_input_destroy)(gpointer user_data),
+ gboolean usenormalpoll);
+
+int
+main(int argc, char ** argv)
+{
+ int iteration = 0;
+ GMainLoop* mainloop = NULL;
+
+ trans_getargs(argc, argv);
+
+ cl_log_set_entity(procname);
+ cl_log_enable_stderr(TRUE);
+
+ init_server_ipc_comms("echo", transient_server_connect, default_ipctest_input_destroy, FALSE);
+
+ /* wait for the reply by creating a mainloop and running it until
+ * the callbacks are invoked...
+ */
+ mainloop = g_main_new(FALSE);
+
+ cl_log(LOG_INFO, "#--#--#--# Echo Server %d is active...", iteration);
+ g_main_run(mainloop);
+ cl_log(LOG_INFO, "#--#--#--# Echo Server %d is stopped...", iteration);
+
+ return 0;
+}
+
+
+int
+init_server_ipc_comms(const char *child,
+ gboolean (*channel_client_connect)(IPC_Channel *newclient, gpointer user_data),
+ void (*channel_input_destroy)(gpointer user_data),
+ gboolean usenormalpoll)
+{
+ /* the clients wait channel is the other source of events.
+ * This source delivers the clients connection events.
+ * listen to this source at a relatively lower priority.
+ */
+ mode_t mask;
+ IPC_WaitConnection *wait_ch;
+ GHashTable * attrs;
+ int local_sock_len = 2; /* 2 = '/' + '\0' */
+ char *commpath = NULL;
+ static char path[] = IPC_PATH_ATTR;
+
+ local_sock_len += strlen(child);
+ local_sock_len += strlen(commdir);
+
+ commpath = (char*)malloc(sizeof(char)*local_sock_len);
+ if (commpath == NULL){
+ cl_log(LOG_ERR, "%s: allocating memory failed", __FUNCTION__);
+ exit(1);
+ }
+ snprintf(commpath, local_sock_len, "%s/%s", commdir, child);
+ commpath[local_sock_len - 1] = '\0';
+
+ attrs = g_hash_table_new(g_str_hash,g_str_equal);
+ g_hash_table_insert(attrs, path, commpath);
+
+ mask = umask(0);
+ wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs);
+ if (wait_ch == NULL){
+ cl_perror("[Server] Can't create wait channel of type %s", IPC_ANYTYPE);
+ exit(1);
+ }
+ mask = umask(mask);
+ g_hash_table_destroy(attrs);
+
+ G_main_add_IPC_WaitConnection(G_PRIORITY_LOW,
+ wait_ch,
+ NULL,
+ FALSE,
+ channel_client_connect,
+ wait_ch, /* user data passed to ?? */
+ channel_input_destroy);
+
+ cl_log(LOG_INFO, "[Server] Listening on: %s", commpath);
+
+/* if (!usenormalpoll) { */
+/* g_main_set_poll_func(cl_glibpoll); */
+/* ipc_set_pollfunc(cl_poll); */
+/* } */
+ return 0;
+}
+
+gboolean
+transient_server_callback(IPC_Channel *client, gpointer user_data)
+{
+ int lpc = 0;
+ IPC_Message *msg = NULL;
+ char *buffer = NULL;
+ IPC_Message *reply = NULL;
+ int llpc = 0;
+
+ cl_log(LOG_DEBUG, "channel: %p", client);
+
+ cl_log(LOG_DEBUG, "Client status %d (disconnect=%d)", client->ch_status, IPC_DISCONNECT);
+
+ while(client->ops->is_message_pending(client)) {
+ if (client->ch_status == IPC_DISCONNECT) {
+ /* The message which was pending for us is that
+ * the IPC status is now IPC_DISCONNECT */
+ break;
+ }
+ if(client->ops->recv(client, &msg) != IPC_OK) {
+ cl_perror("[Server] Receive failure");
+ return FALSE;
+ }
+
+ if (msg != NULL) {
+ lpc++;
+ buffer = (char*)g_malloc(msg->msg_len+1);
+ memcpy(buffer,msg->msg_body, msg->msg_len);
+ buffer[msg->msg_len] = '\0';
+ cl_log(LOG_DEBUG, "[Server] Got xml [text=%s]", buffer);
+
+ reply = create_simple_message(strdup(buffer), client);
+ if (!reply) {
+ cl_log(LOG_ERR, "[Server] Could allocate reply msg.");
+ return FALSE;
+ }
+
+ llpc = 0;
+ while(llpc++ < MAX_IPC_FAIL && client->ops->send(client, reply) == IPC_FAIL) {
+ cl_log(LOG_WARNING, "[Server] ipc channel blocked");
+ cl_shortsleep();
+ }
+
+ if(lpc == MAX_IPC_FAIL) {
+ cl_log(LOG_ERR, "[Server] Could not send IPC, message. Channel is dead.");
+ free(reply);
+ return FALSE;
+ }
+
+ cl_log(LOG_DEBUG, "[Server] Sent reply");
+ msg->msg_done(msg);
+ } else {
+ cl_log(LOG_ERR, "[Server] No message this time");
+ continue;
+ }
+ }
+
+ cl_log(LOG_DEBUG, "[Server] Processed %d messages", lpc);
+
+ cl_log(LOG_DEBUG, "[Server] Client status %d", client->ch_status);
+ if(client->ch_status != IPC_CONNECT) {
+ cl_log(LOG_INFO, "[Server] Server received HUP from child");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+gboolean
+transient_server_connect(IPC_Channel *client_channel, gpointer user_data)
+{
+ /* assign the client to be something, or put in a hashtable */
+ cl_log(LOG_DEBUG, "A client tried to connect... and there was much rejoicing.");
+
+ if(client_channel == NULL) {
+ cl_log(LOG_ERR, "[Server] Channel was NULL");
+ } else if(client_channel->ch_status == IPC_DISCONNECT) {
+ cl_log(LOG_ERR, "[Server] Channel was disconnected");
+ } else {
+ cl_log(LOG_DEBUG, "[Server] Client is %s %p", client_channel == NULL?"NULL":"valid", client_channel);
+ cl_log(LOG_DEBUG, "[Server] Client status %d (disconnect=%d)", client_channel->ch_status, IPC_DISCONNECT);
+
+ cl_log(LOG_DEBUG, "[Server] Adding IPC Channel to main thread.");
+ G_main_add_IPC_Channel(G_PRIORITY_LOW,
+ client_channel,
+ FALSE,
+ transient_server_callback,
+ NULL,
+ default_ipctest_input_destroy);
+ }
+
+ return TRUE;
+}