summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-10-18 07:17:38 +0200
committerDaiki Ueno <ueno@gnu.org>2020-10-18 19:18:09 +0200
commite748eac332661781a010b92cb2ce6d6c080d0b15 (patch)
tree8e4447a7bcfd80f55cf38b226025a248d1cc22fc
parent90f14691e1a269bf3247537e6da374f472b64d25 (diff)
downloadgnutls-e748eac332661781a010b92cb2ce6d6c080d0b15.tar.gz
serv: replace our own list implementation with Gnulib's gl_list
Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--bootstrap.conf2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/list.h446
-rw-r--r--src/serv.c125
-rw-r--r--src/udp-serv.c1
5 files changed, 85 insertions, 491 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index f8de3d4be1..36b6d58f8e 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -36,7 +36,7 @@ unictype/category-all unictype/property-default-ignorable-code-point unictype/pr
"
src_modules="
-accept bind close connect getaddrinfo getpass gettext-h arpa_inet inet_ntop inet_pton listen minmax parse-datetime progname read-file recv recvfrom select send sendto servent setsockopt shutdown socket sockets socklen inttypes
+accept bind close connect getaddrinfo getpass gettext-h arpa_inet inet_ntop inet_pton inttypes listen linked-list minmax parse-datetime progname read-file recv recvfrom select send sendto servent setsockopt shutdown socket sockets socklen xalloc xlist
"
# Build prerequisites
diff --git a/src/Makefile.am b/src/Makefile.am
index 94b701a512..450700a3d0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -140,7 +140,7 @@ nodist_libcmd_ocsp_la_SOURCES = ocsptool-args.h ocsptool-args.c
endif
gnutls_serv_SOURCES = \
- list.h serv.c \
+ serv.c \
udp-serv.c udp-serv.h \
common.h common.c \
certtool-common.h
diff --git a/src/list.h b/src/list.h
deleted file mode 100644
index 1b3c9e4635..0000000000
--- a/src/list.h
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2001,2002 Paul Sheer
- *
- * This file is part of GnuTLS.
- *
- * GnuTLS 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 3 of the License, or
- * (at your option) any later version.
- *
- * GnuTLS 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 program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef GNUTLS_SRC_LIST_H
-#define GNUTLS_SRC_LIST_H
-
-/*
- SOAP:
-
- Academics always want to implement hash tables (i.e. dictionaries),
- singly or doubly linked lists, and queues, because ... well ... they
- know how.
-
- These datatypes are nonsense for the following reasons:
- hash tables: Hash tables are a mapping of some
- string to some data, where that data is going to
- be accessed COMPLETELY RANDOMLY. This is what it
- is for. However it is extremely rare to have a
- large number of data elements which really are
- being accessed in a completely random way.
-
- lists: appending and searching through lists is always
- slow because these operations search all the way
- through the list.
-
- queues: what's the difference between a queue and a list?
- very little really.
-
- The system implemented here is a doubly linked list with previous
- search index that can be appended or prepended with no overhead,
- implemented entirely in macros. It is hence as versatile as a
- doubly/singly linked list or queue and blazingly fast. Hence doing
- sequential searches where the next search result is likely to be
- closely indexed to the previous (usual case), is efficient.
-
- Of course this doesn't mean you should use this as a hash table
- where you REALLY need a hash table.
-
-*/
-
-/********** example usage **********/
-/*
-
-#include "list.h"
-
-extern void free (void *x);
-extern char *strdup (char *s);
-
-// consider a list of elements containing an `int' and a `char *'
-LIST_TYPE_DECLARE (names, char *s; int i;);
-
-// for sorting, to compare elements
-static int cm (names **a, names **b)
-{
- return strcmp ((*a)->s, (*b)->s);
-}
-
-// to free the contents of an element
-static void free_item (names *a)
-{
- free (a->s);
- a->s = 0; // say
- a->i = 0; // say
-}
-
-int main (int argc, char **argv)
-{
-// you can separate these into LIST_TYPE_DECLARE(), LIST_DECLARE() and linit() if needed.
- LIST_DECLARE_INIT (l, names, free_item);
- names *j;
-
- lappend (l);
- l.tail->s = strdup ("hello");
- l.tail->i = 1;
- lappend (l);
- l.tail->s = strdup ("there");
- l.tail->i = 2;
- lappend (l);
- l.tail->s = strdup ("my");
- l.tail->i = 3;
- lappend (l);
- l.tail->s = strdup ("name");
- l.tail->i = 4;
- lappend (l);
- l.tail->s = strdup ("is");
- l.tail->i = 5;
- lappend (l);
- l.tail->s = strdup ("fred");
- l.tail->i = 6;
-
- printf ("%ld\n\n", lcount (l));
- lloopforward (l, j, printf ("%d %s\n", j->i, j->s));
- printf ("\n");
-
- lsort (l, cm);
- lloopforward (l, j, printf ("%d %s\n", j->i, j->s));
-
- lloopreverse (l, j, if (j->i <= 3) ldeleteinc (l, j););
-
- printf ("\n");
- lloopforward (l, j, printf ("%d %s\n", j->i, j->s));
-
- ldeleteall (l);
-
- printf ("\n");
- lloopforward (l, j, printf ("%d %s\n", j->i, j->s));
- return 0;
-}
-
-*/
-
-/* the `search' member points to the last found.
- this speeds up repeated searches on the same list-item,
- the consecutive list-item, or the pre-consecutive list-item.
- this obviates the need for a hash table for 99% of
- cercumstances the time */
-struct list {
- long length;
- long item_size;
- struct list_item {
- struct list_item *next;
- struct list_item *prev;
- char data[1];
- } *head, *tail, *search;
- void (*free_func) (struct list_item *);
-};
-
-/* declare a list of type `x', also called `x' having members `typelist' */
-
-#define LIST_TYPE_DECLARE(type,typelist) \
- typedef struct type { \
- struct type *next; \
- struct type *prev; \
- typelist \
- } type
-
-#define LIST_DECLARE(l,type) \
- struct { \
- long length; \
- long item_size; \
- type *head, *tail, *search; \
- void (*free_func) (type *); \
- } l
-
-#define LIST_DECLARE_INIT(l,type,free) \
- struct { \
- long length; \
- long item_size; \
- type *head, *tail, *search; \
- void (*free_func) (type *); \
- } l = {0, sizeof (type), 0, 0, 0, (void (*) (type *)) free}
-
-#define linit(l,type,free) \
- { \
- memset (&(l), 0, sizeof (l)); \
- (l).item_size = sizeof (type); \
- (l).free_func = free; \
- }
-
-/* returns a pointer to the data of an item */
-#define ldata(i) ((void *) &((i)->data[0]))
-
-/* returns a pointer to the list head */
-#define lhead(l) ((l).head)
-
-/* returns a pointer to the list tail */
-#define ltail(l) ((l).tail)
-
-#define lnewsearch(l) \
- (l).search = 0;
-
-/* adds to the beginning of the list */
-#define lprepend(l) \
- { \
- struct list_item *__t; \
- __t = (struct list_item *) malloc ((l).item_size); \
- memset (__t, 0, (l).item_size); \
- __t->next = (l).head; \
- if (__t->next) \
- __t->next->prev = __t; \
- __t->prev = 0; \
- if (!(l).tail) \
- (l).tail = __t; \
- (l).head = __t; \
- length++; \
- }
-
-/* adds to the end of the list */
-#define lappend(l) \
- { \
- struct list_item *__t; \
- __t = (struct list_item *) malloc ((l).item_size); \
- memset (__t, 0, (l).item_size); \
- __t->prev = (struct list_item *) (l).tail; \
- if (__t->prev) \
- __t->prev->next = __t; \
- __t->next = 0; \
- if (!(l).head) \
- (l).head = (void *) __t; \
- (l).tail = (void *) __t; \
- (l).length++; \
- }
-
-/* you should free these manually */
-#define lunlink(l,e) \
- { \
- struct list_item *__t; \
- (l).search = 0; \
- __t = (void *) e; \
- if ((void *) (l).head == (void *) __t) \
- (l).head = (l).head->next; \
- if ((void *) (l).tail == (void *) __t) \
- (l).tail = (l).tail->prev; \
- if (__t->next) \
- __t->next->prev = __t->prev; \
- if (__t->prev) \
- __t->prev->next = __t->next; \
- (l).length--; \
- }
-
-/* deletes list entry at point e, and increments e to the following list entry */
-#define ldeleteinc(l,e) \
- { \
- struct list_item *__t; \
- (l).search = 0; \
- __t = (void *) e; \
- if ((void *) (l).head == (void *) __t) \
- (l).head = (l).head->next; \
- if ((void *) (l).tail == (void *) __t) \
- (l).tail = (l).tail->prev; \
- if (__t->next) \
- __t->next->prev = __t->prev; \
- if (__t->prev) \
- __t->prev->next = __t->next; \
- __t = __t->next; \
- if ((l).free_func) \
- (*(l).free_func) ((void *) e); \
- free (e); \
- e = (void *) __t; \
- (l).length--; \
- }
-
-/* deletes list entry at point e, and deccrements e to the preceding list emtry */
-#define ldeletedec(l,e) \
- { \
- struct list_item *__t; \
- (l).search = 0; \
- __t = (void *) e; \
- if ((void *) (l).head == (void *) __t) \
- (l).head = (l).head->next; \
- if ((void *) (l).tail == (void *) __t) \
- (l).tail = (l).tail->prev; \
- if (__t->next) \
- __t->next->prev = __t->prev; \
- if (__t->prev) \
- __t->prev->next = __t->next; \
- __t = __t->prev; \
- if ((l).free_func) \
- (*(l).free_func) ((void *) e); \
- free (e); \
- e = (void *) __t; \
- (l).length--; \
- }
-
-/* p and q must be consecutive and neither must be zero */
-#define linsert(l,p,q) \
- { \
- struct list_item *__t; \
- __t = (struct list_item *) malloc ((l).item_size); \
- memset (__t, 0, (l).item_size); \
- __t->prev = (void *) p; \
- __t->next = (void *) q; \
- q->prev = (void *) __t; \
- p->next = (void *) __t; \
- (l).length++; \
- }
-
-/* p and q must be consecutive and neither must be zero */
-#define ldeleteall(l) \
- { \
- (l).search = 0; \
- while ((l).head) { \
- struct list_item *__p; \
- __p = (struct list_item *) (l).head; \
- lunlink(l, __p); \
- if ((l).free_func) \
- (*(l).free_func) ((void *) __p); \
- free (__p); \
- } \
- }
-
-#define lloopstart(l,i) \
- for (i = (void *) (l).head; i;) { \
- struct list_item *__tl; \
- __tl = (void *) i->next; \
-
-#define lloopend(l,i) \
- i = (void *) __tl; \
- } \
-
-#define lloopforward(l,i,op) \
- { \
- for (i = (void *) (l).head; i;) { \
- struct list_item *__t; \
- __t = (void *) i->next; \
- op; \
- i = (void *) __t; \
- } \
- }
-
-#define lloopreverse(l,i,op) \
- { \
- for (i = (void *) (l).tail; i;) { \
- struct list_item *__t; \
- __t = (void *) i->prev; \
- op; \
- i = (void *) __t; \
- } \
- }
-
-#define lindex(l,i,n) \
- { \
- int __k; \
- for (__k = 0, i = (void *) (l).head; i && __k != n; i = i->next, __k++); \
- }
-
-#define lsearchforward(l,i,op) \
- { \
- int __found = 0; \
- if (!__found) \
- if ((i = (void *) (l).search)) { \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- if (!__found) \
- if ((i = (void *) (l).search->next)) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- if (!__found) \
- if ((i = (void *) (l).search->prev)) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- } \
- if (!__found) \
- for (i = (void *) (l).head; i; i = i->next) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- break; \
- } \
- }
-
-#define lsearchreverse(l,i,op) \
- { \
- int __found = 0; \
- if (!__found) \
- if ((i = (void *) (l).search)) { \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- if (!__found) \
- if ((i = (void *) (l).search->prev)) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- if (!__found) \
- if ((i = (void *) (l).search->next)) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- } \
- } \
- if (!__found) \
- for (i = (void *) (l).tail; i; i = i->prev) \
- if (op) { \
- __found = 1; \
- (l).search = (void *) i; \
- break; \
- } \
- }
-
-#define lcount(l) ((l).length)
-
-/* sort with comparison function see qsort(3) */
-#define larray(l,a) \
- { \
- long __i; \
- struct list_item *__p; \
- a = (void *) malloc (((l).length + 1) * sizeof (void *)); \
- for (__i = 0, __p = (void *) (l).head; __p; __p = __p->next, __i++) \
- a[__i] = (void *) __p; \
- a[__i] = 0; \
- } \
-
-/* sort with comparison function see qsort(3) */
-#define llist(l,a) \
- { \
- struct list_item *__p; \
- (l).head = (void *) a[0]; \
- (l).search = 0; \
- __p = (void *) a[0]; \
- __p->prev = 0; \
- for (__j = 1; a[__j]; __j++, __p = __p->next) { \
- __p->next = (void *) a[__j]; \
- __p->next->prev = __p; \
- } \
- (l).tail = (void *) __p; \
- __p->next = 0; \
- } \
-
-/* sort with comparison function see qsort(3) */
-#define lsort(l,compare) \
- { \
- void **__t; \
- long __j; \
- larray (l,__t); \
- qsort (__t, (l).length, sizeof (void *), (int (*) (const void *, const void *)) compare); \
- llist (l,__t); \
- free (__t); \
- } \
-
-#endif /* GNUTLS_SRC_LIST_H */
diff --git a/src/serv.c b/src/serv.c
index 5198b58c65..629c398529 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -28,6 +28,7 @@
#include "common.h"
#include "serv-args.h"
+#include "udp-serv.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
@@ -38,16 +39,17 @@
#include <sys/time.h>
#include <sys/select.h>
#include <fcntl.h>
-#include <list.h>
#include <netdb.h>
#include <unistd.h>
#include <socket.h>
/* Gnulib portability files. */
-#include "read-file.h"
+#include "gl_linked_list.h"
+#include "gl_xlist.h"
#include "minmax.h"
+#include "read-file.h"
#include "sockets.h"
-#include "udp-serv.h"
+#include "xalloc.h"
/* konqueror cannot handle sending the page in multiple
* pieces.
@@ -145,16 +147,21 @@ static void cmd_parser(int argc, char **argv);
#define HTTP_STATE_RESPONSE 2
#define HTTP_STATE_CLOSING 3
-LIST_TYPE_DECLARE(listener_item, char *http_request; char *http_response;
- int request_length; int response_length;
- int response_written; int http_state;
- int listen_socket; int fd;
- gnutls_session_t tls_session;
- int handshake_ok;
- int close_ok;
- time_t start;
- int earlydata_eof;
- );
+typedef struct {
+ char *http_request;
+ char *http_response;
+ int request_length;
+ int response_length;
+ int response_written;
+ int http_state;
+ int listen_socket;
+ int fd;
+ gnutls_session_t tls_session;
+ int handshake_ok;
+ int close_ok;
+ time_t start;
+ int earlydata_eof;
+} listener_item;
static const char *safe_strerror(int value)
{
@@ -164,8 +171,9 @@ static const char *safe_strerror(int value)
return ret;
}
-static void listener_free(listener_item * j)
+static void listener_free(const void *elt)
{
+ listener_item *j = (listener_item *)elt;
free(j->http_request);
free(j->http_response);
@@ -275,7 +283,7 @@ get_params(gnutls_session_t session, gnutls_params_type_t type,
return 0;
}
-LIST_DECLARE_INIT(listener_list, listener_item, listener_free);
+static gl_list_t listener_list;
static int cert_verify_callback(gnutls_session_t session)
{
@@ -865,21 +873,25 @@ const char *human_addr(const struct sockaddr *sa, socklen_t salen,
int wait_for_connection(void)
{
- listener_item *j;
fd_set rd, wr;
int n, sock = -1;
+ gl_list_iterator_t iter;
+ const void *elt;
FD_ZERO(&rd);
FD_ZERO(&wr);
n = 0;
- lloopstart(listener_list, j) {
+ iter = gl_list_iterator(listener_list);
+ while (gl_list_iterator_next(&iter, &elt, NULL)) {
+ const listener_item *j = elt;
+
if (j->listen_socket) {
FD_SET(j->fd, &rd);
n = MAX(n, j->fd);
}
}
- lloopend(listener_list, j);
+ gl_list_iterator_free(&iter);
/* waiting part */
n = select(n + 1, &rd, &wr, NULL, NULL);
@@ -891,14 +903,17 @@ int wait_for_connection(void)
}
/* find which one is ready */
- lloopstart(listener_list, j) {
+ iter = gl_list_iterator(listener_list);
+ while (gl_list_iterator_next(&iter, &elt, NULL)) {
+ const listener_item *j = elt;
+
/* a new connection has arrived */
if (FD_ISSET(j->fd, &rd) && j->listen_socket) {
sock = j->fd;
break;
}
}
- lloopend(listener_list, j);
+ gl_list_iterator_free(&iter);
return sock;
}
@@ -997,8 +1012,8 @@ int listen_socket(const char *name, int listen_port, int socktype)
}
/* new list entry for the connection */
- lappend(listener_list);
- j = listener_list.tail;
+ j = xzalloc(sizeof(*j));
+ gl_list_add_last(listener_list, j);
j->listen_socket = 1;
j->fd = s;
@@ -1151,6 +1166,10 @@ int main(int argc, char **argv)
sockets_init();
+ listener_list = gl_list_create_empty(GL_LINKED_LIST,
+ NULL, NULL, listener_free,
+ true);
+
if (nodb == 0)
wrap_db_init();
@@ -1499,7 +1518,12 @@ static void tcp_server(const char *name, int port)
exit(1);
for (;;) {
- listener_item *j;
+ gl_list_iterator_t iter;
+ gl_list_node_t node;
+ const void *elt;
+ gl_list_t accepted_list = gl_list_create_empty(GL_LINKED_LIST,
+ NULL, NULL, NULL,
+ true);
fd_set rd, wr;
time_t now = time(0);
#ifndef _WIN32
@@ -1511,7 +1535,9 @@ static void tcp_server(const char *name, int port)
n = 0;
/* flag which connections we are reading or writing to within the fd sets */
- lloopstart(listener_list, j) {
+ iter = gl_list_iterator(listener_list);
+ while (gl_list_iterator_next(&iter, &elt, &node)) {
+ listener_item *j = (listener_item *)elt;
#ifndef _WIN32
val = fcntl(j->fd, F_GETFL, 0);
@@ -1541,8 +1567,9 @@ static void tcp_server(const char *name, int port)
FD_SET(j->fd, &wr);
n = MAX(n, j->fd);
}
+ gl_list_node_set_value(listener_list, node, j);
}
- lloopend(listener_list, j);
+ gl_list_iterator_free(&iter);
/* core operation */
tv.tv_sec = 10;
@@ -1556,7 +1583,9 @@ static void tcp_server(const char *name, int port)
}
/* read or write to each connection as indicated by select()'s return argument */
- lloopstart(listener_list, j) {
+ iter = gl_list_iterator(listener_list);
+ while (gl_list_iterator_next(&iter, &elt, &node)) {
+ listener_item *j = (listener_item *)elt;
/* a new connection has arrived */
if (FD_ISSET(j->fd, &rd) && j->listen_socket) {
@@ -1573,23 +1602,24 @@ static void tcp_server(const char *name, int port)
char timebuf[SIMPLE_CTIME_BUF_SIZE];
time_t tt = time(0);
char *ctt;
+ listener_item *jj;
/* new list entry for the connection */
- lappend(listener_list);
- j = listener_list.tail;
- j->http_request =
+ jj = xzalloc(sizeof(*jj));
+ gl_list_add_last(accepted_list, jj);
+ jj->http_request =
(char *) strdup("");
- j->http_state = HTTP_STATE_REQUEST;
- j->fd = accept_fd;
- j->start = tt;
+ jj->http_state = HTTP_STATE_REQUEST;
+ jj->fd = accept_fd;
+ jj->start = tt;
- j->tls_session = initialize_session(0);
- gnutls_session_set_ptr(j->tls_session, j);
+ jj->tls_session = initialize_session(0);
+ gnutls_session_set_ptr(jj->tls_session, jj);
gnutls_transport_set_int
- (j->tls_session, accept_fd);
- set_read_funcs(j->tls_session);
- j->handshake_ok = 0;
- j->close_ok = 0;
+ (jj->tls_session, accept_fd);
+ set_read_funcs(jj->tls_session);
+ jj->handshake_ok = 0;
+ jj->close_ok = 0;
if (verbose != 0) {
ctt = simple_ctime(&tt, timebuf);
@@ -1775,16 +1805,27 @@ static void tcp_server(const char *name, int port)
j->http_state = HTTP_STATE_REQUEST;
}
}
+ gl_list_node_set_value(listener_list, node, j);
}
- lloopend(listener_list, j);
+ gl_list_iterator_free(&iter);
/* loop through all connections, closing those that are in error */
- lloopstart(listener_list, j) {
+ iter = gl_list_iterator(listener_list);
+ while (gl_list_iterator_next(&iter, &elt, &node)) {
+ const listener_item *j = elt;
+
if (j->http_state == HTTP_STATE_CLOSING) {
- ldeleteinc(listener_list, j);
+ gl_list_remove_node(listener_list, node);
}
}
- lloopend(listener_list, j);
+ gl_list_iterator_free(&iter);
+
+ iter = gl_list_iterator(accepted_list);
+ while (gl_list_iterator_next(&iter, &elt, &node)) {
+ gl_list_add_last(listener_list, elt);
+ }
+ gl_list_iterator_free(&iter);
+ gl_list_free(accepted_list);
}
diff --git a/src/udp-serv.c b/src/udp-serv.c
index 9b71719fd2..814d698fbf 100644
--- a/src/udp-serv.c
+++ b/src/udp-serv.c
@@ -37,7 +37,6 @@
#include <common.h>
#include "udp-serv.h"
#include "serv-args.h"
-#include "list.h"
extern int disable_client_cert;