<commit_before>//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include <catch.hpp>
#include <nngcpp.h>

#include "../tests/messaging/messaging_gymnastics.h"

#include <string>
#include <memory>
#include <thread>

void allocate(nng::messaging::binary_message* const bmp
    , nng::messaging::message_base::size_type sz = 0) {

    REQUIRE(bmp != nullptr);
    REQUIRE(bmp->has_message() == false);
    REQUIRE(bmp->get_msgp() == nullptr);

    REQUIRE_NOTHROW(bmp->allocate(sz));
    REQUIRE(bmp->has_message() == true);

    REQUIRE(bmp->get_msgp() != nullptr);
    const auto* msgp = bmp->get_msgp();

    REQUIRE(bmp->header() != nullptr);
    REQUIRE(bmp->header()->has_message());
    REQUIRE(bmp->header()->get_msgp() == msgp);

    REQUIRE(bmp->body() != nullptr);
    REQUIRE(bmp->body()->has_message());
    REQUIRE(bmp->body()->get_msgp() == msgp);
}

namespace constants {

    const std::string nng_addr = "inproc://nng";

    const std::string test_addr = "inproc://test";

    const std::string hello = "hello";
    const std::string again = "again";

    const nng::messaging::message_base::buffer_vector_type hello_buf = { 'h','e','l','l','o' };
    const nng::messaging::message_base::buffer_vector_type again_buf = { 'a','g','a','i','n' };
}

template<typename A_, typename B_>
void check(A_ lhs, B_ rhs) {
    CHECK(lhs == rhs);
}

template<typename A_, typename B_>
void require(A_ lhs, B_ rhs) {
    REQUIRE(lhs == rhs);
}

template<typename A_, typename B_>
void require_not_equal(A_ lhs, B_ rhs) {
    REQUIRE(lhs != rhs);
}

void nng_tests_append_str(::nng_msg* msgp, const char* s) {
    require(::nng_msg_append(msgp, s, std::strlen(s)), 0);
    require(::nng_msg_len(msgp), std::strlen(s));
    require(std::memcmp(::nng_msg_body(msgp), s, std::strlen(s)), 0);
}

void nng_tests_check_str(::nng_msg* msgp, const char* s) {
    require_not_equal(msgp, nullptr);
    require(::nng_msg_len(msgp), std::strlen(s));
    require(std::memcmp(::nng_msg_body(msgp), s, std::strlen(s)), 0);
}

//// todo:
//TEST_CASE("Do some math tests", "[math][foo][bar]") {
//
//    SECTION("This is a test") {
//
//        REQUIRE(2 + 2 != 4);
//    }
//
//    SECTION("This is a test 2") {
//
//        REQUIRE(3 + 3 != 6);
//    }
//}

struct c_style_fixture {

    ::nng_socket push;
    ::nng_socket pull;

    c_style_fixture() : push(0), pull(0) {
        REQUIRE(::nng_push_open(&push) == 0);
        REQUIRE(::nng_pull_open(&pull) == 0);
    }

    virtual ~c_style_fixture() {
        ::nng_close(push);
        ::nng_close(pull);
    }
};

TEST_CASE("C style NNG reconnect works", "[reconnect][nng]") {

    using namespace std;
    using namespace std::chrono;
    using namespace constants;

    c_style_fixture $;

    REQUIRE(::nng_setopt_usec($.pull, NNG_OPT_RECONNMINT, 10000) == 0);
    REQUIRE(::nng_setopt_usec($.pull, NNG_OPT_RECONNMAXT, 10000) == 0);

    // Strictly adapted from the NNG C-style unit tests, but for std::thread specifics.
    SECTION("Dialing before listening works") {

        INFO("Dialing push on address: '" + nng_addr + "'");

        REQUIRE(::nng_dial($.push, nng_addr.c_str(), NULL, NNG_FLAG_NONBLOCK) == 0);

        this_thread::sleep_for(100ms);

        INFO("Pull listening on address: '" + nng_addr + "'");

        REQUIRE(::nng_listen($.pull, nng_addr.c_str(), NULL, 0) == 0);

        // TODO: TBD: for comparison, so far the original C-style approach is working
        SECTION("We can send a frame") {

            ::nng_msg *msgp;

            this_thread::sleep_for(100ms);

            REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
            REQUIRE(msgp != nullptr);

            ::nng_tests_append_str(msgp, hello.c_str());
            REQUIRE(::nng_sendmsg($.push, msgp, 0) == 0);

            ::nng_msg_free(msgp);
            msgp = nullptr;

            REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
            REQUIRE(msgp != nullptr);

            REQUIRE(::nng_recvmsg($.pull, &msgp, 0) == 0);
            ::nng_tests_check_str(msgp, hello.c_str());

            ::nng_msg_free(msgp);
        }
        // TODO: TBD: continue appending sections of the original test.
    }
}

//TEST_CASE("Wrapper style reconnect works", "[reconnect][cxx]") {
//
//    using namespace std;
//    using namespace std::chrono;
//    using namespace nng;
//    using namespace nng::protocol;
//    using namespace nng::messaging;
//    using namespace constants;
//    using namespace Catch::Matchers;
//    using _opt_ = option_names;
//
//    // Which "at-exit" destructor handles cleaning up the NNG resources: i.e. ::nng_fini.
//    session _session_;
//
//    SECTION("We can create a pipeline") {
//
//        std::shared_ptr<latest_push_socket> push;
//        std::shared_ptr<latest_pull_socket> pull;
//
//        REQUIRE_NOTHROW(push = _session_.create_push_socket());
//        REQUIRE_NOTHROW(pull = _session_.create_pull_socket());
//
//        const duration<uint64_t, milli> reconnect_time = 10ms;
//
//        // TODO: TBD: count() might be the way to go here, but I cannot say for sure.
//        // http://en.cppreference.com/w/cpp/chrono/duration
//        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::min_reconnect_time_usec, reconnect_time.count()));
//        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::max_reconnect_time_usec, reconnect_time.count()));
//
//        SECTION("Dialing before listening works") {
//
//            REQUIRE_NOTHROW(push->dial(test_addr, to_int(flag_nonblock)));
//            this_thread::sleep_for(100ms);
//
//            REQUIRE_NOTHROW(pull->listen(test_addr));
//
//            /* 'Frame' in this case is loosely speaking. We do not care about exposing the NNG msg structure,
//            per se. Rather, we should simply be able to "frame" buffers or strings, accordingly. */
//            SECTION("We can send a frame") {
//
//                this_thread::sleep_for(100ms);
//
//                binary_message bm;
//
//                allocate(&bm);
//
//                // And with a little C++ operator overloading help:
//                REQUIRE_NOTHROW(bm << hello);
//
//                REQUIRE_THAT(bm.body()->get(), Equals(hello_buf));
//
//                push->send(&bm);
//
//                FAIL();
//                REQUIRE_NOTHROW(push->send(&bm));
//                REQUIRE_NOTHROW(pull->try_receive(&bm));
//
//                std::string _pulled_actual;
//
//                // Ditto C++ operator overloading.
//                _pulled_actual << bm;
//
//                REQUIRE_THAT(_pulled_actual, Equals(hello));
//            }
//        }
//
//        SECTION("Reconnection works") {
//
//            FAIL();
//
//            REQUIRE_NOTHROW(push->dial(test_addr, to_int(flag_nonblock)));
//
//            {
//                shared_ptr<listener> lp;
//
//                REQUIRE_NOTHROW(lp = _session_.create_listener_ep());
//                REQUIRE(lp != nullptr);
//
//                REQUIRE_NOTHROW(pull->listen(test_addr, lp.get()));
//                this_thread::sleep_for(100ms);
//
//                REQUIRE_NOTHROW(_session_.remove_listener_ep(lp.get()));
//                REQUIRE_NOTHROW(lp.reset());
//            }
//
//            REQUIRE_NOTHROW(pull->listen(test_addr));
//
//            // TODO: TBD: This was heavily nng_pipe based from reconnect.c
//            // TODO: TBD: we may provide comprehension of nng_pipe from a nngcpp POV, but I'm not sure the complexity of nng_msg how that is different from a simple send/receive?
//            SECTION("They still exchange frames") {
//
//                FAIL();
//
//                std::unique_ptr<binary_message> bmp;
//
//                this_thread::sleep_for(100ms);
//
//                REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
//                REQUIRE(bmp != nullptr);
//
//                allocate(bmp.get());
//
//                *bmp << hello;
//
//                REQUIRE_NOTHROW(push->send(bmp.get()));
//
//                /* The C-based tests simple "reset" the pointer to NULL. Clearly a memory leak in the making.
//                Instead, we will make the effort to be friendly to our memory consumption. */
//                REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
//                REQUIRE(bmp != nullptr);
//
//                REQUIRE_NOTHROW(pull->try_receive(bmp.get()));
//
//                REQUIRE(bmp->has_message() == true);
//                REQUIRE(bmp->header()->has_message() == true);
//                REQUIRE(bmp->body()->has_message() == true);
//
//                // Type conversion magic from the Message to a std::string.
//                std::string _gotten_actual = *bmp;
//
//                REQUIRE_THAT(_gotten_actual, Equals(hello));
//
//                std::unique_ptr<message_pipe> mpp1;
//
//                REQUIRE_NOTHROW(mpp1 = std::make_unique<message_pipe>(bmp.get()));
//                REQUIRE(mpp1 != nullptr);
//
//                // Now both we and the original C-based unit test agree, reset the memory.
//                REQUIRE_NOTHROW(bmp.reset());
//                REQUIRE(bmp == nullptr);
//
//                SECTION("Even after pipe close") {
//
//                    FAIL();
//
//                    std::unique_ptr<message_pipe> mpp2;
//
//                    REQUIRE_NOTHROW(mpp1->close());
//
//                    this_thread::sleep_for(100ms);
//
//                    allocate(bmp.get());
//
//                    *bmp << again;
//
//                    REQUIRE_NOTHROW(push->send(bmp.get()));
//
//                    // Ditto C-based NULL-ifying the pointers without freeing them.
//                    REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
//                    REQUIRE(bmp != nullptr);
//
//                    REQUIRE_NOTHROW(pull->try_receive(bmp.get()));
//
//                    REQUIRE(bmp->has_message() == true);
//                    REQUIRE(bmp->header()->has_message() == true);
//                    REQUIRE(bmp->body()->has_message() == true);
//
//                    // Type conversion magic from the Message to a std::string.
//                    _gotten_actual = *bmp;
//
//                    REQUIRE_THAT(_gotten_actual, Equals(again));
//
//                    auto mp2 = message_pipe(bmp.get());
//
//                    // TODO: TBD: so, we can define the != operator alone, but there is no std::not_equal_to implemented. is there a patch? or migration path from 2015 -> 2017?
//                    REQUIRE((*mpp1.get()) != mp2);
//                }
//            }
//        }
//    }
//}
<commit_msg>troubleshooting reconnect behavior<commit_after>//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include <catch.hpp>
#include <nngcpp.h>

