moved interface enumeration code to socket, where it belongs
[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
86 pthread_mutex_lock(&this->mutex);
87
88 /* go to wait while no packets available */
89 while(this->list->get_count(this->list) == 0)
90 {
91 /* add mutex unlock handler for cancellation, enable cancellation */
92 pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex);
93 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
94 pthread_cond_wait(&this->condvar, &this->mutex);
95
96 /* reset cancellation, remove mutex-unlock handler (without executing) */
97 pthread_setcancelstate(oldstate, NULL);
98 pthread_cleanup_pop(0);
99 }
100 this->list->remove_first(this->list, (void**)&packet);
101 pthread_mutex_unlock(&this->mutex);
102 return packet;
103 }
104
105 /**
106 * implements send_queue_t.add
107 */
108 static void add(private_send_queue_t *this, packet_t *packet)
109 {
110 host_t *src, *dst;
111
112 src = packet->get_source(packet);
113 dst = packet->get_destination(packet);
114 this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d",
115 src->get_string(src), src->get_port(src),
116 dst->get_string(dst), dst->get_port(dst));
117
118 pthread_mutex_lock(&this->mutex);
119 this->list->insert_last(this->list, packet);
120 pthread_cond_signal(&this->condvar);
121 pthread_mutex_unlock(&this->mutex);
122 }
123
124 /**
125 * implements send_queue_t.destroy
126 */
127 static void destroy (private_send_queue_t *this)
128 {
129 packet_t *packet;
130 while (this->list->remove_last(this->list, (void**)&packet) == SUCCESS)
131 {
132 packet->destroy(packet);
133 }
134 this->list->destroy(this->list);
135 pthread_mutex_destroy(&(this->mutex));
136 pthread_cond_destroy(&(this->condvar));
137 free(this);
138 }
139
140 /*
141 *
142 * Documented in header
143 */
144 send_queue_t *send_queue_create(void)
145 {
146 private_send_queue_t *this = malloc_thing(private_send_queue_t);
147
148 this->public.get_count = (int(*)(send_queue_t*)) get_count;
149 this->public.get = (packet_t*(*)(send_queue_t*)) get;
150 this->public.add = (void(*)(send_queue_t*, packet_t*)) add;
151 this->public.destroy = (void(*)(send_queue_t*)) destroy;
152
153 this->list = linked_list_create();
154 pthread_mutex_init(&this->mutex, NULL);
155 pthread_cond_init(&this->condvar, NULL);
156 this->logger = logger_manager->get_logger(logger_manager, SOCKET);
157
158 return (&this->public);
159 }