2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
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>.
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
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>
29 typedef struct private_sender_t private_sender_t
;
32 * Private data of a sender_t object.
34 struct private_sender_t
{
36 * Public part of a sender_t object.
46 * The packets are stored in a linked list
51 * mutex to synchronize access to list
56 * condvar to signal for packets added to list
61 * condvar to signal for packets sent
66 METHOD(sender_t
, send_
, void,
67 private_sender_t
*this, packet_t
*packet
)
71 src
= packet
->get_source(packet
);
72 dst
= packet
->get_destination(packet
);
73 DBG1(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
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
);
82 * Job callback function to send packets
84 static job_requeue_t
send_packets(private_sender_t
* this)
89 this->mutex
->lock(this->mutex
);
90 while (this->list
->get_count(this->list
) == 0)
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
);
96 this->got
->wait(this->got
, this->mutex
);
98 thread_cancelability(oldstate
);
99 thread_cleanup_pop(FALSE
);
101 this->list
->remove_first(this->list
, (void**)&packet
);
102 this->sent
->signal(this->sent
);
103 this->mutex
->unlock(this->mutex
);
105 charon
->socket
->send(charon
->socket
, packet
);
106 packet
->destroy(packet
);
107 return JOB_REQUEUE_DIRECT
;
110 METHOD(sender_t
, destroy
, void,
111 private_sender_t
*this)
113 /* send all packets in the queue */
114 this->mutex
->lock(this->mutex
);
115 while (this->list
->get_count(this->list
))
117 this->sent
->wait(this->sent
, this->mutex
);
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
);
129 * Described in header.
131 sender_t
* sender_create()
133 private_sender_t
*this;
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
,
148 charon
->processor
->queue_job(charon
->processor
, (job_t
*)this->job
);
150 return &this->public;