Migrated sender_t to METHOD/INIT macros
[strongswan.git] / src / charon / network / sender.c
1 /*
2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18
19 #include "sender.h"
20
21 #include <daemon.h>
22 #include <network/socket.h>
23 #include <processing/jobs/callback_job.h>
24 #include <threading/thread.h>
25 #include <threading/condvar.h>
26 #include <threading/mutex.h>
27
28
29 typedef struct private_sender_t private_sender_t;
30
31 /**
32 * Private data of a sender_t object.
33 */
34 struct private_sender_t {
35 /**
36 * Public part of a sender_t object.
37 */
38 sender_t public;
39
40 /**
41 * Sender threads job.
42 */
43 callback_job_t *job;
44
45 /**
46 * The packets are stored in a linked list
47 */
48 linked_list_t *list;
49
50 /**
51 * mutex to synchronize access to list
52 */
53 mutex_t *mutex;
54
55 /**
56 * condvar to signal for packets added to list
57 */
58 condvar_t *got;
59
60 /**
61 * condvar to signal for packets sent
62 */
63 condvar_t *sent;
64 };
65
66 METHOD(sender_t, send_, void,
67 private_sender_t *this, packet_t *packet)
68 {
69 host_t *src, *dst;
70
71 src = packet->get_source(packet);
72 dst = packet->get_destination(packet);
73 DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
74
75 this->mutex->lock(this->mutex);
76 this->list->insert_last(this->list, packet);
77 this->got->signal(this->got);
78 this->mutex->unlock(this->mutex);
79 }
80
81 /**
82 * Job callback function to send packets
83 */
84 static job_requeue_t send_packets(private_sender_t * this)
85 {
86 packet_t *packet;
87 bool oldstate;
88
89 this->mutex->lock(this->mutex);
90 while (this->list->get_count(this->list) == 0)
91 {
92 /* add cleanup handler, wait for packet, remove cleanup handler */
93 thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
94 oldstate = thread_cancelability(TRUE);
95
96 this->got->wait(this->got, this->mutex);
97
98 thread_cancelability(oldstate);
99 thread_cleanup_pop(FALSE);
100 }
101 this->list->remove_first(this->list, (void**)&packet);
102 this->sent->signal(this->sent);
103 this->mutex->unlock(this->mutex);
104
105 charon->socket->send(charon->socket, packet);
106 packet->destroy(packet);
107 return JOB_REQUEUE_DIRECT;
108 }
109
110 METHOD(sender_t, destroy, void,
111 private_sender_t *this)
112 {
113 /* send all packets in the queue */
114 this->mutex->lock(this->mutex);
115 while (this->list->get_count(this->list))
116 {
117 this->sent->wait(this->sent, this->mutex);
118 }
119 this->mutex->unlock(this->mutex);
120 this->job->cancel(this->job);
121 this->list->destroy(this->list);
122 this->got->destroy(this->got);
123 this->sent->destroy(this->sent);
124 this->mutex->destroy(this->mutex);
125 free(this);
126 }
127
128 /*
129 * Described in header.
130 */
131 sender_t * sender_create()
132 {
133 private_sender_t *this;
134
135 INIT(this,
136 .public = {
137 .send = _send_,
138 .destroy = _destroy,
139 },
140 .list = linked_list_create(),
141 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
142 .got = condvar_create(CONDVAR_TYPE_DEFAULT),
143 .sent = condvar_create(CONDVAR_TYPE_DEFAULT),
144 .job = callback_job_create((callback_job_cb_t)send_packets,
145 this, NULL, NULL),
146 );
147
148 charon->processor->queue_job(charon->processor, (job_t*)this->job);
149
150 return &this->public;
151 }
152