#include "../tests/messaging/messaging_gymnastics.h"

#include <string>
#include <memory>
#include <thread>

void allocate(nng::messaging::binary_message* const bmp
    , nng::messaging::message_base::size_type sz = 0) {

    REQUIRE(bmp != nullptr);
    REQUIRE(bmp->has_message() == false);
    REQUIRE(bmp->get_msgp() == nullptr);

    REQUIRE_NOTHROW(bmp->allocate(sz));
    REQUIRE(bmp->has_message() == true);

    REQUIRE(bmp->get_msgp() != nullptr);
    const auto* msgp = bmp->get_msgp();

    REQUIRE(bmp->header() != nullptr);
    REQUIRE(bmp->header()->has_message());
    REQUIRE(bmp->header()->get_msgp() == msgp);

    REQUIRE(bmp->body() != nullptr);
    REQUIRE(bmp->body()->has_message());
    REQUIRE(bmp->body()->get_msgp() == msgp);
}

namespace constants {

    const std::string nng_addr = "inproc://nng";

    const std::string test_addr = "inproc://test";

    const std::string hello = "hello";
    const std::string again = "again";

    const nng::messaging::message_base::buffer_vector_type hello_buf = { 'h','e','l','l','o' };
    const nng::messaging::message_base::buffer_vector_type again_buf = { 'a','g','a','i','n' };
}

#define NNG_TESTS_INIT() int errnum

#define NNG_TESTS_APPEND_STR(m, s) \
    REQUIRE(::nng_msg_append(m, s, std::strlen(s)) == 0); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

#define NNG_TESTS_CHECK_STR(m, s) \
    REQUIRE(m != nullptr); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

//// todo:
//TEST_CASE("Do some math tests", "[math][foo][bar]") {
//
//    SECTION("This is a test") {
//
//        REQUIRE(2 + 2 != 4);
//    }
//
//    SECTION("This is a test 2") {
//
//        REQUIRE(3 + 3 != 6);
//    }
//}

struct c_style_fixture {

    ::nng_socket push;
    ::nng_socket pull;

    c_style_fixture() : push(0), pull(0) {
        REQUIRE(::nng_push_open(&push) == 0);
        REQUIRE(::nng_pull_open(&pull) == 0);
    }

    virtual ~c_style_fixture() {
        ::nng_close(push);
        ::nng_close(pull);
        ::nng_fini();
    }
};

