2 * Copyright (C) 2008-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "ha_sync_socket.h"
17 #include "ha_sync_plugin.h"
19 #include <sys/types.h>
20 #include <sys/socket.h>
26 #include <utils/host.h>
27 #include <processing/jobs/callback_job.h>
29 typedef struct private_ha_sync_socket_t private_ha_sync_socket_t
;
32 * Private data of an ha_sync_socket_t object.
34 struct private_ha_sync_socket_t
{
37 * Public ha_sync_socket_t interface.
39 ha_sync_socket_t
public;
42 * UDP communication socket fd
47 * local host to receive/send from
52 * remote host to receive/send to
58 * Data to pass to the send_message() callback job
61 ha_sync_message_t
*message
;
62 private_ha_sync_socket_t
*this;
68 static void job_data_destroy(job_data_t
*this)
70 this->message
->destroy(this->message
);
75 * Callback to asynchronously send messages
77 static job_requeue_t
send_message(job_data_t
*data
)
79 private_ha_sync_socket_t
*this;
83 chunk
= data
->message
->get_encoding(data
->message
);
84 if (sendto(this->fd
, chunk
.ptr
, chunk
.len
, 0,
85 this->remote
->get_sockaddr(this->remote
),
86 *this->remote
->get_sockaddr_len(this->remote
)) < chunk
.len
)
88 DBG1(DBG_CFG
, "pushing HA sync message failed: %s", strerror(errno
));
90 return JOB_REQUEUE_NONE
;
94 * Implementation of ha_sync_socket_t.push
96 static void push(private_ha_sync_socket_t
*this, ha_sync_message_t
*message
)
101 data
= malloc_thing(job_data_t
);
102 data
->message
= message
;
105 /* we send sync message asynchronously. This is required, as sendto()
106 * is a blocking call if it acquires a policy. Otherwise we could
107 * end up in a deadlock, as we own an IKE_SA. */
108 job
= callback_job_create((callback_job_cb_t
)send_message
,
109 data
, (void*)job_data_destroy
, NULL
);
110 charon
->processor
->queue_job(charon
->processor
, (job_t
*)job
);
115 * Implementation of ha_sync_socket_t.pull
117 static ha_sync_message_t
*pull(private_ha_sync_socket_t
*this)
121 ha_sync_message_t
*message
;
126 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
127 len
= recv(this->fd
, buf
, sizeof(buf
), 0);
128 pthread_setcancelstate(oldstate
, NULL
);
137 DBG1(DBG_CFG
, "pulling HA sync message failed: %s",
142 message
= ha_sync_message_parse(chunk_create(buf
, len
));
151 * Open and connect the HA sync socket
153 static bool open_socket(private_ha_sync_socket_t
*this)
155 this->fd
= socket(this->local
->get_family(this->local
), SOCK_DGRAM
, 0);
158 DBG1(DBG_CFG
, "opening HA sync socket failed: %s", strerror(errno
));
162 if (bind(this->fd
, this->local
->get_sockaddr(this->local
),
163 *this->local
->get_sockaddr_len(this->local
)) == -1)
165 DBG1(DBG_CFG
, "binding HA sync socket failed: %s", strerror(errno
));
170 if (connect(this->fd
, this->remote
->get_sockaddr(this->remote
),
171 *this->remote
->get_sockaddr_len(this->remote
)) == -1)
173 DBG1(DBG_CFG
, "connecting HA sync socket failed: %s", strerror(errno
));
183 * Implementation of ha_sync_socket_t.destroy.
185 static void destroy(private_ha_sync_socket_t
*this)
191 DESTROY_IF(this->local
);
192 DESTROY_IF(this->remote
);
199 ha_sync_socket_t
*ha_sync_socket_create(char *local
, char *remote
)
201 private_ha_sync_socket_t
*this = malloc_thing(private_ha_sync_socket_t
);
203 this->public.push
= (void(*)(ha_sync_socket_t
*, ha_sync_message_t
*))push
;
204 this->public.pull
= (ha_sync_message_t
*(*)(ha_sync_socket_t
*))pull
;
205 this->public.destroy
= (void(*)(ha_sync_socket_t
*))destroy
;
207 this->local
= host_create_from_dns(local
, 0, HA_SYNC_PORT
);
208 this->remote
= host_create_from_dns(remote
, 0, HA_SYNC_PORT
);
211 if (!this->local
|| !this->remote
)
213 DBG1(DBG_CFG
, "invalid local/remote HA sync address");
217 if (!open_socket(this))
222 return &this->public;