Return to ipsec_event_relay.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libipsec |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2012 Tobias Brunner ! 3: * Copyright (C) 2012 Giuliano Grassi ! 4: * Copyright (C) 2012 Ralf Sager ! 5: * HSR Hochschule fuer Technik Rapperswil ! 6: * ! 7: * This program is free software; you can redistribute it and/or modify it ! 8: * under the terms of the GNU General Public License as published by the ! 9: * Free Software Foundation; either version 2 of the License, or (at your ! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, but ! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 15: * for more details. ! 16: */ ! 17: ! 18: #include "ipsec_event_relay.h" ! 19: ! 20: #include <library.h> ! 21: #include <utils/debug.h> ! 22: #include <threading/rwlock.h> ! 23: #include <collections/linked_list.h> ! 24: #include <collections/blocking_queue.h> ! 25: #include <processing/jobs/callback_job.h> ! 26: ! 27: typedef struct private_ipsec_event_relay_t private_ipsec_event_relay_t; ! 28: ! 29: /** ! 30: * Private additions to ipsec_event_relay_t. ! 31: */ ! 32: struct private_ipsec_event_relay_t { ! 33: ! 34: /** ! 35: * Public members ! 36: */ ! 37: ipsec_event_relay_t public; ! 38: ! 39: /** ! 40: * Registered listeners ! 41: */ ! 42: linked_list_t *listeners; ! 43: ! 44: /** ! 45: * Lock to safely access the list of listeners ! 46: */ ! 47: rwlock_t *lock; ! 48: ! 49: /** ! 50: * Blocking queue for events ! 51: */ ! 52: blocking_queue_t *queue; ! 53: }; ! 54: ! 55: /** ! 56: * Helper struct used to manage events in a queue ! 57: */ ! 58: typedef struct { ! 59: ! 60: /** ! 61: * Type of the event ! 62: */ ! 63: enum { ! 64: IPSEC_EVENT_EXPIRE, ! 65: } type; ! 66: ! 67: /** ! 68: * Protocol of the SA ! 69: */ ! 70: uint8_t protocol; ! 71: ! 72: /** ! 73: * SPI of the SA, if any ! 74: */ ! 75: uint32_t spi; ! 76: ! 77: /** ! 78: * SA destination address ! 79: */ ! 80: host_t *dst; ! 81: ! 82: /** ! 83: * Additional data for specific event types ! 84: */ ! 85: union { ! 86: ! 87: struct { ! 88: /** TRUE in case of a hard expire */ ! 89: bool hard; ! 90: } expire; ! 91: ! 92: } data; ! 93: ! 94: } ipsec_event_t; ! 95: ! 96: /** ! 97: * Destroy IPsec event data ! 98: */ ! 99: static void ipsec_event_destroy(ipsec_event_t *event) ! 100: { ! 101: event->dst->destroy(event->dst); ! 102: free(event); ! 103: } ! 104: ! 105: /** ! 106: * Dequeue events and relay them to listeners ! 107: */ ! 108: static job_requeue_t handle_events(private_ipsec_event_relay_t *this) ! 109: { ! 110: enumerator_t *enumerator; ! 111: ipsec_event_listener_t *current; ! 112: ipsec_event_t *event; ! 113: ! 114: event = this->queue->dequeue(this->queue); ! 115: ! 116: this->lock->read_lock(this->lock); ! 117: enumerator = this->listeners->create_enumerator(this->listeners); ! 118: while (enumerator->enumerate(enumerator, (void**)¤t)) ! 119: { ! 120: switch (event->type) ! 121: { ! 122: case IPSEC_EVENT_EXPIRE: ! 123: if (current->expire) ! 124: { ! 125: current->expire(event->protocol, event->spi, event->dst, ! 126: event->data.expire.hard); ! 127: } ! 128: break; ! 129: } ! 130: } ! 131: enumerator->destroy(enumerator); ! 132: this->lock->unlock(this->lock); ! 133: ipsec_event_destroy(event); ! 134: return JOB_REQUEUE_DIRECT; ! 135: } ! 136: ! 137: METHOD(ipsec_event_relay_t, expire, void, ! 138: private_ipsec_event_relay_t *this, uint8_t protocol, uint32_t spi, ! 139: host_t *dst, bool hard) ! 140: { ! 141: ipsec_event_t *event; ! 142: ! 143: INIT(event, ! 144: .type = IPSEC_EVENT_EXPIRE, ! 145: .protocol = protocol, ! 146: .spi = spi, ! 147: .dst = dst->clone(dst), ! 148: .data = { ! 149: .expire = { ! 150: .hard = hard, ! 151: }, ! 152: }, ! 153: ); ! 154: this->queue->enqueue(this->queue, event); ! 155: } ! 156: ! 157: METHOD(ipsec_event_relay_t, register_listener, void, ! 158: private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener) ! 159: { ! 160: this->lock->write_lock(this->lock); ! 161: this->listeners->insert_last(this->listeners, listener); ! 162: this->lock->unlock(this->lock); ! 163: } ! 164: ! 165: METHOD(ipsec_event_relay_t, unregister_listener, void, ! 166: private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener) ! 167: { ! 168: this->lock->write_lock(this->lock); ! 169: this->listeners->remove(this->listeners, listener, NULL); ! 170: this->lock->unlock(this->lock); ! 171: } ! 172: ! 173: METHOD(ipsec_event_relay_t, destroy, void, ! 174: private_ipsec_event_relay_t *this) ! 175: { ! 176: this->queue->destroy_function(this->queue, free); ! 177: this->listeners->destroy(this->listeners); ! 178: this->lock->destroy(this->lock); ! 179: free(this); ! 180: } ! 181: ! 182: /** ! 183: * Described in header. ! 184: */ ! 185: ipsec_event_relay_t *ipsec_event_relay_create() ! 186: { ! 187: private_ipsec_event_relay_t *this; ! 188: ! 189: INIT(this, ! 190: .public = { ! 191: .expire = _expire, ! 192: .register_listener = _register_listener, ! 193: .unregister_listener = _unregister_listener, ! 194: .destroy = _destroy, ! 195: }, ! 196: .listeners = linked_list_create(), ! 197: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ! 198: .queue = blocking_queue_create(), ! 199: ); ! 200: ! 201: lib->processor->queue_job(lib->processor, ! 202: (job_t*)callback_job_create((callback_job_cb_t)handle_events, this, ! 203: NULL, (callback_job_cancel_t)return_false)); ! 204: ! 205: return &this->public; ! 206: }