TEST_CASE("C style NNG reconnect works", "[reconnect][nng]") {

    using namespace std;
    using namespace std::chrono;
    using namespace constants;

    SECTION("We can create a pipeline") {

        NNG_TESTS_INIT();

        c_style_fixture $;

        REQUIRE(::nng_setopt_usec($.pull, NNG_OPT_RECONNMINT, 10000) == 0);
        REQUIRE(::nng_setopt_usec($.pull, NNG_OPT_RECONNMAXT, 10000) == 0);

        // Strictly adapted from the NNG C-style unit tests, but for std::thread specifics.
        SECTION("Dialing before listening works") {

            INFO("Dialing push on address: '" + nng_addr + "'");

            // With Reconnect Times configured, Should re-dial until Listener comes online.
            REQUIRE(::nng_dial($.push, nng_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);

            this_thread::sleep_for(100ms);

            INFO("Pull listening on address: '" + nng_addr + "'");

            REQUIRE(::nng_listen($.pull, nng_addr.c_str(), nullptr, 0) == 0);

            // TODO: TBD: for comparison, so far the original C-style approach is working
            SECTION("We can send a frame") {

                struct ::nng_msg *msgp = nullptr;

                this_thread::sleep_for(100ms);

                REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                REQUIRE(msgp != nullptr);

                NNG_TESTS_APPEND_STR(msgp, hello.c_str());

                //::nng_tests_append_str(msgp, hello.c_str());
                REQUIRE(::nng_sendmsg($.push, msgp, 0) == 0);

                ::nng_msg_free(msgp);
                msgp = nullptr;

                ::nng_msg_alloc(&msgp, 0);
                REQUIRE(msgp != nullptr);

                // Which Receiving a Message should allocate when we did not provide one.
                errnum = ::nng_recvmsg($.pull, &msgp, 0);
                REQUIRE(errnum == 0);
                REQUIRE(msgp != nullptr);

                NNG_TESTS_CHECK_STR(msgp, hello.c_str());

                ::nng_msg_free(msgp);
            }

            // TODO: TBD: continue appending sections of the original test.
        }

        //SECTION("Reconnection works") {

        //    ::nng_listener l;

        //    REQUIRE(::nng_dial($.push, nng_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);
        //    REQUIRE(::nng_listen($.pull, nng_addr.c_str(), &l, 0) == 0);

        //    this_thread::sleep_for(100ms);

        //    REQUIRE(::nng_listener_close(l) == 0);
        //    REQUIRE(::nng_listen($.pull, nng_addr.c_str(), nullptr, 0) == 0);

        //    SECTION("They still exchange frames") {

        //        ::nng_msg* msgp;
        //        ::nng_pipe p1;

        //        this_thread::sleep_for(100ms);

        //        REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);

        //        NNG_TESTS_APPEND_STR(msgp, hello.c_str());
        //        REQUIRE(::nng_sendmsg($.push, msgp, 0) == 0);

        //        ::nng_msg_free(msgp);
        //        msgp = nullptr;

        //        REQUIRE(::nng_recvmsg($.pull, &msgp, 0) == 0);
        //        REQUIRE(msgp != nullptr);

        //        NNG_TESTS_CHECK_STR(msgp, hello.c_str());

        //        p1 = ::nng_msg_get_pipe(msgp);

        //        ::nng_msg_free(msgp);

        //        SECTION("Even after pipe close") {

        //            ::nng_pipe p2;

        //            ::nng_pipe_close(p1);

        //            this_thread::sleep_for(100ms);

        //            REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
        //            NNG_TESTS_APPEND_STR(msgp, again.c_str());
        //        }
        //    }
        //}

        //Convey("Reconnection works", {

        //Convey("They still exchange frames",{

        //Convey("Even after pipe close",{

        //APPENDSTR(msg, "again");
        //So(nng_sendmsg(push, msg, 0) == 0);
        //msg = NULL;
        //So(nng_recvmsg(pull, &msg, 0) == 0);
        //So(msg != NULL);
        //CHECKSTR(msg, "again");
        //p2 = nng_msg_get_pipe(msg);
        //nng_msg_free(msg);
        //So(p2 != p1);
        //});
        //});
        //});
    }
}

TEST_CASE("Wrapper style reconnect works", "[reconnect][cxx]") {

    using namespace std;
    using namespace std::chrono;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using _opt_ = option_names;

    // Which "at-exit" destructor handles cleaning up the NNG resources: i.e. ::nng_fini.
    session _session_;

    SECTION("We can create a pipeline") {

        std::shared_ptr<latest_push_socket> push;
        std::shared_ptr<latest_pull_socket> pull;

        REQUIRE_NOTHROW(push = _session_.create_push_socket());
        REQUIRE_NOTHROW(pull = _session_.create_pull_socket());

        const duration<uint64_t, milli> reconnect_time = 10ms;

        // TODO: TBD: count() might be the way to go here, but I cannot say for sure.
        // http://en.cppreference.com/w/cpp/chrono/duration
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::min_reconnect_time_usec, reconnect_time.count()));
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::max_reconnect_time_usec, reconnect_time.count()));

        SECTION("Dialing before listening works") {

            REQUIRE_NOTHROW(push->dial(test_addr, to_int(flag_nonblock)));
            this_thread::sleep_for(100ms);

            REQUIRE_NOTHROW(pull->listen(test_addr));

            /* 'Frame' in this case is loosely speaking. We do not care about exposing the NNG msg structure,
            per se. Rather, we should simply be able to "frame" buffers or strings, accordingly. */
            SECTION("We can send a frame") {

                this_thread::sleep_for(100ms);

                binary_message bm;

                allocate(&bm);

                // And with a little C++ operator overloading help:
                REQUIRE_NOTHROW(bm << hello);

                REQUIRE_THAT(bm.body()->get(), Equals(hello_buf));

                push->send(&bm);

                FAIL();
                REQUIRE_NOTHROW(push->send(&bm));
                REQUIRE_NOTHROW(pull->try_receive(&bm));

                std::string _pulled_actual;

                // Ditto C++ operator overloading.
                _pulled_actual << bm;

                REQUIRE_THAT(_pulled_actual, Equals(hello));
            }
        }

        SECTION("Reconnection works") {

            FAIL();

            REQUIRE_NOTHROW(push->dial(test_addr, to_int(flag_nonblock)));

            {
                shared_ptr<listener> lp;

                REQUIRE_NOTHROW(lp = _session_.create_listener_ep());
                REQUIRE(lp != nullptr);

                REQUIRE_NOTHROW(pull->listen(test_addr, lp.get()));
                this_thread::sleep_for(100ms);

                REQUIRE_NOTHROW(_session_.remove_listener_ep(lp.get()));
                REQUIRE_NOTHROW(lp.reset());
            }

            REQUIRE_NOTHROW(pull->listen(test_addr));

            // TODO: TBD: This was heavily nng_pipe based from reconnect.c
            // TODO: TBD: we may provide comprehension of nng_pipe from a nngcpp POV, but I'm not sure the complexity of nng_msg how that is different from a simple send/receive?
            SECTION("They still exchange frames") {

                FAIL();

                std::unique_ptr<binary_message> bmp;

                this_thread::sleep_for(100ms);

                REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
                REQUIRE(bmp != nullptr);

                allocate(bmp.get());

                *bmp << hello;

                REQUIRE_NOTHROW(push->send(bmp.get()));

                /* The C-based tests simple "reset" the pointer to NULL. Clearly a memory leak in the making.
                Instead, we will make the effort to be friendly to our memory consumption. */
                REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
                REQUIRE(bmp != nullptr);

                REQUIRE_NOTHROW(pull->try_receive(bmp.get()));

                REQUIRE(bmp->has_message() == true);
                REQUIRE(bmp->header()->has_message() == true);
                REQUIRE(bmp->body()->has_message() == true);

                // Type conversion magic from the Message to a std::string.
                std::string _gotten_actual = *bmp;

                REQUIRE_THAT(_gotten_actual, Equals(hello));

                std::unique_ptr<message_pipe> mpp1;

                REQUIRE_NOTHROW(mpp1 = std::make_unique<message_pipe>(bmp.get()));
                REQUIRE(mpp1 != nullptr);

                // Now both we and the original C-based unit test agree, reset the memory.
                REQUIRE_NOTHROW(bmp.reset());
                REQUIRE(bmp == nullptr);

                SECTION("Even after pipe close") {

                    FAIL();

                    std::unique_ptr<message_pipe> mpp2;

                    REQUIRE_NOTHROW(mpp1->close());

                    this_thread::sleep_for(100ms);

                    allocate(bmp.get());

                    *bmp << again;

                    REQUIRE_NOTHROW(push->send(bmp.get()));

                    // Ditto C-based NULL-ifying the pointers without freeing them.
                    REQUIRE_NOTHROW(bmp = std::make_unique<binary_message>());
                    REQUIRE(bmp != nullptr);

                    REQUIRE_NOTHROW(pull->try_receive(bmp.get()));

                    REQUIRE(bmp->has_message() == true);
                    REQUIRE(bmp->header()->has_message() == true);
                    REQUIRE(bmp->body()->has_message() == true);

                    // Type conversion magic from the Message to a std::string.
                    _gotten_actual = *bmp;

                    REQUIRE_THAT(_gotten_actual, Equals(again));

                    auto mp2 = message_pipe(bmp.get());

                    // TODO: TBD: so, we can define the != operator alone, but there is no std::not_equal_to implemented. is there a patch? or migration path from 2015 -> 2017?
                    REQUIRE((*mpp1.get()) != mp2);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: vclxdevice.cxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:02:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_AWT_DEVICECAPABILITY_HPP_
#include <com/sun/star/awt/DeviceCapability.hpp>
#endif

#include <toolkit/awt/vclxdevice.hxx>
#include <toolkit/awt/vclxfont.hxx>
#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <rtl/memory.h>
#include <rtl/uuid.h>

#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#include <vcl/window.hxx>
#include <vcl/print.hxx>
#include <vcl/virdev.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/font.hxx>

//  ----------------------------------------------------
//  class VCLXDevice
//  ----------------------------------------------------
VCLXDevice::VCLXDevice() : mrMutex( Application::GetSolarMutex() )
{
    mpOutputDevice = NULL;
#ifdef DEBUG
    nDummy = 0x12345678;
    pDummy = (void*)0x12345678;
#endif
}

VCLXDevice::~VCLXDevice()
{
#ifdef DEBUG
    nDummy = 0xbaadbaad;
    pDummy = (void*)0xbaadbaad;
#endif
}

void VCLXDevice::DestroyOutputDevice()
{
    delete mpOutputDevice;
    mpOutputDevice = NULL;
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXDevice::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDevice*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXDevice )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXDevice )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XDevice,
::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > VCLXDevice::createGraphics(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > xRef;

    if ( mpOutputDevice )
        xRef = mpOutputDevice->CreateUnoGraphics();

    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > VCLXDevice::createDevice( sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >  xRef;
    if ( GetOutputDevice() )
    {
        VCLXVirtualDevice* pVDev = new VCLXVirtualDevice;
        VirtualDevice* pVclVDev = new VirtualDevice( *GetOutputDevice() );
        pVclVDev->SetOutputSizePixel( Size( nWidth, nHeight ) );
        pVDev->SetVirtualDevice( pVclVDev );
        xRef = pVDev;
    }
    return xRef;
}

::com::sun::star::awt::DeviceInfo VCLXDevice::getInfo() throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::awt::DeviceInfo aInfo;

    if( mpOutputDevice )
    {
        Size aDevSz;
        OutDevType eDevType = mpOutputDevice->GetOutDevType();
        if ( eDevType == OUTDEV_WINDOW )
        {
            aDevSz = ((Window*)mpOutputDevice)->GetSizePixel();
            ((Window*)mpOutputDevice)->GetBorder( aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset );
        }
        else if ( eDevType == OUTDEV_PRINTER )
        {
            aDevSz = ((Printer*)mpOutputDevice)->GetPaperSizePixel();
            Size aOutSz = mpOutputDevice->GetOutputSizePixel();
            Point aOffset = ((Printer*)mpOutputDevice)->GetPageOffset();
            aInfo.LeftInset = aOffset.X();
            aInfo.TopInset = aOffset.Y();
            aInfo.RightInset = aDevSz.Width() - aOutSz.Width() - aOffset.X();
            aInfo.BottomInset = aDevSz.Height() - aOutSz.Height() - aOffset.Y();
        }
        else // VirtualDevice
        {
            aDevSz = mpOutputDevice->GetOutputSizePixel();
            aInfo.LeftInset = 0;
            aInfo.TopInset = 0;
            aInfo.RightInset = 0;
            aInfo.BottomInset = 0;
        }

        aInfo.Width = aDevSz.Width();
        aInfo.Height = aDevSz.Height();

        Size aTmpSz = mpOutputDevice->LogicToPixel( Size( 1000, 1000 ), MapMode( MAP_CM ) );
        aInfo.PixelPerMeterX = aTmpSz.Width()/10;
        aInfo.PixelPerMeterY = aTmpSz.Height()/10;

        aInfo.BitsPerPixel = mpOutputDevice->GetBitCount();

        aInfo.Capabilities = 0;
        if ( mpOutputDevice->GetOutDevType() != OUTDEV_PRINTER )
            aInfo.Capabilities = ::com::sun::star::awt::DeviceCapability::RASTEROPERATIONS|::com::sun::star::awt::DeviceCapability::GETBITS;
    }

    return aInfo;
}

::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor > VCLXDevice::getFontDescriptors(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor> aFonts;
    if( mpOutputDevice )
    {
        sal_uInt16 nFonts = mpOutputDevice->GetDevFontCount();
        if ( nFonts )
        {
            aFonts = ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor>( nFonts );
            ::com::sun::star::awt::FontDescriptor* pFonts = aFonts.getArray();
            for ( sal_uInt16 n = 0; n < nFonts; n++ )
                pFonts[n] = VCLUnoHelper::CreateFontDescriptor( mpOutputDevice->GetDevFont( n ) );
        }
    }
    return aFonts;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > VCLXDevice::getFont( const ::com::sun::star::awt::FontDescriptor& rDescriptor ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont >  xRef;
    if( mpOutputDevice )
    {
        VCLXFont* pMetric = new VCLXFont;
        pMetric->Init( *this, VCLUnoHelper::CreateFont( rDescriptor, mpOutputDevice->GetFont() ) );
        xRef = pMetric;
    }
    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > VCLXDevice::createBitmap( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >  xBmp;
    if( mpOutputDevice )
    {
        Bitmap aBmp = mpOutputDevice->GetBitmap( Point( nX, nY ), Size( nWidth, nHeight ) );

        VCLXBitmap* pBmp = new VCLXBitmap;
        pBmp->SetBitmap( BitmapEx( aBmp ) );
        xBmp = pBmp;
    }
    return xBmp;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap > VCLXDevice::createDisplayBitmap( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >& rxBitmap ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    BitmapEx aBmp = VCLUnoHelper::GetBitmap( rxBitmap );
    VCLXBitmap* pBmp = new VCLXBitmap;
    pBmp->SetBitmap( aBmp );
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap >  xDBmp = pBmp;
    return xDBmp;
}

<commit_msg>#86489# Lock solar mutex before calling DestroyOutputDevice...<commit_after>/*************************************************************************
 *
 *  $RCSfile: vclxdevice.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mt $ $Date: 2001-05-15 12:34:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_AWT_DEVICECAPABILITY_HPP_
#include <com/sun/star/awt/DeviceCapability.hpp>
#endif

#include <toolkit/awt/vclxdevice.hxx>
#include <toolkit/awt/vclxfont.hxx>
#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <rtl/memory.h>
#include <rtl/uuid.h>

#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#include <vcl/window.hxx>
#include <vcl/print.hxx>
#include <vcl/virdev.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/font.hxx>

//  ----------------------------------------------------
//  class VCLXDevice
//  ----------------------------------------------------
VCLXDevice::VCLXDevice() : mrMutex( Application::GetSolarMutex() )
{
    mpOutputDevice = NULL;
#ifdef DEBUG
    nDummy = 0x12345678;
    pDummy = (void*)0x12345678;
#endif
}

VCLXDevice::~VCLXDevice()
{
#ifdef DEBUG
    nDummy = 0xbaadbaad;
    pDummy = (void*)0xbaadbaad;
#endif
}

void VCLXDevice::DestroyOutputDevice()
{
    delete mpOutputDevice;
    mpOutputDevice = NULL;
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXDevice::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDevice*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXDevice )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXDevice )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XDevice,
::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > VCLXDevice::createGraphics(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > xRef;

    if ( mpOutputDevice )
        xRef = mpOutputDevice->CreateUnoGraphics();

    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > VCLXDevice::createDevice( sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >  xRef;
    if ( GetOutputDevice() )
    {
        VCLXVirtualDevice* pVDev = new VCLXVirtualDevice;
        VirtualDevice* pVclVDev = new VirtualDevice( *GetOutputDevice() );
        pVclVDev->SetOutputSizePixel( Size( nWidth, nHeight ) );
        pVDev->SetVirtualDevice( pVclVDev );
        xRef = pVDev;
    }
    return xRef;
}

::com::sun::star::awt::DeviceInfo VCLXDevice::getInfo() throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::awt::DeviceInfo aInfo;

    if( mpOutputDevice )
    {
        Size aDevSz;
        OutDevType eDevType = mpOutputDevice->GetOutDevType();
        if ( eDevType == OUTDEV_WINDOW )
        {
            aDevSz = ((Window*)mpOutputDevice)->GetSizePixel();
            ((Window*)mpOutputDevice)->GetBorder( aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset );
        }
        else if ( eDevType == OUTDEV_PRINTER )
        {
            aDevSz = ((Printer*)mpOutputDevice)->GetPaperSizePixel();
            Size aOutSz = mpOutputDevice->GetOutputSizePixel();
            Point aOffset = ((Printer*)mpOutputDevice)->GetPageOffset();
            aInfo.LeftInset = aOffset.X();
            aInfo.TopInset = aOffset.Y();
            aInfo.RightInset = aDevSz.Width() - aOutSz.Width() - aOffset.X();
            aInfo.BottomInset = aDevSz.Height() - aOutSz.Height() - aOffset.Y();
        }
        else // VirtualDevice
        {
            aDevSz = mpOutputDevice->GetOutputSizePixel();
            aInfo.LeftInset = 0;
            aInfo.TopInset = 0;
            aInfo.RightInset = 0;
            aInfo.BottomInset = 0;
        }

        aInfo.Width = aDevSz.Width();
        aInfo.Height = aDevSz.Height();

        Size aTmpSz = mpOutputDevice->LogicToPixel( Size( 1000, 1000 ), MapMode( MAP_CM ) );
        aInfo.PixelPerMeterX = aTmpSz.Width()/10;
        aInfo.PixelPerMeterY = aTmpSz.Height()/10;

        aInfo.BitsPerPixel = mpOutputDevice->GetBitCount();

        aInfo.Capabilities = 0;
        if ( mpOutputDevice->GetOutDevType() != OUTDEV_PRINTER )
            aInfo.Capabilities = ::com::sun::star::awt::DeviceCapability::RASTEROPERATIONS|::com::sun::star::awt::DeviceCapability::GETBITS;
    }

    return aInfo;
}

::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor > VCLXDevice::getFontDescriptors(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor> aFonts;
    if( mpOutputDevice )
    {
        sal_uInt16 nFonts = mpOutputDevice->GetDevFontCount();
        if ( nFonts )
        {
            aFonts = ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor>( nFonts );
            ::com::sun::star::awt::FontDescriptor* pFonts = aFonts.getArray();
            for ( sal_uInt16 n = 0; n < nFonts; n++ )
                pFonts[n] = VCLUnoHelper::CreateFontDescriptor( mpOutputDevice->GetDevFont( n ) );
        }
    }
    return aFonts;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > VCLXDevice::getFont( const ::com::sun::star::awt::FontDescriptor& rDescriptor ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont >  xRef;
    if( mpOutputDevice )
    {
        VCLXFont* pMetric = new VCLXFont;
        pMetric->Init( *this, VCLUnoHelper::CreateFont( rDescriptor, mpOutputDevice->GetFont() ) );
        xRef = pMetric;
    }
    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > VCLXDevice::createBitmap( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >  xBmp;
    if( mpOutputDevice )
    {
        Bitmap aBmp = mpOutputDevice->GetBitmap( Point( nX, nY ), Size( nWidth, nHeight ) );

        VCLXBitmap* pBmp = new VCLXBitmap;
        pBmp->SetBitmap( BitmapEx( aBmp ) );
        xBmp = pBmp;
    }
    return xBmp;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap > VCLXDevice::createDisplayBitmap( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >& rxBitmap ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    BitmapEx aBmp = VCLUnoHelper::GetBitmap( rxBitmap );
    VCLXBitmap* pBmp = new VCLXBitmap;
    pBmp->SetBitmap( aBmp );
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap >  xDBmp = pBmp;
    return xDBmp;
}

VCLXVirtualDevice::~VCLXVirtualDevice()
{
    ::vos::OGuard aGuard( GetMutex() );

    DestroyOutputDevice();
}

<|endoftext|>


<commit_before>#include "toplayer.h"
#include "domain.h"
#include <iostream>

using namespace std;

toplayer::toplayer()
{

}
void toplayer::run()
{
    help();
    cout << "\n Enter -help to display the command list again " << endl;
    while(selection())
    {

    }
}
void toplayer::help()
{
    cout << "*********************************************************" << endl;
    cout << "**        Notable Computer Scientists In History       **" << endl;
    cout << "**                                                     **" << endl;
    cout << "**     Enter -new to add a new person                  **" << endl;
    cout << "**     Enter -list for a full list                     **" << endl;
    cout << "**     Enter -search to search the list                **" << endl;
    cout << "**     Enter -remove to remove element from the list   **" << endl;
    cout << "**     Enter -sort to sort the list                    **" << endl;
    cout << "**     Enter -exit to exit the program                 **" << endl;
    cout << "**                                                     **" << endl;
    cout << "*********************************************************" << endl;
}

void toplayer::print(vector<Person>& pers) {

    for(unsigned int i = 0; i < pers.size(); i++) {
        cout << pers[i].getFirstname() << "\t"
             << pers[i].getLastname()  << "\t"
             << pers[i].getSex() << "\t"
             << pers[i].getBirth() << "\t"
             << pers[i].getDeath() << endl;
    }
    cout << "============================" << endl;

}

bool toplayer::selection()
{
    string input;
    cin >> input;
    if (input == "-list")
    {
        vector<Person> p;
        domain d;
        p = d.list();
        cout << "===== List =====" << endl;
        print(p);
    }
    else if (input == "-search")
    {
        vector<Person> p;
        domain d;
        string whattype, input;
        cout << "What do you want to search for?" << endl;
        cout << "-firstname" << endl << "-lastname" << endl << "-sex"
             << endl << "-birthyear" << endl << "-deathyear" << endl;
        cout << "Enter your choice: ";
        cin >> whattype;
        cout << "What is word do you want to serch for? ";
        cin >> input;
        p = d.search(whattype, input);
        if (p.size() == 0){
            cout << "Sorry, no results!" << endl;
        } else {
            cout << "===== Search results =====" << endl;
            print(p);
        }

    }
    else if (input == "-new")
    {
        string firstname, lastname, sex, death;
        int birth;
        cout << "Enter first and last name: ";
        cin >> firstname;
        cin >> lastname;
        cout << "Enter sex: ";
        cin >> sex;
        cout << "Enter year of birth: ";
        while(!(cin>>birth)) {
            cin.clear();
            cin.ignore();
            cout << "Invalid input!" << endl << "Try again: ";
            }
        cout << "Enter year of death, if the person has not died please type \"-\": ";
        cin >> death;
        domain d;
        d.add(firstname, lastname, sex, birth, death);
        cout << "You successfully created new person!" << endl;
    }
    else if (input == "-sort")
    {
        vector<Person> p;
        string input;
        cout << "What do you want to sort by?" << endl;
        cout << "-firstname" << endl << "-lastname" << endl << "-sex" << endl
             << "-yearborn" << endl << "-deathyear" << endl;
        cin >> input;
        domain d;
        p = d.sort(input);
        cout << "===== Sorted list =====" << endl;
        print(p);
    }
    else if (input == "-remove")
    {
        unsigned int lineNumber = 1;
        vector<Person> p;
        domain d;
        p = d.list();
        cout << "===== List =====" << endl;
        for(unsigned int i = 0; i < p.size(); i++) {
            cout << i+1 << "\t"
                 << p[i].getFirstname() << "\t"
                 << p[i].getLastname()  << "\t"
                 << p[i].getSex() << "\t"
                 << p[i].getBirth() << "\t"
                 << p[i].getDeath() << endl;
        }
        cout << "Which entry do you want to remove?" << endl;
        cout << "Type the line number: ";
        do {
            if (lineNumber <= 0 || lineNumber > p.size()) {
                cout << "Sorry this isn't a vailid line, try again: ";
            }
            cin >> lineNumber;
        } while (lineNumber <= 0 || lineNumber > p.size());
        p.erase (p.begin()+(lineNumber-1));
        d.remove(p);
        cout << "You successfully removed line " << lineNumber << endl;
    }
    else if (input == "-help")
    {
        help();
    }
    else if (input == "-exit")
    {
        return false;
    }
    else
    {
        cout << "This command does not exist" << endl;
    }
    return true;

}

<commit_msg>width<commit_after>#include "toplayer.h"
#include "domain.h"
#include <iostream>

using namespace std;

toplayer::toplayer()
{

}
void toplayer::run()
{
    help();
    cout << "\n Enter -help to display the command list again " << endl;
    while(selection())
    {

    }
}
void toplayer::help()
{
    cout << "*********************************************************" << endl;
    cout << "**        Notable Computer Scientists In History       **" << endl;
    cout << "**                                                     **" << endl;
    cout << "**     Enter -new to add a new person                  **" << endl;
    cout << "**     Enter -list for a full list                     **" << endl;
    cout << "**     Enter -search to search the list                **" << endl;
    cout << "**     Enter -remove to remove element from the list   **" << endl;
    cout << "**     Enter -sort to sort the list                    **" << endl;
    cout << "**     Enter -exit to exit the program                 **" << endl;
    cout << "**                                                     **" << endl;
    cout << "*********************************************************" << endl;
}

void toplayer::print(vector<Person>& pers) {

    for(unsigned int i = 0; i < pers.size(); i++) {
        cout.width(10);
        cout << left;
        cout << pers[i].getFirstname();
        cout.width(10);
        cout <<left;
        cout << pers[i].getLastname();
        cout.width(10);
        cout << left;
        cout << pers[i].getSex();
        cout.width(10);
        cout <<left;
        cout << pers[i].getBirth();
        cout.width(10);
        cout << left;
        cout << pers[i].getDeath() << endl;
    }
    cout << "======================================" << endl;

}

bool toplayer::selection()
{
    string input;
    cin >> input;
    if (input == "-list")
    {
        vector<Person> p;
        domain d;
        p = d.list();
        cout << "================ List ================" << endl;
        print(p);
    }
    else if (input == "-search")
    {
        vector<Person> p;
        domain d;
        string whattype, input;
        cout << "What do you want to search for?" << endl;
        cout << "-firstname" << endl << "-lastname" << endl << "-sex"
             << endl << "-birthyear" << endl << "-deathyear" << endl;
        cout << "Enter your choice: ";
        cin >> whattype;
        cout << "What is word do you want to serch for? ";
        cin >> input;
        p = d.search(whattype, input);
        if (p.size() == 0){
            cout << "Sorry, no results!" << endl;
        } else {
            cout << "===== Search results =====" << endl;
            print(p);
        }

    }
    else if (input == "-new")
    {
        string firstname, lastname, sex, death;
        int birth;
        cout << "Enter first and last name: ";
        cin >> firstname;
        cin >> lastname;
        cout << "Enter sex: ";
        cin >> sex;
        cout << "Enter year of birth: ";
        while(!(cin>>birth)) {
            cin.clear();
            cin.ignore();
            cout << "Invalid input!" << endl << "Try again: ";
            }
        cout << "Enter year of death, if the person has not died please type \"-\": ";
        cin >> death;
        domain d;
        d.add(firstname, lastname, sex, birth, death);
        cout << "You successfully created new person!" << endl;
    }
    else if (input == "-sort")
    {
        vector<Person> p;
        string input;
        cout << "What do you want to sort by?" << endl;
        cout << "-firstname" << endl << "-lastname" << endl << "-sex" << endl
             << "-yearborn" << endl << "-deathyear" << endl;
        cin >> input;
        domain d;
        p = d.sort(input);
        cout << "===== Sorted list =====" << endl;
        print(p);
    }
    else if (input == "-remove")
    {
        unsigned int lineNumber = 1;
        vector<Person> p;
        domain d;
        p = d.list();
        cout << "===== List =====" << endl;
        for(unsigned int i = 0; i < p.size(); i++){
            cout << i+1 << "\t"
                 << p[i].getFirstname() << "\t"
                 << p[i].getLastname() << "\t"
                 << p[i].getSex() << "\t"
                 << p[i].getBirth() << "\t"
                 << p[i].getDeath() << endl;
        }
        cout << "Which entry do you want to remove?" << endl;
        cout << "Type the line number: ";
        do {
            if (lineNumber <= 0 || lineNumber > p.size()) {
                cout << "Sorry this isn't a vailid line, try again: ";
            }
            cin >> lineNumber;
        } while (lineNumber <= 0 || lineNumber > p.size());
        p.erase (p.begin()+(lineNumber-1));
        d.remove(p);
        cout << "You successfully removed line " << lineNumber << endl;
    }
    else if (input == "-help")
    {
        help();
    }
    else if (input == "-exit")
    {
        return false;
    }
    else
    {
        cout << "This command does not exist" << endl;
    }
    return true;

}

<|endoftext|>


<commit_before>/* snesasm

nicklausw's attempt at a portable
snes assembler

licensed under the isc license. you
should have gotten a copy with snesasm,
if not then visit http://nicklausw.github.io/isc.txt

enjoy. */

#include <iostream> // basics
#include <fstream> // io
#include <string> // string
#include <sstream> // file streams
#include <vector> // vectors
#include <cctype> // char checks
#include <cstdlib> // exit
using namespace std; // print

// definitions
#define success 0
#define fail 1

// function declarations
void help(string prog_name); // help message
int snesasm(string in, string out); // the true main function
bool file_existent(string name); // file existence check
void file_to_string(string file); // speaks for itself
int lexer(); // the wonderful lexer magic
int append_token(unsigned int counter, int current_token); // add token to string
int pass_1(); // first pass: get directives, labels, defines
int pass_2(); // second pass: calculate stuff, fix stuff, write to rom
int hint_next_token_type(unsigned int counter, string cur); // speaks for itself
string hint_next_token_dat(unsigned int counter, string cur); // same
int one_numeric_arg(string str, unsigned int counter); // directives with one number arg

// token struct
typedef struct {
    int token_type; // type
    string token_i; // internals
} token;

// tokens vector
vector<token> tokens;

// token types
int tkUNDEF = 0; // fail
int tkNUM = 1; // number
int tkDIR = 2; // directive
int tkOP = 3; // opcode

string ins; // universal file string

// snes variables
bool compcheck_flag = false;
bool autoromsize_flag = false;
int romsize = 0;
int carttype = 0;
int licenseecode = 0;
int version = 0;

// temporary transfer variable
int tr = 0;

int main(int argc, char **argv)
{
    // args!
    if (argc != 3) {
        help(argv[0]);
        return fail;
    }

    // hand it all off to snesasm()
    if (snesasm(string(argv[1]), string(argv[2])) == fail) return fail;
    return success;
}

void help(string prog_name)
{
    cerr << "snesasm by nicklausw\n";
    cerr << "args: " << prog_name << " [in file] [out file]\n";
}

int snesasm(string in, string out)
{
    if (file_existent(in) == false) {
        cerr << "error: file " << in << " doesn't exist\n";
        return fail;
    }

    file_to_string(in); // read file
    if (lexer() == fail) return fail; // lexer magic
    if (pass_1() == fail) return fail; // pass 1
    if (pass_2() == fail) return fail; // pass 2

    return success;
}

bool file_existent(string name)
{
    ifstream file(name.c_str());
    return file.good();
}

void file_to_string(string file)
{
    ifstream in(file.c_str()); // file stream
    string str; // temporary build-up string
    char in_c; // char for comparison
    unsigned int counter = 0; // basic counter

    // clear ins
    ins.clear();

    // read into new_str converting tabs to spaces
    while (!in.eof()) {
        in.get(in_c);
        if (in_c == '\t') {
            ins.append(" ");
        } else {
            ins.append(string(1, in_c));
        }
    }

    str = ins;

    // simplify multiple spaces to one space
    ins.clear();

    while (counter <= str.length()) {
        if (str[counter] == ' ') {
            ins.append(" ");
            while (str[counter] == ' ') {
                counter++;
                if (counter == str.length())
                    break;
            }
        } else {
            ins.append(string(1, str[counter]));
            counter++;
        }
    }

    // do same to remove comments
    ins.clear();
    counter = 0;

    while (counter <= str.length()) {
        if (str[counter] == ';') {
            ins.append("\n");
            while (str[counter] != '\n') {
                counter++;
                if (counter == str.length())
                    break;
            }
        } else {
            ins.append(string(1, str[counter]));
            counter++;
        }
    }
}

int lexer()
{
    // the crazy part, tokens
    unsigned int counter = 0; // counter again
    int current_token = 0; // vector location value
    bool ct_used = false; // current token usage

    // we need the token vector big enough
    // for the first token, obviously
    tokens.resize(1);

    while (counter <= ins.length()) {
        // handle newlines
        if (ins[counter] == '\n' || ins[counter] == ' ') {
            if (ct_used == false) {
                counter++;
                continue;
            } else {
                // handle vector size
                tokens.resize((current_token+1)*sizeof(token));

                // get ready for another loop
                ct_used = false;
                counter++;
                current_token++;
                continue;
            }
        }

        // no newline means do a token

        if (ins[counter] == '.') {
            // directive
            ct_used = true;
            tokens[current_token].token_type = tkDIR;
            counter++; // skip period

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        } else if (isalpha(ins[counter])) {
            // opcode
            ct_used = true;
            tokens[current_token].token_type = tkOP;

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        } else if (isdigit(ins[counter])) {
            // number
            ct_used = true;
            tokens[current_token].token_type = tkNUM;

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        }

        // be sure to move on to next symbol.
        counter++;
    }

    return success;
}

int append_token(unsigned int counter, int current_token)
{
    while (ins[counter] != ' ' && ins[counter] != '\n') {
                if (counter == ins.length())
                    break; // no overflows please!
                tokens[current_token].token_i.append(string(1, ins[counter]));
                counter++;
    }

    return counter;
}

int pass_1()
{
    for (unsigned int counter = 0; counter < (tokens.size())/sizeof(token); counter++) {
        if (tokens[counter].token_type == tkDIR) {
            if (tokens[counter].token_i == "compcheck") {
                compcheck_flag = true;
            } else if (tokens[counter].token_i == "autoromsize") {
                autoromsize_flag = true;
            } else if (tokens[counter].token_i == "romsize") {
                counter = one_numeric_arg("romsize", counter); romsize = tr;
            } else if (tokens[counter].token_i == "carttype") {
                counter = one_numeric_arg("carttype", counter); carttype = tr;
            } else if (tokens[counter].token_i == "licenseecode") {
                counter = one_numeric_arg("licenseecode", counter); licenseecode = tr;
            } else if (tokens[counter].token_i == "version") {
                counter = one_numeric_arg("version", counter); version = tr;
            } else {
                cout << "error: unknown directive \"" << tokens[counter].token_i << "\"\n";
                return fail;
            }
        } else if (tokens[counter].token_type == tkNUM) {
            cout << "error: loose num " << tokens[counter].token_i << '\n';
            return fail;
        } else if (tokens[counter].token_type == tkOP) {
            cout << "error: opcodes aren't implemented yet, sorry.\n";
            return fail;
        } else {
            cout << "error: unknown symbol \"" << tokens[counter].token_i << "\"\n";
            return fail;
        }
    }

    return success;
}

int pass_2()
{
    return success;
}

int hint_next_token_type(unsigned int counter, string cur)
{
    if (counter >= tokens.size()) {
        cout << "error: " << cur << " requires args\n";
        exit(fail);
    }

    return tokens[counter+1].token_type;
}

string hint_next_token_dat(unsigned int counter, string cur)
{
    if (counter >= tokens.size()) {
        cout << "error: " << cur << " requires args\n";
        exit(fail);
    }

    return tokens[counter+1].token_i;
}

int one_numeric_arg(string str, unsigned int counter)
{
    if (hint_next_token_type(counter, tokens[counter].token_i) != tkNUM) {
        cout << "error: " << str << " expects numeric args\n";
        exit(fail);
    } else {
		string out_hint = hint_next_token_dat(counter, tokens[counter].token_i);
		tr = atoi(out_hint.c_str());
        counter++;
    }

    return counter;
}
<commit_msg>tabs -> spaces<commit_after>/* snesasm

nicklausw's attempt at a portable
snes assembler

licensed under the isc license. you
should have gotten a copy with snesasm,
if not then visit http://nicklausw.github.io/isc.txt

enjoy. */

#include <iostream> // basics
#include <fstream> // io
#include <string> // string
#include <sstream> // file streams
#include <vector> // vectors
#include <cctype> // char checks
#include <cstdlib> // exit
using namespace std; // print

// definitions
#define success 0
#define fail 1

// function declarations
void help(string prog_name); // help message
int snesasm(string in, string out); // the true main function
bool file_existent(string name); // file existence check
void file_to_string(string file); // speaks for itself
int lexer(); // the wonderful lexer magic
int append_token(unsigned int counter, int current_token); // add token to string
int pass_1(); // first pass: get directives, labels, defines
int pass_2(); // second pass: calculate stuff, fix stuff, write to rom
int hint_next_token_type(unsigned int counter, string cur); // speaks for itself
string hint_next_token_dat(unsigned int counter, string cur); // same
int one_numeric_arg(string str, unsigned int counter); // directives with one number arg

// token struct
typedef struct {
    int token_type; // type
    string token_i; // internals
} token;

// tokens vector
vector<token> tokens;

// token types
int tkUNDEF = 0; // fail
int tkNUM = 1; // number
int tkDIR = 2; // directive
int tkOP = 3; // opcode

string ins; // universal file string

// snes variables
bool compcheck_flag = false;
bool autoromsize_flag = false;
int romsize = 0;
int carttype = 0;
int licenseecode = 0;
int version = 0;

// temporary transfer variable
int tr = 0;

int main(int argc, char **argv)
{
    // args!
    if (argc != 3) {
        help(argv[0]);
        return fail;
    }

    // hand it all off to snesasm()
    if (snesasm(string(argv[1]), string(argv[2])) == fail) return fail;
    return success;
}

void help(string prog_name)
{
    cerr << "snesasm by nicklausw\n";
    cerr << "args: " << prog_name << " [in file] [out file]\n";
}

int snesasm(string in, string out)
{
    if (file_existent(in) == false) {
        cerr << "error: file " << in << " doesn't exist\n";
        return fail;
    }

    file_to_string(in); // read file
    if (lexer() == fail) return fail; // lexer magic
    if (pass_1() == fail) return fail; // pass 1
    if (pass_2() == fail) return fail; // pass 2

    return success;
}

bool file_existent(string name)
{
    ifstream file(name.c_str());
    return file.good();
}

void file_to_string(string file)
{
    ifstream in(file.c_str()); // file stream
    string str; // temporary build-up string
    char in_c; // char for comparison
    unsigned int counter = 0; // basic counter

    // clear ins
    ins.clear();

    // read into new_str converting tabs to spaces
    while (!in.eof()) {
        in.get(in_c);
        if (in_c == '\t') {
            ins.append(" ");
        } else {
            ins.append(string(1, in_c));
        }
    }

    str = ins;

    // simplify multiple spaces to one space
    ins.clear();

    while (counter <= str.length()) {
        if (str[counter] == ' ') {
            ins.append(" ");
            while (str[counter] == ' ') {
                counter++;
                if (counter == str.length())
                    break;
            }
        } else {
            ins.append(string(1, str[counter]));
            counter++;
        }
    }

    // do same to remove comments
    ins.clear();
    counter = 0;

    while (counter <= str.length()) {
        if (str[counter] == ';') {
            ins.append("\n");
            while (str[counter] != '\n') {
                counter++;
                if (counter == str.length())
                    break;
            }
        } else {
            ins.append(string(1, str[counter]));
            counter++;
        }
    }
}

int lexer()
{
    // the crazy part, tokens
    unsigned int counter = 0; // counter again
    int current_token = 0; // vector location value
    bool ct_used = false; // current token usage

    // we need the token vector big enough
    // for the first token, obviously
    tokens.resize(1);

    while (counter <= ins.length()) {
        // handle newlines
        if (ins[counter] == '\n' || ins[counter] == ' ') {
            if (ct_used == false) {
                counter++;
                continue;
            } else {
                // handle vector size
                tokens.resize((current_token+1)*sizeof(token));

                // get ready for another loop
                ct_used = false;
                counter++;
                current_token++;
                continue;
            }
        }

        // no newline means do a token

        if (ins[counter] == '.') {
            // directive
            ct_used = true;
            tokens[current_token].token_type = tkDIR;
            counter++; // skip period

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        } else if (isalpha(ins[counter])) {
            // opcode
            ct_used = true;
            tokens[current_token].token_type = tkOP;

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        } else if (isdigit(ins[counter])) {
            // number
            ct_used = true;
            tokens[current_token].token_type = tkNUM;

            counter = append_token(counter, current_token);

            // no need for a counter++ here, it's handled above.
            continue;
        }

        // be sure to move on to next symbol.
        counter++;
    }

    return success;
}

int append_token(unsigned int counter, int current_token)
{
    while (ins[counter] != ' ' && ins[counter] != '\n') {
                if (counter == ins.length())
                    break; // no overflows please!
                tokens[current_token].token_i.append(string(1, ins[counter]));
                counter++;
    }

    return counter;
}

int pass_1()
{
    for (unsigned int counter = 0; counter < (tokens.size())/sizeof(token); counter++) {
        if (tokens[counter].token_type == tkDIR) {
            if (tokens[counter].token_i == "compcheck") {
                compcheck_flag = true;
            } else if (tokens[counter].token_i == "autoromsize") {
                autoromsize_flag = true;
            } else if (tokens[counter].token_i == "romsize") {
                counter = one_numeric_arg("romsize", counter); romsize = tr;
            } else if (tokens[counter].token_i == "carttype") {
                counter = one_numeric_arg("carttype", counter); carttype = tr;
            } else if (tokens[counter].token_i == "licenseecode") {
                counter = one_numeric_arg("licenseecode", counter); licenseecode = tr;
            } else if (tokens[counter].token_i == "version") {
                counter = one_numeric_arg("version", counter); version = tr;
            } else {
                cout << "error: unknown directive \"" << tokens[counter].token_i << "\"\n";
                return fail;
            }
        } else if (tokens[counter].token_type == tkNUM) {
            cout << "error: loose num " << tokens[counter].token_i << '\n';
            return fail;
        } else if (tokens[counter].token_type == tkOP) {
            cout << "error: opcodes aren't implemented yet, sorry.\n";
            return fail;
        } else {
            cout << "error: unknown symbol \"" << tokens[counter].token_i << "\"\n";
            return fail;
        }
    }

    return success;
}

int pass_2()
{
    return success;
}

int hint_next_token_type(unsigned int counter, string cur)
{
    if (counter >= tokens.size()) {
        cout << "error: " << cur << " requires args\n";
        exit(fail);
    }

    return tokens[counter+1].token_type;
}

string hint_next_token_dat(unsigned int counter, string cur)
{
    if (counter >= tokens.size()) {
        cout << "error: " << cur << " requires args\n";
        exit(fail);
    }

    return tokens[counter+1].token_i;
}

int one_numeric_arg(string str, unsigned int counter)
{
    if (hint_next_token_type(counter, tokens[counter].token_i) != tkNUM) {
        cout << "error: " << str << " expects numeric args\n";
        exit(fail);
    } else {
        string out_hint = hint_next_token_dat(counter, tokens[counter].token_i);
        tr = atoi(out_hint.c_str());
        counter++;
    }

    return counter;
}
<|endoftext|>


<commit_before>#include "sniffer.h"

#include "util.h"
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <string>
#include <pcap.h>
#include <map>
#include <iostream>

using namespace std;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

const int num_channels = 12;
int current_channel = 0;

void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  run_command(argv);
}

const float max_time = 60;
const float round_time = 12;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

void initialize(char * interface) {
  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

struct ieee80211_radiotap_header {
        u_int8_t        it_version;     /* set to 0 */
        u_int8_t        it_pad;
        u_int16_t       it_len;         /* entire length */
        u_int32_t       it_present;     /* fields present */
} __attribute__((__packed__));

struct prism_value{
  u_int32_t did;
  u_int16_t status;
  u_int16_t len;
  u_int32_t data;
};

struct prism_header{
  u_int32_t msgcode;
  u_int32_t msglen;
  prism_value hosttime;
  prism_value mactime;
  prism_value channel;
  prism_value rssi;
  prism_value sq;
  prism_value signal;
  prism_value noise;
  prism_value rate;
  prism_value istx;
  prism_value frmlen;
};

map<string,int> mac_count[num_channels+1][4];

void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  debug("MAC %d : %s",pos,mac_c_str);
}

void handlePacket(const u_char* packet) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    handleMAC(packet+4+(i*6),i);
  }

  channel_packets[current_channel]++;
}

class Timer {
  timespec start_time;

  float diff(timespec start, timespec end) {
	  timespec temp;
	  if ((end.tv_nsec-start.tv_nsec)<0) {
		  temp.tv_sec = end.tv_sec-start.tv_sec-1;
		  temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
	  } else {
		  temp.tv_sec = end.tv_sec-start.tv_sec;
		  temp.tv_nsec = end.tv_nsec-start.tv_nsec;
	  }
    return (float)temp.tv_sec + 1e-9 * temp.tv_nsec;
  }

public:
  void reset() { clock_gettime(CLOCK_MONOTONIC_COARSE,&start_time); }
  float get_time() {
    timespec temp;
    clock_gettime(CLOCK_MONOTONIC_COARSE,&temp);
    return diff(start_time,temp);
  }
  Timer() { reset(); }
};

void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    pcap_pkthdr header;
    handlePacket(pcap_next(handle, &header));
    debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

void print_info() {
  cout << "\n\n";
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
     }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
  }
}

// TODO: Make sure that pcap_next doesn't take too long
// TODO: Output timetamps for each MAC in debug mode<commit_msg>Take care of message lengths<commit_after>#include "sniffer.h"

#include "util.h"
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <string>
#include <pcap.h>
#include <map>
#include <iostream>

using namespace std;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

const int num_channels = 12;
int current_channel = 0;

void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  run_command(argv);
}

const float max_time = 60;
const float round_time = 12;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

void initialize(char * interface) {
  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

struct ieee80211_radiotap_header {
        u_int8_t        it_version;     /* set to 0 */
        u_int8_t        it_pad;
        u_int16_t       it_len;         /* entire length */
        u_int32_t       it_present;     /* fields present */
} __attribute__((__packed__));

struct prism_value{
  u_int32_t did;
  u_int16_t status;
  u_int16_t len;
  u_int32_t data;
};

struct prism_header{
  u_int32_t msgcode;
  u_int32_t msglen;
  prism_value hosttime;
  prism_value mactime;
  prism_value channel;
  prism_value rssi;
  prism_value sq;
  prism_value signal;
  prism_value noise;
  prism_value rate;
  prism_value istx;
  prism_value frmlen;
};

map<string,int> mac_count[num_channels+1][4];

void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  debug("MAC %d : %s",pos,mac_c_str);
}

void handlePacket(const u_char* packet, int length) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
    length -= rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
    length -= rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    if ( 4+i*6 < length ) {
      handleMAC(packet+4+(i*6),i);
    }
  }

  channel_packets[current_channel]++;
}

