Annotation of embedaddon/strongswan/src/libcharon/network/sender.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012 Tobias Brunner
! 3: * Copyright (C) 2005-2006 Martin Willi
! 4: * Copyright (C) 2005 Jan Hutter
! 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 <unistd.h>
! 19: #include <stdlib.h>
! 20:
! 21: #include "sender.h"
! 22:
! 23: #include <daemon.h>
! 24: #include <network/socket.h>
! 25: #include <processing/jobs/callback_job.h>
! 26: #include <threading/thread.h>
! 27: #include <threading/condvar.h>
! 28: #include <threading/mutex.h>
! 29:
! 30:
! 31: typedef struct private_sender_t private_sender_t;
! 32:
! 33: /**
! 34: * Private data of a sender_t object.
! 35: */
! 36: struct private_sender_t {
! 37: /**
! 38: * Public part of a sender_t object.
! 39: */
! 40: sender_t public;
! 41:
! 42: /**
! 43: * The packets are stored in a linked list
! 44: */
! 45: linked_list_t *list;
! 46:
! 47: /**
! 48: * mutex to synchronize access to list
! 49: */
! 50: mutex_t *mutex;
! 51:
! 52: /**
! 53: * condvar to signal for packets added to list
! 54: */
! 55: condvar_t *got;
! 56:
! 57: /**
! 58: * condvar to signal for packets sent
! 59: */
! 60: condvar_t *sent;
! 61:
! 62: /**
! 63: * Delay for sending outgoing packets, to simulate larger RTT
! 64: */
! 65: int send_delay;
! 66:
! 67: /**
! 68: * Specific message type to delay, 0 for any
! 69: */
! 70: int send_delay_type;
! 71:
! 72: /**
! 73: * Delay request messages?
! 74: */
! 75: bool send_delay_request;
! 76:
! 77: /**
! 78: * Delay response messages?
! 79: */
! 80: bool send_delay_response;
! 81: };
! 82:
! 83: METHOD(sender_t, send_no_marker, void,
! 84: private_sender_t *this, packet_t *packet)
! 85: {
! 86: this->mutex->lock(this->mutex);
! 87: this->list->insert_last(this->list, packet);
! 88: this->got->signal(this->got);
! 89: this->mutex->unlock(this->mutex);
! 90: }
! 91:
! 92: METHOD(sender_t, send_, void,
! 93: private_sender_t *this, packet_t *packet)
! 94: {
! 95: host_t *src, *dst;
! 96:
! 97: src = packet->get_source(packet);
! 98: dst = packet->get_destination(packet);
! 99:
! 100: DBG1(DBG_NET, "sending packet: from %#H to %#H (%zu bytes)", src, dst,
! 101: packet->get_data(packet).len);
! 102:
! 103: if (this->send_delay)
! 104: {
! 105: message_t *message;
! 106:
! 107: message = message_create_from_packet(packet->clone(packet));
! 108: if (message->parse_header(message) == SUCCESS)
! 109: {
! 110: if (this->send_delay_type == 0 ||
! 111: this->send_delay_type == message->get_exchange_type(message))
! 112: {
! 113: if ((message->get_request(message) && this->send_delay_request) ||
! 114: (!message->get_request(message) && this->send_delay_response))
! 115: {
! 116: DBG1(DBG_NET, "using send delay: %dms", this->send_delay);
! 117: usleep(this->send_delay * 1000);
! 118: }
! 119: }
! 120: }
! 121: message->destroy(message);
! 122: }
! 123:
! 124: /* if neither source nor destination port is 500 we add a Non-ESP marker */
! 125: if (dst->get_port(dst) != IKEV2_UDP_PORT &&
! 126: src->get_port(src) != IKEV2_UDP_PORT)
! 127: {
! 128: chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
! 129:
! 130: data = chunk_cat("cc", marker, packet->get_data(packet));
! 131: packet->set_data(packet, data);
! 132: }
! 133:
! 134: send_no_marker(this, packet);
! 135: }
! 136:
! 137: /**
! 138: * Job callback function to send packets
! 139: */
! 140: static job_requeue_t send_packets(private_sender_t *this)
! 141: {
! 142: packet_t *packet;
! 143: bool oldstate;
! 144:
! 145: this->mutex->lock(this->mutex);
! 146: while (this->list->get_count(this->list) == 0)
! 147: {
! 148: /* add cleanup handler, wait for packet, remove cleanup handler */
! 149: thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
! 150: oldstate = thread_cancelability(TRUE);
! 151:
! 152: this->got->wait(this->got, this->mutex);
! 153:
! 154: thread_cancelability(oldstate);
! 155: thread_cleanup_pop(FALSE);
! 156: }
! 157: this->list->remove_first(this->list, (void**)&packet);
! 158: this->sent->signal(this->sent);
! 159: this->mutex->unlock(this->mutex);
! 160:
! 161: charon->socket->send(charon->socket, packet);
! 162: packet->destroy(packet);
! 163: return JOB_REQUEUE_DIRECT;
! 164: }
! 165:
! 166: METHOD(sender_t, flush, void,
! 167: private_sender_t *this)
! 168: {
! 169: /* send all packets in the queue */
! 170: this->mutex->lock(this->mutex);
! 171: while (this->list->get_count(this->list))
! 172: {
! 173: this->sent->wait(this->sent, this->mutex);
! 174: }
! 175: this->mutex->unlock(this->mutex);
! 176: }
! 177:
! 178: METHOD(sender_t, destroy, void,
! 179: private_sender_t *this)
! 180: {
! 181: this->list->destroy_offset(this->list, offsetof(packet_t, destroy));
! 182: this->got->destroy(this->got);
! 183: this->sent->destroy(this->sent);
! 184: this->mutex->destroy(this->mutex);
! 185: free(this);
! 186: }
! 187:
! 188: /*
! 189: * Described in header.
! 190: */
! 191: sender_t * sender_create()
! 192: {
! 193: private_sender_t *this;
! 194:
! 195: INIT(this,
! 196: .public = {
! 197: .send = _send_,
! 198: .send_no_marker = _send_no_marker,
! 199: .flush = _flush,
! 200: .destroy = _destroy,
! 201: },
! 202: .list = linked_list_create(),
! 203: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
! 204: .got = condvar_create(CONDVAR_TYPE_DEFAULT),
! 205: .sent = condvar_create(CONDVAR_TYPE_DEFAULT),
! 206: .send_delay = lib->settings->get_int(lib->settings,
! 207: "%s.send_delay", 0, lib->ns),
! 208: .send_delay_type = lib->settings->get_int(lib->settings,
! 209: "%s.send_delay_type", 0, lib->ns),
! 210: .send_delay_request = lib->settings->get_bool(lib->settings,
! 211: "%s.send_delay_request", TRUE, lib->ns),
! 212: .send_delay_response = lib->settings->get_bool(lib->settings,
! 213: "%s.send_delay_response", TRUE, lib->ns),
! 214: );
! 215:
! 216: lib->processor->queue_job(lib->processor,
! 217: (job_t*)callback_job_create_with_prio((callback_job_cb_t)send_packets,
! 218: this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
! 219:
! 220: return &this->public;
! 221: }
! 222:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>