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
25 #include <network/socket.h>
26 #include <processing/jobs/callback_job.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
53 pthread_mutex_t mutex
;
56 * condvar to signal for packets in list
58 pthread_cond_t condvar
;
62 * implements sender_t.send
64 static void send_(private_sender_t
*this, packet_t
*packet
)
68 src
= packet
->get_source(packet
);
69 dst
= packet
->get_destination(packet
);
70 DBG1(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
72 pthread_mutex_lock(&this->mutex
);
73 this->list
->insert_last(this->list
, packet
);
74 pthread_mutex_unlock(&this->mutex
);
75 pthread_cond_signal(&this->condvar
);
79 * Implementation of private_sender_t.send_packets.
81 static job_requeue_t
send_packets(private_sender_t
* this)
86 pthread_mutex_lock(&this->mutex
);
87 while (this->list
->get_count(this->list
) == 0)
89 /* add cleanup handler, wait for packet, remove cleanup handler */
90 pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock
, (void*)&this->mutex
);
91 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
93 pthread_cond_wait(&this->condvar
, &this->mutex
);
95 pthread_setcancelstate(oldstate
, NULL
);
96 pthread_cleanup_pop(0);
98 this->list
->remove_first(this->list
, (void**)&packet
);
99 pthread_mutex_unlock(&this->mutex
);
101 charon
->socket
->send(charon
->socket
, packet
);
102 packet
->destroy(packet
);
103 return JOB_REQUEUE_DIRECT
;
107 * Implementation of sender_t.destroy.
109 static void destroy(private_sender_t
*this)
111 /* send all packets in the queue */
112 while (this->list
->get_count(this->list
))
116 this->job
->cancel(this->job
);
117 this->list
->destroy(this->list
);
122 * Described in header.
124 sender_t
* sender_create()
126 private_sender_t
*this = malloc_thing(private_sender_t
);
128 this->public.send
= (void(*)(sender_t
*,packet_t
*))send_
;
129 this->public.destroy
= (void(*)(sender_t
*)) destroy
;
131 this->list
= linked_list_create();
132 pthread_mutex_init(&this->mutex
, NULL
);
133 pthread_cond_init(&this->condvar
, NULL
);
135 this->job
= callback_job_create((callback_job_cb_t
)send_packets
,
137 charon
->processor
->queue_job(charon
->processor
, (job_t
*)this->job
);
139 return &this->public;