1112beffbee790be94be0f58fb0d531a8a58f5a7
[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 <utils/logger_manager.h>
30
31
32 typedef struct private_send_queue_t private_send_queue_t;
33
34 /**
35 * @brief Private Variables and Functions of send_queue class
36 *
37 */
38 struct private_send_queue_t {
39 /**
40 * Public part of the send_queue_t object
41 */
42 send_queue_t public;
43
44 /**
45 * The packets are stored in a linked list
46 */
47 linked_list_t *list;
48
49 /**
50 * access to linked_list is locked through this mutex
51 */
52 pthread_mutex_t mutex;
53
54 /**
55 * If the queue is empty a thread has to wait
56 * This condvar is used to wake up such a thread
57 */
58 pthread_cond_t condvar;
59
60 /**
61 * Logger reference
62 */
63 logger_t *logger;
64 };
65
66 /**
67 * implements send_queue_t.get_count
68 */
69 static int get_count(private_send_queue_t *this)
70 {
71 int count;
72 pthread_mutex_lock(&(this->mutex));
73 count = this->list->get_count(this->list);
74 pthread_mutex_unlock(&(this->mutex));
75 return count;
76 }
77
78 /**
79 * implements send_queue_t.get
80 */
81 static packet_t *get(private_send_queue_t *this)
82 {
83 int oldstate;
84 packet_t *packet;
85 pthread_mutex_lock(&(this->mutex));
86 /* go to wait while no packets available */
87
88 while(this->list->get_count(this->list) == 0)
89 {
90 /* add mutex unlock handler for cancellation, enable cancellation */
91 pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex));
92 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
93 pthread_cond_wait( &(this->condvar), &(this->mutex));
94
95 /* reset cancellation, remove mutex-unlock handler (without executing) */
96 pthread_setcancelstate(oldstate, NULL);
97 pthread_cleanup_pop(0);
98 }
99 this->list->remove_first(this->list,(void **)&packet);
100 pthread_mutex_unlock(&(this->mutex));
101 return packet;
102 }
103
104 /**
105 * implements send_queue_t.add
106 */
107 static void add(private_send_queue_t *this, packet_t *packet)
108 {
109 host_t *src, *dst;
110
111 src = packet->get_source(packet);
112 dst = packet->get_destination(packet);
113 this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d",
114 src->get_address(src), src->get_port(src),
115 dst->get_address(dst), dst->get_port(dst));
116
117 pthread_mutex_lock(&(this->mutex));
118 this->list->insert_last(this->list,packet);
119 pthread_cond_signal( &(this->condvar));
120 pthread_mutex_unlock(&(this->mutex));
121 }
122
123 /**
124 * implements send_queue_t.destroy
125 */
126 static void destroy (private_send_queue_t *this)
127 {
128
129 /* destroy all packets in list before destroying list */
130 while (this->list->get_count(this->list) > 0)
131 {
132 packet_t *packet;
133 if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS)
134 {
135 this->list->destroy(this->list);
136 break;
137 }
138 packet->destroy(packet);
139 }
140 this->list->destroy(this->list);
141
142 pthread_mutex_destroy(&(this->mutex));
143
144 pthread_cond_destroy(&(this->condvar));
145
146 free(this);
147 }
148
149 /*
150 *
151 * Documented in header
152 */
153 send_queue_t *send_queue_create(void)
154 {
155 private_send_queue_t *this = malloc_thing(private_send_queue_t);
156
157 this->public.get_count = (int(*)(send_queue_t*)) get_count;
158 this->public.get = (packet_t*(*)(send_queue_t*)) get;
159 this->public.add = (void(*)(send_queue_t*, packet_t*)) add;
160 this->public.destroy = (void(*)(send_queue_t*)) destroy;
161
162 this->list = linked_list_create();
163 pthread_mutex_init(&(this->mutex), NULL);
164 pthread_cond_init(&(this->condvar), NULL);
165 this->logger = logger_manager->get_logger(logger_manager, SOCKET);
166
167 return (&this->public);
168 }