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/>.
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
29 #ifdef HAVE_LINUX_SOCKIOS_H
30 #include <linux/sockios.h>
33 #ifdef HAVE_SYS_FILIO_H
34 #include <sys/filio.h>
37 #include "pwmd-error.h"
39 #include "util-misc.h"
41 #include "util-string.h"
47 send_status (assuan_context_t ctx
, status_msg_t which
, const char *fmt
, ...)
49 const char *line
= NULL
;
50 char buf
[ASSUAN_LINELENGTH
+ 1];
51 const char *status
= NULL
;
55 struct client_s
*client
= ctx
? assuan_get_pointer (ctx
) : NULL
;
62 vsnprintf (buf
, sizeof (buf
), fmt
, ap
);
76 snprintf (buf
, sizeof (buf
), "%u", cache_file_count ());
81 MUTEX_LOCK (&cn_mutex
);
82 snprintf (buf
, sizeof (buf
), "%i", slist_length (cn_thread_list
));
84 MUTEX_UNLOCK (&cn_mutex
);
89 line
= _("Waiting for lock");
100 case STATUS_KEEPALIVE
:
101 status
= "KEEPALIVE";
104 p
= strchr (line
, ' ');
114 line
= line
+ strlen (status
) + 1;
121 log_write ("%s %s", status
, line
? line
: "");
126 if (client
->thd
->remote
&& which
== STATUS_KEEPALIVE
)
130 #ifdef HAVE_DECL_SIOCOUTQ
131 if (ioctl (client
->thd
->fd
, SIOCOUTQ
, &buffered
) == -1)
132 log_write ("%s(%i): ioctl: %s", __FUNCTION__
, __LINE__
,
133 pwmd_strerror (gpg_error_from_syserror ()));
134 #elif defined (HAVE_DECL_FIONWRITE)
135 if (ioctl (client
->thd
->fd
, FIONWRITE
, &buffered
) == -1)
136 log_write ("%s(%i): ioctl: %s", __FUNCTION__
, __LINE__
,
137 pwmd_strerror (gpg_error_from_syserror ()));
142 socklen_t len
= sizeof(int);
144 if (getsockopt (client
->thd
->fd
, SOL_SOCKET
, SO_SNDBUF
, &sndbuf
,
146 log_write ("%s(%i): getsockopt: %s", __FUNCTION__
, __LINE__
,
147 pwmd_strerror (gpg_error_from_syserror ()));
153 if (getsockopt (client
->thd
->fd
, SOL_SOCKET
, SO_SNDLOWAT
,
155 log_write ("%s(%i): getsockopt: %s", __FUNCTION__
,
156 __LINE__
, pwmd_strerror (gpg_error_from_syserror ()));
160 if (setsockopt (client
->thd
->fd
, SOL_SOCKET
, SO_SNDLOWAT
,
162 log_write ("%s(%i): setsockopt: %s", __FUNCTION__
,
164 pwmd_strerror (gpg_error_from_syserror ()));
167 struct timeval tv
= { 0, 0 };
171 buffered
= client
->thd
->last_buffer_size
+ 1;
173 FD_SET (client
->thd
->fd
, &wfds
);
174 n
= select (client
->thd
->fd
+ 1, NULL
, &wfds
, NULL
, &tv
);
176 if (setsockopt (client
->thd
->fd
, SOL_SOCKET
, SO_SNDLOWAT
,
178 log_write ("%s(%i): setsockopt: %s", __FUNCTION__
,
180 pwmd_strerror (gpg_error_from_syserror ()));
181 if (n
> 0 && FD_ISSET (client
->thd
->fd
, &wfds
))
190 int interval
= config_get_integer ("global", "keepalive_interval");
191 int timeout
= config_get_integer ("global", "tls_timeout");
193 if (buffered
< client
->thd
->last_buffer_size
)
194 client
->thd
->buffer_timeout
= 0;
196 client
->thd
->last_buffer_size
= buffered
;
198 if (++client
->thd
->buffer_timeout
* interval
>= timeout
)
199 rc
= gpg_error (GPG_ERR_ETIMEDOUT
);
202 client
->thd
->buffer_timeout
= client
->thd
->last_buffer_size
= 0;
207 rc
= assuan_write_status (ctx
, status
, line
);
210 if (client
->thd
->remote
&& which
!= STATUS_KEEPALIVE
)
211 client
->thd
->buffer_timeout
= client
->thd
->last_buffer_size
= 0;
218 send_status_all (status_msg_t s
, const char *fmt
, ...)
220 MUTEX_LOCK (&cn_mutex
);
222 int t
= slist_length (cn_thread_list
);
226 struct client_thread_s
*thd
= slist_nth_data (cn_thread_list
, i
);
227 struct status_msg_s
*msg
, *p
;
231 MUTEX_LOCK (&thd
->status_mutex
);
233 for (p
= thd
->msg_queue
; p
; p
= p
->next
)
244 MUTEX_UNLOCK (&thd
->status_mutex
);
248 msg
= xcalloc (1, sizeof (struct status_msg_s
));
255 str_vasprintf (&msg
->line
, fmt
, ap
);
259 for (p
= thd
->msg_queue
; p
&& p
->next
; p
= p
->next
);
261 thd
->msg_queue
= msg
;
265 write (thd
->status_msg_pipe
[1], &c
, 1);
266 MUTEX_UNLOCK (&thd
->status_mutex
);
269 MUTEX_UNLOCK (&cn_mutex
);