2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file lockmanager/gnunet-service-lockmanager.c
23 * @brief implementation of the LOCKMANAGER service
24 * @author Sree Harsha Totakura
28 #include "gnunet_common.h"
29 #include "gnunet_container_lib.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_service_lib.h"
32 #include "gnunet_server_lib.h"
34 #include "lockmanager.h"
36 #define VERBOSE GNUNET_YES
38 #define LOG(kind,...) \
39 GNUNET_log (kind, __VA_ARGS__)
41 #define TIME_REL_MINS(min) \
42 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, min)
44 #define TIMEOUT TIME_REL_MINS(3)
48 * Doubly linked list of clients waiting for a lock
53 * The next client structure
55 struct WaitList *next;
58 * The prev client structure
60 struct WaitList *prev;
63 * Pointer to the client
65 struct GNUNET_SERVER_Client *client;
70 * A Lock element for a doubly linked list
75 * The next element pointer
77 struct LockList *next;
80 * Pointer to the previous element
82 struct LockList *prev;
85 * The client whizch is currently holding this lock
87 struct GNUNET_SERVER_Client *client;
90 * List head of clients waiting for this lock
92 struct WaitList *wait_list_head;
95 * List tail of clients waiting for this lock
97 struct WaitList *wait_list_tail;
100 * The name of the locking domain this lock belongs to
105 * The number of this lock
112 * Doubly linked list of clients having connections to us
117 * The next client structure
119 struct ClientList *next;
122 * The previous client structure
124 struct ClientList *prev;
127 * Pointer to the client
129 struct GNUNET_SERVER_Client *client;
134 * Head of the doubly linked list of the currently held locks
136 static struct LockList *ll_head;
139 * Tail of the doubly linked list of the currently held locks
141 static struct LockList *ll_tail;
144 * Head of the doubly linked list of clients currently connected
146 static struct ClientList *cl_head;
149 * Tail of the doubly linked list of clients currently connected
151 static struct ClientList *cl_tail;
156 * Function to search for a lock in lock_list matching the given domain_name and
159 * @param domain_name the name of the locking domain
160 * @param lock_num the number of the lock
161 * @param ret this will be the pointer to the corresponding Lock if found; else
162 * it will be the last element in the locks list
163 * @return GNUNET_YES if a matching lock is present in lock_list; GNUNET_NO if not
166 ll_find_lock (const char *domain_name,
167 const uint32_t lock_num,
168 struct LockList **ret)
170 struct LockList *current_lock;
172 current_lock = ll_head;
174 while (NULL != current_lock)
176 if ( (0 == strcmp (domain_name, current_lock->domain_name))
177 && (lock_num == current_lock->lock_num))
183 current_lock = current_lock->next;
192 * Function to append a lock to the global lock list
194 * @param domain_name the name of the locking domain
195 * @param domain_name_len the length of the domain name
196 * @param lock_num the number of the lock
197 * @param tail the pointer to the tail of the global lock list
200 ll_add_lock (const char *domain_name,
201 size_t domain_name_len,
202 const uint32_t lock_num)
204 struct LockList *lock;
206 lock = GNUNET_malloc (sizeof (struct LockList));
207 lock->domain_name = GNUNET_malloc (domain_name_len);
208 strncpy (lock->domain_name, domain_name, domain_name_len);
209 lock->lock_num = lock_num;
211 GNUNET_CONTAINER_DLL_insert_tail (ll_head,
218 * Function to delete a lock from the lock list
220 * @param lock the lock to be deleted
223 ll_remove_lock (struct LockList *lock)
225 GNUNET_assert (NULL != ll_head);
226 GNUNET_CONTAINER_DLL_remove (ll_head,
229 GNUNET_free (lock->domain_name);
235 * Find a client in the waiting list of a lock
237 * @param lock the LockList entry of a lock
238 * @param client the client to look for
239 * @param ret where to store the matched wait list entry
240 * @return GNUNET_YES if a match is found; GNUNET_NO if not
243 ll_wl_find_client (struct LockList *lock,
244 const struct GNUNET_SERVER_Client *client,
245 struct WaitList **ret)
247 struct WaitList *current_wl_entry;
249 current_wl_entry = lock->wait_list_head;
251 while (NULL != current_wl_entry)
253 if (client == current_wl_entry->client)
255 *ret = current_wl_entry;
258 current_wl_entry = current_wl_entry->next;
260 *ret = current_wl_entry;
266 * Add a client to the wait list of a lock
268 * @param lock the lock list entry of a lock
269 * @param client the client to queue for the lock's wait list
272 ll_wl_add_client (struct LockList *lock,
273 struct GNUNET_SERVER_Client *client)
275 struct WaitList *wl_entry;
277 wl_entry = GNUNET_malloc (sizeof (struct WaitList));
278 wl_entry->client = client;
279 GNUNET_CONTAINER_DLL_insert_tail (lock->wait_list_head,
280 lock->wait_list_tail,
286 ll_wl_remove_client (struct LockList *lock,
287 struct WaitList *wl_client)
289 GNUNET_CONTAINER_DLL_remove (lock->wait_list_head,
290 lock->wait_list_tail,
293 GNUNET_free (wl_client);
298 * Search for a client in the client list
300 * @param client the client to be searched for
301 * @param ret will be pointing to the matched list entry (if there is a match);
302 * else to the tail of the client list
303 * @return GNUNET_YES if the client is present; GNUNET_NO if not
306 cl_find_client (const struct GNUNET_SERVER_Client *client,
307 struct ClientList **ret)
309 struct ClientList *current;
313 while (NULL != current)
315 if (client == current->client)
321 current = current->next;
330 * Append a client to the client list
332 * @param client the client to be appended to the list
335 cl_add_client (struct GNUNET_SERVER_Client *client)
337 struct ClientList *new_client;
339 new_client = GNUNET_malloc (sizeof (struct ClientList));
340 new_client->client = client;
341 GNUNET_CONTAINER_DLL_insert_tail (cl_head,
348 * Delete the given client from the client list
350 * @param client the client list entry to delete
353 cl_remove_client (struct ClientList *client)
355 GNUNET_CONTAINER_DLL_remove (cl_head,
358 GNUNET_free (client);
363 * Transmit notify for sending message to client
365 * @param cls the message to send
366 * @param size number of bytes available in buf
367 * @param buf where the callee should write the message
368 * @return number of bytes written to buf
371 transmit_notify (void *cls, size_t size, void *buf)
373 struct GNUNET_LOCKMANAGER_Message *msg = cls;
376 if ((0 == size) || (NULL == buf))
378 /* FIXME: Timed out -- requeue? */
381 msg_size = ntohs (msg->header.size);
382 GNUNET_assert (size >= msg_size);
383 memcpy (buf, msg, msg_size);
385 LOG (GNUNET_ERROR_TYPE_DEBUG,
386 "Message of size %u sent\n", msg_size);
392 * Handler for GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE
395 * @param client the client sending this message
396 * @param message GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE message
399 handle_acquire (void *cls,
400 struct GNUNET_SERVER_Client *client,
401 const struct GNUNET_MessageHeader *message)
403 const struct GNUNET_LOCKMANAGER_Message *request;
404 struct GNUNET_LOCKMANAGER_Message *reply;
405 int16_t request_size;
408 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 "Received an ACQUIRE message\n");
411 request = (struct GNUNET_LOCKMANAGER_Message *) message;
413 /* FIXME: Dummy implementation; just echos success for every lock */
414 request_size = ntohs (message->size);
415 reply = GNUNET_malloc (request_size);
416 memcpy (reply, request, request_size);
417 reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS);
418 GNUNET_SERVER_notify_transmit_ready (client,
424 GNUNET_SERVER_receive_done (client, GNUNET_OK);
429 * Handle for GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE
432 * @param client the client sending this message
433 * @param message the LOCKMANAGER_RELEASE message
436 handle_release (void *cls,
437 struct GNUNET_SERVER_Client *client,
438 const struct GNUNET_MessageHeader *message)
440 LOG (GNUNET_ERROR_TYPE_DEBUG,
441 "Received a RELEASE message\n");
443 GNUNET_SERVER_receive_done (client, GNUNET_OK);
451 * @param server the initialized server
452 * @param cfg configuration to use
455 lockmanager_run (void *cls,
456 struct GNUNET_SERVER_Handle * server,
457 const struct GNUNET_CONFIGURATION_Handle *cfg)
459 static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
461 {&handle_acquire, NULL, GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE, 0},
462 {&handle_release, NULL, GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE, 0},
466 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lockmanager\n");
467 GNUNET_SERVER_add_handlers (server,
473 * The starting point of execution
475 int main (int argc, char *const *argv)
479 GNUNET_log_setup ("lockmanager",
487 LOG (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
490 GNUNET_SERVICE_run (argc,
493 GNUNET_SERVICE_OPTION_NONE,
496 LOG (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");