Reimplement the KEEPALIVE status message.
[pwmd.git] / src / status.c
blobb21ec6a807aabe0f77fe04a4cfd7936d7bc775b6
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <pthread.h>
25 #include <stdarg.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
29 #ifdef HAVE_LINUX_SOCKIOS_H
30 #include <linux/sockios.h>
31 #endif
33 #include "pwmd-error.h"
34 #include "mutex.h"
35 #include "util-misc.h"
36 #include "common.h"
37 #include "util-string.h"
38 #include "status.h"
39 #include "cache.h"
40 #include "mem.h"
42 gpg_error_t
43 send_status (assuan_context_t ctx, status_msg_t which, const char *fmt, ...)
45 const char *line = NULL;
46 char buf[ASSUAN_LINELENGTH + 1];
47 const char *status = NULL;
48 va_list ap;
49 char *p;
50 struct client_s *client = ctx ? assuan_get_pointer (ctx) : NULL;
51 gpg_error_t rc = 0;
53 if (fmt)
55 va_start (ap, fmt);
56 vsnprintf (buf, sizeof (buf), fmt, ap);
57 va_end (ap);
58 line = buf;
61 switch (which)
63 case STATUS_GENKEY:
64 status = "GENKEY";
65 break;
66 case STATUS_XFER:
67 status = "XFER";
68 break;
69 case STATUS_CACHE:
70 snprintf (buf, sizeof (buf), "%u", cache_file_count ());
71 line = buf;
72 status = "CACHE";
73 break;
74 case STATUS_CLIENTS:
75 MUTEX_LOCK (&cn_mutex);
76 snprintf (buf, sizeof (buf), "%i", slist_length (cn_thread_list));
77 line = buf;
78 MUTEX_UNLOCK (&cn_mutex);
79 status = "CLIENTS";
80 break;
81 case STATUS_LOCKED:
82 status = "LOCKED";
83 line = _("Waiting for lock");
84 break;
85 case STATUS_ENCRYPT:
86 status = "ENCRYPT";
87 break;
88 case STATUS_DECRYPT:
89 status = "DECRYPT";
90 break;
91 case STATUS_NEWFILE:
92 status = "NEWFILE";
93 break;
94 case STATUS_KEEPALIVE:
95 status = "KEEPALIVE";
96 break;
97 case STATUS_AGENT:
98 p = strchr (line, ' ');
99 if (!p)
101 status = line;
102 line = NULL;
104 else
106 *p = 0;
107 status = line;
108 line = line + strlen (status) + 1;
110 break;
113 if (!ctx)
115 log_write ("%s %s", status, line ? line : "");
116 return 0;
119 #ifdef WITH_GNUTLS
120 if (client && client->thd->remote && which == STATUS_KEEPALIVE)
122 #ifdef HAVE_DECL_SIOCOUTQ
123 int buffered;
124 if (ioctl (client->thd->fd, SIOCOUTQ, &buffered) == -1)
125 log_write ("%s(%i): ioctl: %s", __FUNCTION__, __LINE__,
126 pwmd_strerror (gpg_error_from_syserror ()));
127 else if (buffered)
129 int interval = config_get_integer ("global", "keepalive_interval");
130 int timeout = config_get_integer ("global", "tls_timeout");
132 if (++client->thd->buffer_timeout * interval >= timeout)
133 rc = gpg_error (GPG_ERR_ETIMEDOUT);
135 #endif
137 #endif
139 if (!rc)
140 rc = assuan_write_status (ctx, status, line);
142 if (which != STATUS_KEEPALIVE)
143 client->thd->buffer_timeout = 0;
145 return rc;
148 void
149 send_status_all (status_msg_t s, const char *fmt, ...)
151 MUTEX_LOCK (&cn_mutex);
152 int i = 0;
153 int t = slist_length (cn_thread_list);
155 for (; i < t; i++)
157 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
158 struct status_msg_s *msg, *p;
159 char c = 0xff;
160 int match = 0;
162 MUTEX_LOCK (&thd->status_mutex);
164 for (p = thd->msg_queue; p; p = p->next)
166 if (p->s == s)
168 match = 1;
169 break;
173 if (match)
175 MUTEX_UNLOCK (&thd->status_mutex);
176 continue;
179 msg = xcalloc (1, sizeof (struct status_msg_s));
180 msg->s = s;
181 if (fmt)
183 va_list ap;
185 va_start (ap, fmt);
186 str_vasprintf (&msg->line, fmt, ap);
187 va_end (ap);
190 for (p = thd->msg_queue; p && p->next; p = p->next);
191 if (!p)
192 thd->msg_queue = msg;
193 else
194 p->next = msg;
196 write (thd->status_msg_pipe[1], &c, 1);
197 MUTEX_UNLOCK (&thd->status_mutex);
200 MUTEX_UNLOCK (&cn_mutex);