class Timer {
  timespec start_time;

  float diff(timespec start, timespec end) {
	  timespec temp;
	  if ((end.tv_nsec-start.tv_nsec)<0) {
		  temp.tv_sec = end.tv_sec-start.tv_sec-1;
		  temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
	  } else {
		  temp.tv_sec = end.tv_sec-start.tv_sec;
		  temp.tv_nsec = end.tv_nsec-start.tv_nsec;
	  }
    return (float)temp.tv_sec + 1e-9 * temp.tv_nsec;
  }

public:
  void reset() { clock_gettime(CLOCK_MONOTONIC_COARSE,&start_time); }
  float get_time() {
    timespec temp;
    clock_gettime(CLOCK_MONOTONIC_COARSE,&temp);
    return diff(start_time,temp);
  }
  Timer() { reset(); }
};

void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    pcap_pkthdr header;
    handlePacket(pcap_next(handle, &header),header.len);
    debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

void print_info() {
  cout << "\n\n";
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
     }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
  }
}

// TODO: Make sure that pcap_next doesn't take too long
// TODO: Output timetamps for each MAC in debug mode<|endoftext|>


<commit_before>const int num_channels = 12;
const float max_time = 60;
const float round_time = max_time/5;

#include "sniffer.h"
#include "protocol_headers.h"
#include "util.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <pcap.h>
#include <map>
#include <set>
#include <iostream>

