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>