fixed reauthentication when connections other is %any
[strongswan.git] / src / charon / queues / send_queue.c
1 /**
2 * @file send_queue.c
3 *
4 * @brief Implementation of send_queue_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <pthread.h>
25
26 #include "send_queue.h"
27
28 #include <utils/linked_list.h>
29 #include <bus/bus.h>
30 #include <daemon.h>
31
32
33 typedef struct private_send_queue_t private_send_queue_t;
34
35 /**
36 * @brief Private Variables and Functions of send_queue class
37 *
38 */
39 struct private_send_queue_t {
40 /**
41 * Public part of the send_queue_t object
42 */
43 send_queue_t public;
44
45 /**
46 * The packets are stored in a linked list
47 */
48 linked_list_t *list;
49
50 /**
51 * access to linked_list is locked through this mutex
52 */
53 pthread_mutex_t mutex;
54
55 /**
56 * If the queue is empty a thread has to wait
57 * This condvar is used to wake up such a thread
58 */
59 pthread_cond_t condvar;
60 };
61
62 /**
63 * implements send_queue_t.get_count
64 */
65 static int get_count(private_send_queue_t *this)
66 {
67 int count;
68 pthread_mutex_lock(&this->mutex);
69 count = this->list->get_count(this->list);
70 pthread_mutex_unlock(&this->mutex);
71 return count;
72 }
73
74 /**
75 * implements send_queue_t.get
76 */
77 static packet_t *get(private_send_queue_t *this)
78 {
79 int oldstate;
80 packet_t *packet;
81
82 pthread_mutex_lock(&this->mutex);
83
84 /* go to wait while no packets available */
85 while(this->list->get_count(this->list) == 0)
86 {
87 /* add mutex unlock handler for cancellation, enable cancellation */
88 pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex);
89 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
90 pthread_cond_wait(&this->condvar, &this->mutex);
91
92 /* reset cancellation, remove mutex-unlock handler (without executing) */
93 pthread_setcancelstate(oldstate, NULL);
94 pthread_cleanup_pop(0);
95 }
96 this->list->remove_first(this->list, (void**)&packet);
97 pthread_mutex_unlock(&this->mutex);
98 return packet;
99 }
100
101 /**
102 * implements send_queue_t.add
103 */
104 static void add(private_send_queue_t *this, packet_t *packet)
105 {
106 host_t *src, *dst;
107
108 src = packet->get_source(packet);
109 dst = packet->get_destination(packet);
110 DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
111
112 pthread_mutex_lock(&this->mutex);
113 this->list->insert_last(this->list, packet);
114 pthread_cond_signal(&this->condvar);
115 pthread_mutex_unlock(&this->mutex);
116 }
117
118 /**
119 * implements send_queue_t.destroy
120 */
121 static void destroy (private_send_queue_t *this)
122 {
123 this->list->destroy_offset(this->list, offsetof(packet_t, destroy));
124 free(this);
125 }
126
127 /*
128 * Documented in header
129 */
130 send_queue_t *send_queue_create(void)
131 {
132 private_send_queue_t *this = malloc_thing(private_send_queue_t);
133
134 this->public.get_count = (int(*)(send_queue_t*)) get_count;
135 this->public.get = (packet_t*(*)(send_queue_t*)) get;
136 this->public.add = (void(*)(send_queue_t*, packet_t*)) add;
137 this->public.destroy = (void(*)(send_queue_t*)) destroy;
138
139 this->list = linked_list_create();
140 pthread_mutex_init(&this->mutex, NULL);
141 pthread_cond_init(&this->condvar, NULL);
142
143 return (&this->public);
144 }