using namespace std;

int macstat_flag = 0;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

int current_channel = 0;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

map<string,int> mac_count[num_channels+1][4];

multimap<string,string> mac_timestamp;

void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  int ret = run_command(argv);
  if ( ret ) {
    debug("Probably on an Ubuntu system. Trying to set monitor using ifconfig technique.");
    char * const ifconfig_down[] = {(char*)("ifconfig"),iface,(char*)("down"),0};
    char * const ifconfig_up[] = {(char*)("ifconfig"),iface,(char*)("up"),0};
    ret = run_command(ifconfig_down);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(argv);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(ifconfig_up);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
  }
}

void initialize(char * interface) {
  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  if ( pcap_setnonblock(handle,1,errbuf) == -1 ) {
    error("Couldn't set to non-blocking mode. Error: %s",errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  time_t t = time(NULL);
  mac_timestamp.insert(make_pair(mac_str,string(ctime(&t))));
  debug("MAC %d : %s",pos,mac_c_str);
}

void handlePacket(const u_char* packet, int length) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
    length -= rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
    length -= rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    if ( 4+i*6 < length ) {
      handleMAC(packet+4+(i*6),i);
    }
  }

  channel_packets[current_channel]++;
}

void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

void callback(u_char *user,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
  handlePacket(packet,pkthdr->len);
}

