Annotation of embedaddon/strongswan/src/libcharon/network/sender.c, revision 1.1.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>