void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    if ( pcap_dispatch(handle,1,callback,NULL) ) {
      debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    }
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

void print_info() {
  cout << "\n\n";
  int overall_total_mac_count = 0;
  int overall_total_packets_captured = 0;
  float overall_total_time = 0;
  set<string> overall_macs;
  bool suppressed = false;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    if ( channel_packets[i] == 0 ) {
      suppressed = true;
      continue;
    }
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
        overall_macs.insert(it->first);
      }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
    overall_total_mac_count += total_mac_count;
    overall_total_packets_captured += channel_packets[i];
    overall_total_time += channel_time[i];
  }
  if ( suppressed ) {
    cout << "Note: Output for empty channels suppressed.\n";
  }
  if ( macstat_flag ) {
    cout << "\nTimestamps: \n";
    for ( multimap<string,string>::iterator it = mac_timestamp.begin() ; it != mac_timestamp.end() ; it++ ) {
      cout << "  " << it->first << " : " << it->second;
    }
    cout << "\n";
  }
  cout << "Overall:\n";
  cout << " Number of unique MACs seen = " << overall_macs.size() << endl;
  cout << " Total number of MACs seen  = " << overall_total_mac_count << endl;
  cout << " Total packets captured     = " << overall_total_packets_captured << endl;
  cout << " Packet capture rate        = " << overall_total_packets_captured/overall_total_time << " packets/sec" << endl;
  cout << "\n";
}
<commit_msg>Handle MAC outputs better<commit_after>const int num_channels = 12;
const float max_time = 60;
const float round_time = max_time/5;

#include "sniffer.h"
#include "protocol_headers.h"
#include "util.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <pcap.h>
#include <map>
#include <set>
#include <iostream>

using namespace std;

int macstat_flag = 0;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

int current_channel = 0;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

map<string,int> mac_count[num_channels+1][4];

multimap<string,string> mac_timestamp;

void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  int ret = run_command(argv);
  if ( ret ) {
    debug("Probably on an Ubuntu system. Trying to set monitor using ifconfig technique.");
    char * const ifconfig_down[] = {(char*)("ifconfig"),iface,(char*)("down"),0};
    char * const ifconfig_up[] = {(char*)("ifconfig"),iface,(char*)("up"),0};
    ret = run_command(ifconfig_down);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(argv);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(ifconfig_up);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
  }
}

void initialize(char * interface) {
  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  if ( pcap_setnonblock(handle,1,errbuf) == -1 ) {
    error("Couldn't set to non-blocking mode. Error: %s",errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  time_t t = time(NULL);
  mac_timestamp.insert(make_pair(mac_str,string(ctime(&t))));
  debug("MAC %d : %s",pos,mac_c_str);
}

void handlePacket(const u_char* packet, int length) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
    length -= rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
    length -= rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    if ( 4+i*6 < length ) {
      handleMAC(packet+4+(i*6),i);
    }
  }

  channel_packets[current_channel]++;
}

void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

void callback(u_char *user,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
  handlePacket(packet,pkthdr->len);
}

void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    if ( pcap_dispatch(handle,1,callback,NULL) ) {
      debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    }
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

void print_info() {
  cout << "\n\n";
  int overall_total_mac_count = 0;
  int overall_total_packets_captured = 0;
  float overall_total_time = 0;
  set<string> overall_macs;
  bool suppressed = false;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    if ( channel_packets[i] == 0 ) {
      suppressed = true;
      continue;
    }
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
        overall_macs.insert(it->first);
      }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
    overall_total_mac_count += total_mac_count;
    overall_total_packets_captured += channel_packets[i];
    overall_total_time += channel_time[i];
  }
  if ( suppressed ) {
    cout << "Note: Output for empty channels suppressed.\n";
  }
  if ( macstat_flag ) {
    cout << "\nMAC Stats: \n";
    string prev_mac = "";
    for ( multimap<string,string>::iterator it = mac_timestamp.begin() ; it != mac_timestamp.end() ; it++ ) {
      string mac = it->first;
      if ( mac != prev_mac ) {
        cout << "  " << mac << " - " << mac_timestamp.count(mac) << endl;
      }
      cout << "    " << it->second;
      prev_mac = mac;
    }
    cout << "\n";
  }
  cout << "Overall:\n";
  cout << " Number of unique MACs seen = " << overall_macs.size() << endl;
  cout << " Total number of MACs seen  = " << overall_total_mac_count << endl;
  cout << " Total packets captured     = " << overall_total_packets_captured << endl;
  cout << " Packet capture rate        = " << overall_total_packets_captured/overall_total_time << " packets/sec" << endl;
  cout << "\n";
}
<|endoftext|>