<commit_before>#include <set>
#include <sstream>
#include <string>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>

#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>

namespace asio = boost::asio;
namespace ip = asio::ip;
namespace placeholders = asio::placeholders;
namespace sys = boost::system;
namespace algorithm = boost::algorithm;

template< typename TConnection >
class Task
{
public:
    Task( TConnection * connection )
        : m_connection( connection )
    {
    }

    typename TConnection::Action parseLine(
        asio::streambuf & buffer
    )
    {
        return TConnection::Action::ReadCompleted;
    }

    typename TConnection::Action parseSome(
        asio::streambuf & buffer
    )
    {
        return TConnection::Action::ReadCompleted;
    }

    void parseError(
        sys::error_code const & errorCode
    )
    {
        std::cerr
            << "Parse error"
            << std::endl;
    }

    void process(
        asio::streambuf & buffer,
        sys::error_code const & errorCode
    )
    {
        std::istream iss( & buffer );

        char command, cr, lf;
        iss >> command;

        if( command == 'g' )
        {
            std::string id;
            iss >> id >> cr >> lf;
            m_connection->setId( id );

            char const * const line = "Hello.";
            m_connection->responseAndRead( line, strlen( line ) );
        }
        else if( command == 'b' )
        {
            std::string message;
            iss >> message >> cr >> lf;

            m_connection->broadcastAndRead( message.c_str(), message.size() );
        }
        else if( command == 'u' )
        {
            std::string id;
            std::string message;
            iss >> id >> message >> cr >> lf;

            m_connection->unicastAndRead( id, message.c_str(), message.size() );
        }
        else
        {
            std::cout << "unknown" << std::endl;

            m_connection->start();
        }
    }

private:
    TConnection * m_connection;
};

class ConnectionManager;

class Connection
    : public boost::enable_shared_from_this< Connection >
{
public:

    typedef boost::shared_ptr< Connection > ConnectionPtr;

public:

    enum class Action
    {
        ReadCompleted,
        ReadError,
        ReadLine,
        ReadSome
    };

    Connection(
        asio::io_service & ioService,
        ConnectionManager & connectionManager
    );

    ip::tcp::socket & socket();

    void onStop();

    void start(
        Action const action = Action::ReadLine
    );

public: // api

    void setId(
        std::string const & id
    );

    std::string const & getId() const ;

    Action parseLine();

    Action parseSome();

    void parseError(
        sys::error_code const & errorCode
    );

    void process(
        sys::error_code const & errorCode
    );

    void broadcastAndRead(
        char const * const message,
        std::size_t const size
    );

    void broadcastAndProcess(
        char const * const message,
        std::size_t const size
    );

    void broadcastAndStop(
        char const * const message,
        std::size_t const size
    );

    void unicastAndRead(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void unicastAndStop(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void unicastAndProcess(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void responseAndRead(
        char const * const message,
        std::size_t const size
    );

    void responseAndProcess(
        char const * const message,
        std::size_t const size
    );

    void responseAndStop(
        char const * const message,
        std::size_t const size
    );

private:

    template< typename MemberPtr >
    void broadcastImpl(
        MemberPtr && memberPtr,
        char const * const message,
        std::size_t const size
    );

    template< typename MemberPtr >
    void unicastImpl(
        MemberPtr && memberPtr,
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    template< typename MemberPtr >
    void responseImpl(
        MemberPtr && memberPtr,
        char const * const message,
        std::size_t const size
    );

    void readLine(
        sys::error_code const & errorCode,
        std::size_t const bytesTransferred
    );

    void readSome(
        sys::error_code const & errorCode,
        std::size_t const bytesTransferred
    );

    void startAgain(
        sys::error_code const & errorCode
    );

    void stop(
        sys::error_code const & errorCode
    );

private:

    ip::tcp::socket m_socket;
    asio::io_service::strand m_strand;
    ConnectionManager & m_connectionManager;

    Task< Connection > m_task;

    std::string m_id;

    asio::streambuf m_buffer;
};

Connection::Connection(
    asio::io_service & ioService,
    ConnectionManager & connectionManager
)
    : m_socket( ioService )
    , m_strand( ioService )
    , m_connectionManager( connectionManager )
    , m_task( this )
{
}

ip::tcp::socket & Connection::socket()
{
    return m_socket;
}

void Connection::setId(
    std::string const & id
)
{
    m_id = id;
}

std::string const & Connection::getId() const
{
    return m_id;
}

void Connection::start(
    Connection::Action const action
)
{
    switch( action )
    {
        case Action::ReadCompleted:
        {
            process( sys::error_code() );

            break;
        }

        case Action::ReadError:
        {
            break;
        }

        case Action::ReadLine:
        {
            auto const readLine = boost::bind(
                & Connection::readLine,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred()
            );

            asio::async_read_until(
                m_socket,
                m_buffer,
                "\r\n",
                m_strand.wrap( readLine )
            );

            break;
        }

        case Action::ReadSome:
        {
            auto const readSome = boost::bind(
                & Connection::readSome,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred()
            );

            asio::async_read(
                m_socket,
                m_buffer,
                asio::transfer_at_least( 1 ),
                m_strand.wrap( readSome )
            );

            break;
        }
    }
}

Connection::Action Connection::parseLine()
{
    return m_task.parseLine( m_buffer );
}

Connection::Action Connection::parseSome()
{
    return m_task.parseLine( m_buffer );
}

void Connection::parseError(
    sys::error_code const & errorCode
)
{
    m_task.parseError( errorCode );
}

void Connection::process(
    sys::error_code const & errorCode
)
{
    m_task.process( m_buffer, errorCode );
}

void Connection::readLine(
    sys::error_code const & errorCode,
    std::size_t const bytesTransferred
)
{
    if( errorCode )
    {
        std::cerr << "Response Read Error: " << errorCode.message() << std::endl;
    }
    else
    {
        start( parseLine() );
    }
}

void Connection::readSome(
    sys::error_code const & errorCode,
    std::size_t const bytesTransferred
)
{
    if( errorCode )
    {
        std::cerr << "Response Read Error: " << errorCode.message() << std::endl;
    }
    else
    {
        start( parseSome() );
    }
}

void Connection::startAgain(
    sys::error_code const & errorCode
)
{
    if( ! errorCode )
    {
        start();
    }
}

void Connection::stop(
    sys::error_code const & errorCode
)
{
}

typedef Connection::ConnectionPtr ConnectionPtr;

class ConnectionManager
    : public boost::noncopyable
{
    typedef std::set< ConnectionPtr > ConnectionsPtr;

public:

    template< typename Function, class... Args >
    void forEach( Function&& func, Args && ...args )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        for( auto & connection : m_connections )
        {
            func( connection, std::forward< Args >( args )... );
        }
    }

    template< typename Predicate, typename Function, class... Args >
    void forEachIf( Predicate && predicate, Function && func, Args && ...args )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        for( auto & connection : m_connections )
        {
            if( predicate( connection ) )
            {
                func( connection, std::forward< Args >( args )... );
            }
        }
    }

    void add(
        ConnectionPtr & connection
    )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        m_connections.insert( connection );
    }

    void remove(
        ConnectionPtr const & connection
    )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        auto const pos = m_connections.find( connection );

        if( pos != m_connections.end() ){
            m_connections.erase( pos );
        }
    }

private:

    boost::mutex m_mutex;
    ConnectionsPtr m_connections;
};

void Connection::onStop()
{
    char const * const message = "Goodbye.";

    responseAndStop( message, strlen( message ) );
}

template< typename MemberPtr >
void Connection::responseImpl(
    MemberPtr && memberPtr,
    char const * const message,
    std::size_t const size
)
{
    auto const continuation = boost::bind(
        std::forward< MemberPtr >( memberPtr ),
        shared_from_this(),
        placeholders::error
    );

    asio::async_write(
        m_socket,
        asio::buffer( message, size ),
        continuation
    );
}

void Connection::responseAndRead(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::startAgain, message, size );
}

void Connection::responseAndProcess(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::process, message, size );
}

void Connection::responseAndStop(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::stop, message, size );
}

template< typename MemberPtr >
void Connection::broadcastImpl(
    MemberPtr && memberPtr,
    char const * const message,
    std::size_t const size
)
{
    auto const skipSender = [ this ]( ConnectionPtr const & connectionPtr )
    {
        return connectionPtr->socket().native_handle() != this->socket().native_handle();
    };

    auto sendMessage = [ this, & size, & message, & memberPtr ]( ConnectionPtr const & connectionPtr )
    {
        auto const continuation = boost::bind(
            std::forward< MemberPtr >( memberPtr ),
            shared_from_this(),
            placeholders::error
        );

        asio::async_write(
            connectionPtr->socket(),
            asio::buffer( message, size ),
            continuation
        );
    };

    m_connectionManager.forEachIf( skipSender, sendMessage );
}

void Connection::broadcastAndStop(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::stop, message, size );
}

void Connection::broadcastAndRead(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::startAgain, message, size );
}

void Connection::broadcastAndProcess(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::process, message, size );
}

template< typename MemberPtr >
void Connection::unicastImpl(
    MemberPtr && memberPtr,
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    auto const matchReceiver = [ this, & receiverId ]( ConnectionPtr const & connectionPtr )
    {
        return connectionPtr->getId() == receiverId;
    };

    auto sendMessage = [ this, & size, & message, & memberPtr ]( ConnectionPtr const & connectionPtr )
    {
        auto const stop = boost::bind(
            std::forward< MemberPtr >( memberPtr ),
            shared_from_this(),
            placeholders::error
        );

        asio::async_write(
            connectionPtr->socket(),
            asio::buffer( message, size ),
            stop
        );
    };

    m_connectionManager.forEachIf( matchReceiver, sendMessage );
}

void Connection::unicastAndStop(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::stop, receiverId, message, size );
}

void Connection::unicastAndProcess(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::process, receiverId, message, size );
}

void Connection::unicastAndRead(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::startAgain, receiverId, message, size );
}

class Server
{
public:

    Server(
        std::string const & port
    )
        : m_acceptor( m_ioService )
        , m_signals( m_ioService )
    {
        m_signals.add( SIGINT );
        m_signals.add( SIGTERM );
        m_signals.add( SIGQUIT );

        m_signals.async_wait(
            boost::bind( & Server::onStop, this )
        );

        ip::tcp::resolver resolver( m_ioService );
        ip::tcp::resolver::query query( "127.0.0.1", port );
        ip::tcp::endpoint endpoint = * resolver.resolve( query );

        m_acceptor.open( endpoint.protocol() );
        m_acceptor.set_option( ip::tcp::acceptor::reuse_address( true ) );
        m_acceptor.bind( endpoint );
        m_acceptor.listen();

        startAccept();
    }

    void run()
    {
        boost::thread_group threadGroup;

        auto const threadBody = boost::bind(
            & asio::io_service::run,
            & m_ioService
        );

        for( unsigned i = 0 ; i < 4 ; ++ i )
        {
            threadGroup.create_thread( threadBody );
        }

        threadGroup.join_all();
    }

private:

    void startAccept()
    {
        m_newConnection.reset( new Connection( m_ioService, m_connectionManager ) );

        m_connectionManager.add( m_newConnection );

        auto const onAccepted = boost::bind(
            & Server::onAccepted,
            this,
            placeholders::error
        );

        m_acceptor.async_accept(
            m_newConnection->socket(),
            onAccepted
        );
    }

    void onAccepted(
        sys::error_code const & errorCode
    )
    {
        if( ! errorCode )
        {
            m_newConnection->start();
        }

        startAccept();
    }

    void onStop()
    {
        m_connectionManager.forEach(
            boost::bind( & Connection::onStop, _1 )
        );

        m_ioService.stop();
    }

private:

    asio::io_service m_ioService;
    asio::ip::tcp::acceptor m_acceptor;
    asio::signal_set m_signals;

    ConnectionPtr m_newConnection;
    ConnectionManager m_connectionManager;
};

int main( int argc, char* argv[] )
{
    Server( argv[1] ).run();
}

<commit_msg>Task class<commit_after>#include <set>
#include <sstream>
#include <string>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>

#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>

namespace asio = boost::asio;
namespace ip = asio::ip;
namespace placeholders = asio::placeholders;
namespace sys = boost::system;
namespace algorithm = boost::algorithm;

template< typename TConnection >
class Task
{
public:
    Task( TConnection * connection )
        : m_connection( connection )
    {
    }

    static typename TConnection::Action start()
    {
        return TConnection::Action::ReadLine;
    }

    typename TConnection::Action parseLine(
        asio::streambuf & buffer
    )
    {
        return TConnection::Action::ReadCompleted;
    }

    typename TConnection::Action parseSome(
        asio::streambuf & buffer
    )
    {
        return TConnection::Action::ReadCompleted;
    }

    void parseError(
        sys::error_code const & errorCode
    )
    {
        std::cerr
            << "Parse error"
            << std::endl;
    }

    void process(
        asio::streambuf & buffer,
        sys::error_code const & errorCode
    )
    {
        std::istream iss( & buffer );

        char command, cr, lf;
        iss >> command;

        if( command == 'g' )
        {
            std::string id;
            iss >> id >> cr >> lf;
            m_connection->setId( id );

            char const * const line = "Hello.";
            m_connection->responseAndRead( line, strlen( line ) );
        }
        else if( command == 'b' )
        {
            std::string message;
            iss >> message >> cr >> lf;

            m_connection->broadcastAndRead( message.c_str(), message.size() );
        }
        else if( command == 'u' )
        {
            std::string id;
            std::string message;
            iss >> id >> message >> cr >> lf;

            m_connection->unicastAndRead( id, message.c_str(), message.size() );
        }
        else
        {
            std::cout << "unknown" << std::endl;

            m_connection->start();
        }
    }

private:
    TConnection * m_connection;
};

class ConnectionManager;

class Connection
    : public boost::enable_shared_from_this< Connection >
{
public:

    typedef boost::shared_ptr< Connection > ConnectionPtr;

public:

    enum class Action
    {
        ReadCompleted,
        ReadError,
        ReadLine,
        ReadSome
    };

    Connection(
        asio::io_service & ioService,
        ConnectionManager & connectionManager
    );

    ip::tcp::socket & socket();

    void onStop();

    void start(
        Action const action = Task< Connection >::start()
    );

public: // api

    void setId(
        std::string const & id
    );

    std::string const & getId() const ;

    Action parseLine();

    Action parseSome();

    void parseError(
        sys::error_code const & errorCode
    );

    void process(
        sys::error_code const & errorCode
    );

    void broadcastAndRead(
        char const * const message,
        std::size_t const size
    );

    void broadcastAndProcess(
        char const * const message,
        std::size_t const size
    );

    void broadcastAndStop(
        char const * const message,
        std::size_t const size
    );

    void unicastAndRead(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void unicastAndStop(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void unicastAndProcess(
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    void responseAndRead(
        char const * const message,
        std::size_t const size
    );

    void responseAndProcess(
        char const * const message,
        std::size_t const size
    );

    void responseAndStop(
        char const * const message,
        std::size_t const size
    );

private:

    template< typename MemberPtr >
    void broadcastImpl(
        MemberPtr && memberPtr,
        char const * const message,
        std::size_t const size
    );

    template< typename MemberPtr >
    void unicastImpl(
        MemberPtr && memberPtr,
        std::string const & receiverId,
        char const * const message,
        std::size_t const size
    );

    template< typename MemberPtr >
    void responseImpl(
        MemberPtr && memberPtr,
        char const * const message,
        std::size_t const size
    );

    void readLine(
        sys::error_code const & errorCode,
        std::size_t const bytesTransferred
    );

    void readSome(
        sys::error_code const & errorCode,
        std::size_t const bytesTransferred
    );

    void startAgain(
        sys::error_code const & errorCode
    );

    void stop(
        sys::error_code const & errorCode
    );

private:

    ip::tcp::socket m_socket;
    asio::io_service::strand m_strand;
    ConnectionManager & m_connectionManager;

    Task< Connection > m_task;

    std::string m_id;

    asio::streambuf m_buffer;
};

Connection::Connection(
    asio::io_service & ioService,
    ConnectionManager & connectionManager
)
    : m_socket( ioService )
    , m_strand( ioService )
    , m_connectionManager( connectionManager )
    , m_task( this )
{
}

ip::tcp::socket & Connection::socket()
{
    return m_socket;
}

void Connection::setId(
    std::string const & id
)
{
    m_id = id;
}

std::string const & Connection::getId() const
{
    return m_id;
}

void Connection::start(
    Connection::Action const action
)
{
    switch( action )
    {
        case Action::ReadCompleted:
        {
            process( sys::error_code() );

            break;
        }

        case Action::ReadError:
        {
            break;
        }

        case Action::ReadLine:
        {
            auto const readLine = boost::bind(
                & Connection::readLine,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred()
            );

            asio::async_read_until(
                m_socket,
                m_buffer,
                "\r\n",
                m_strand.wrap( readLine )
            );

            break;
        }

        case Action::ReadSome:
        {
            auto const readSome = boost::bind(
                & Connection::readSome,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred()
            );

            asio::async_read(
                m_socket,
                m_buffer,
                asio::transfer_at_least( 1 ),
                m_strand.wrap( readSome )
            );

            break;
        }
    }
}

Connection::Action Connection::parseLine()
{
    return m_task.parseLine( m_buffer );
}

Connection::Action Connection::parseSome()
{
    return m_task.parseLine( m_buffer );
}

void Connection::parseError(
    sys::error_code const & errorCode
)
{
    m_task.parseError( errorCode );
}

void Connection::process(
    sys::error_code const & errorCode
)
{
    m_task.process( m_buffer, errorCode );
}

void Connection::readLine(
    sys::error_code const & errorCode,
    std::size_t const bytesTransferred
)
{
    if( errorCode )
    {
        std::cerr << "Response Read Error: " << errorCode.message() << std::endl;
    }
    else
    {
        start( parseLine() );
    }
}

void Connection::readSome(
    sys::error_code const & errorCode,
    std::size_t const bytesTransferred
)
{
    if( errorCode )
    {
        std::cerr << "Response Read Error: " << errorCode.message() << std::endl;
    }
    else
    {
        start( parseSome() );
    }
}

void Connection::startAgain(
    sys::error_code const & errorCode
)
{
    if( errorCode )
    {
        std::cerr << "Start Again Error: " << errorCode.message() << std::endl;
    }
    else
    {
        start();
    }
}

void Connection::stop(
    sys::error_code const & errorCode
)
{
}

typedef Connection::ConnectionPtr ConnectionPtr;

class ConnectionManager
    : public boost::noncopyable
{
    typedef std::set< ConnectionPtr > ConnectionsPtr;

public:

    template< typename Function, class... Args >
    void forEach( Function&& func, Args && ...args )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        for( auto & connection : m_connections )
        {
            func( connection, std::forward< Args >( args )... );
        }
    }

    template< typename Predicate, typename Function, class... Args >
    void forEachIf( Predicate && predicate, Function && func, Args && ...args )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        for( auto & connection : m_connections )
        {
            if( predicate( connection ) )
            {
                func( connection, std::forward< Args >( args )... );
            }
        }
    }

    void add(
        ConnectionPtr & connection
    )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        m_connections.insert( connection );
    }

    void remove(
        ConnectionPtr const & connection
    )
    {
        boost::lock_guard< boost::mutex > lock( m_mutex );

        auto const pos = m_connections.find( connection );

        if( pos != m_connections.end() ){
            m_connections.erase( pos );
        }
    }

private:

    boost::mutex m_mutex;
    ConnectionsPtr m_connections;
};

void Connection::onStop()
{
    char const * const message = "Goodbye.";

    responseAndStop( message, strlen( message ) );
}

template< typename MemberPtr >
void Connection::responseImpl(
    MemberPtr && memberPtr,
    char const * const message,
    std::size_t const size
)
{
    auto const continuation = boost::bind(
        std::forward< MemberPtr >( memberPtr ),
        shared_from_this(),
        placeholders::error
    );

    asio::async_write(
        m_socket,
        asio::buffer( message, size ),
        continuation
    );
}

void Connection::responseAndRead(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::startAgain, message, size );
}

void Connection::responseAndProcess(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::process, message, size );
}

void Connection::responseAndStop(
    char const * const message,
    std::size_t const size
)
{
    responseImpl( & Connection::stop, message, size );
}

template< typename MemberPtr >
void Connection::broadcastImpl(
    MemberPtr && memberPtr,
    char const * const message,
    std::size_t const size
)
{
    auto const skipSender = [ this ]( ConnectionPtr const & connectionPtr )
    {
        return connectionPtr->socket().native_handle() != this->socket().native_handle();
    };

    auto sendMessage = [ this, & size, & message, & memberPtr ]( ConnectionPtr const & connectionPtr )
    {
        auto const continuation = boost::bind(
            std::forward< MemberPtr >( memberPtr ),
            shared_from_this(),
            placeholders::error
        );

        asio::async_write(
            connectionPtr->socket(),
            asio::buffer( message, size ),
            continuation
        );
    };

    m_connectionManager.forEachIf( skipSender, sendMessage );
}

void Connection::broadcastAndStop(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::stop, message, size );
}

void Connection::broadcastAndRead(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::startAgain, message, size );
}

void Connection::broadcastAndProcess(
    char const * const message,
    std::size_t const size
)
{
    broadcastImpl( & Connection::process, message, size );
}

template< typename MemberPtr >
void Connection::unicastImpl(
    MemberPtr && memberPtr,
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    auto const matchReceiver = [ this, & receiverId ]( ConnectionPtr const & connectionPtr )
    {
        return connectionPtr->getId() == receiverId;
    };

    auto sendMessage = [ this, & size, & message, & memberPtr ]( ConnectionPtr const & connectionPtr )
    {
        auto const stop = boost::bind(
            std::forward< MemberPtr >( memberPtr ),
            shared_from_this(),
            placeholders::error
        );

        asio::async_write(
            connectionPtr->socket(),
            asio::buffer( message, size ),
            stop
        );
    };

    m_connectionManager.forEachIf( matchReceiver, sendMessage );
}

void Connection::unicastAndStop(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::stop, receiverId, message, size );
}

void Connection::unicastAndProcess(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::process, receiverId, message, size );
}

void Connection::unicastAndRead(
    std::string const & receiverId,
    char const * const message,
    std::size_t const size
)
{
    unicastImpl( & Connection::startAgain, receiverId, message, size );
}

class Server
{
public:

    Server(
        std::string const & port
    )
        : m_acceptor( m_ioService )
        , m_signals( m_ioService )
    {
        m_signals.add( SIGINT );
        m_signals.add( SIGTERM );
        m_signals.add( SIGQUIT );

        m_signals.async_wait(
            boost::bind( & Server::onStop, this )
        );

        ip::tcp::resolver resolver( m_ioService );
        ip::tcp::resolver::query query( "127.0.0.1", port );
        ip::tcp::endpoint endpoint = * resolver.resolve( query );

        m_acceptor.open( endpoint.protocol() );
        m_acceptor.set_option( ip::tcp::acceptor::reuse_address( true ) );
        m_acceptor.bind( endpoint );
        m_acceptor.listen();

        startAccept();
    }

    void run()
    {
        boost::thread_group threadGroup;

        auto const threadBody = boost::bind(
            & asio::io_service::run,
            & m_ioService
        );

        for( unsigned i = 0 ; i < 4 ; ++ i )
        {
            threadGroup.create_thread( threadBody );
        }

        threadGroup.join_all();
    }

private:

    void startAccept()
    {
        m_newConnection.reset( new Connection( m_ioService, m_connectionManager ) );

        m_connectionManager.add( m_newConnection );

        auto const onAccepted = boost::bind(
            & Server::onAccepted,
            this,
            placeholders::error
        );

        m_acceptor.async_accept(
            m_newConnection->socket(),
            onAccepted
        );
    }

    void onAccepted(
        sys::error_code const & errorCode
    )
    {
        if( ! errorCode )
        {
            m_newConnection->start();
        }

        startAccept();
    }

    void onStop()
    {
        m_connectionManager.forEach(
            boost::bind( & Connection::onStop, _1 )
        );

        m_ioService.stop();
    }

private:

    asio::io_service m_ioService;
    asio::ip::tcp::acceptor m_acceptor;
    asio::signal_set m_signals;

    ConnectionPtr m_newConnection;
    ConnectionManager m_connectionManager;
};

int main( int argc, char* argv[] )
{
    Server( argv[1] ).run();
}

<|endoftext|>


<commit_before>#include "stdafx.h"

#include "Type.h"
#include "Skill_Core.h"
#include "Scene.h"
#include "LogicManager.h"
#include "Log.h"
#include "OResultDef.h"
#include "HumanItemLogic.h"
#include "GameTable.h"
#include "ActionDelegator.h"
#include "Obj_Human.h"

namespace Combat_Module
{
    namespace Skill_Module
    {
        using namespace Combat_Module ;
        using namespace Packets ;
        using namespace Action_Module ;
        //class SkillCore_T
        BOOL SkillCore_T::ProcessSkillRequest( Obj_Character& rMe,
                                               SkillID_t nSkillID,
                                               BYTE nLevel,
                                               ObjID_t nTargetID,
                                               WORLD_POS const& rTargetPos,
                                               FLOAT fTargetDir,
                                               GUID_t guidTarget ) const
        {
            __ENTER_FUNCTION

                BOOL bRet = TRUE ;
                SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                Skill_Module::SkillTemplateData_T const* pSkillTemplate = g_SkillTemplateDataMgr.GetInstanceByID( nSkillID ) ;
                if ( NULL == pSkillTemplate )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL ) ;
                    return FALSE ;
                }

                if ( INVALID_ID == nSkillID )
                {
                    rParams.SetErrCode( OR_OK ) ;
                    return TRUE ;
                }
                if ( FALSE == rMe.IsAlive() )
                {
                    rParams.SetErrCode( OR_DIE ) ;
                    return FALSE ;
                }
                //是否当前状态不允许使用这个技能
                if ( FALSE == rMe.Skill_CanUseThisSkillInThisStatus( nSkillID ) )
                {
                    rParams.SetErrCode( OR_LIMIT_USE_SKILL ) ;
                    return FALSE ;
                }
                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() && A_SKILL_FOR_PLAYER == pSkillTemplate->GetClassByUser() )
                {
                    if ( FALSE == rMe.Skill_HaveSkill( nSkillID, nLevel ) && FALSE == rParams.GetIgnoreConditionCheckFlag() )
                    {    //角色不会这个技能
                        rParams.SetErrCode( OR_INVALID_SKILL ) ;
                        return FALSE ;
                    }
                }
                if ( FALSE == rMe.Skill_IsSkillCooldowned( nSkillID ) )
                {
                    rParams.SetErrCode( OR_COOL_DOWNING ) ;
                    return FALSE ;
                }
                if ( FALSE == GetGlobalActionDelegator().CanDoNextAction( rMe ) )
                {
                    rParams.SetErrCode( OR_BUSY ) ;
                    return FALSE ;
                }
                if ( INVALID_ID == pSkillTemplate->GetSkillClass() &&
                    INVALID_ID == pSkillTemplate->GetMenPai() )
                {
                    nLevel = 1 ;
                }
                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                {
                    SkillID_t nSkillInstance = pSkillTemplate->GetSkillInstance( nLevel - 1 ) ;
                    Skill_Module::SkillInstanceData_T const* pSkillInstance = GetSkillInstanceByID( nSkillInstance ) ;
                    Obj_Human& rHuman = ( Obj_Human& )rMe ;
                    if ( NULL == pSkillInstance )
                    {
                        rParams.SetErrCode( OR_INVALID_SKILL ) ;
                        return FALSE ;
                    }
                    if ( rHuman.GetLevel() < pSkillInstance->GetStudyLevel() )
                    {
                        rParams.SetErrCode( OR_NEED_HIGH_LEVEL_XINFA ) ;
                        return FALSE ;
                    }
                }
                rParams.SetActivatedSkill( nSkillID ) ;
                rParams.SetSkillLevel( nLevel ) ;
                rParams.SetTargetObj( nTargetID ) ;
                rParams.SetTargetPosition( rTargetPos ) ;
                rParams.SetTargetDirection( fTargetDir ) ;
                rParams.SetTargetGuid( guidTarget ) ;
                bRet=ActiveSkillNow( rMe ) ;
                if ( FALSE == bRet )
                {
                    g_SkillCore.OnException( rMe ) ;
                }

                return bRet ;

            __LEAVE_FUNCTION

                return FALSE ;
        }

        BOOL SkillCore_T::InstanceSkill( SkillInfo_T& rSkillInfoOut, Obj_Character& rMe, SkillID_t nSkill, BYTE nLevel ) const
        {
            __ENTER_FUNCTION

                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                Skill_Module::SkillTemplateData_T const* pSkillTemplate = GetSkillTemplateByID( nSkill ) ;
                if ( NULL == pSkillTemplate )
                {
                    AssertEx( FALSE,"[ CombatCore_T::InstanceSkill ]: Can't find skill date in the SkillTemplateDateMgr!" ) ;
                    return FALSE ;
                }
                //复制技能模板信息

                rSkillInfoOut = *pSkillTemplate ; // Copy Skill data to output buffer
                //根据技能模板信息取心法信息
                //ID_t nSkillClass = rSkillInfoOut.GetSkillClass() ;
                //INT nXinFaParam = rSkillInfoOut.GetXinFaParam() ;
                //计算心法等级: 没有心法的,心法级别为0
                //INT nXinFaLvl = 0 ;
                //if(Obj::OBJ_TYPE_HUMAN == rMe.GetObjType())
                //{
                //    nXinFaLvl= rMe.Skill_GetXinFaLevel(nXinFaID) ;
                //    if(0<=nXinFaLvl)
                //    {
                //        nXinFaLvl = (nXinFaLvl+nXinFaParam)/10 ;
                //    }
                //    else
                //    {
                //        nXinFaLvl = 0 ;//暂时先这样
                //    }
                //}
                //if(0>nXinFaLvl)
                //{
                //    nXinFaLvl = 0 ;
                //}
                //if(MAX_XINFA_LEVEL_NUM/10 <= nXinFaLvl)
                //{
                //    nXinFaLvl = MAX_XINFA_LEVEL_NUM/10 -1 ;
                //}

                //保存相关的心法等级
                if ( 0 == nLevel || MAX_CHAR_SKILL_LEVEL < nLevel )
                {
                    GUID_t nGUID = 0 ;
                    if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                    {
                        Obj_Human* pTempHuman = ( Obj_Human* )&rMe ;
                        nGUID = pTempHuman->GetGUID() ;
                    }
                    g_pLog->FastSaveLog( LOG_FILE_1, "[ SkillCore_T::InstanceSkill ]: Warning Skill Level outof Range. Skill = %d, Level = %d, GUID = %X",
                        nSkill, nLevel, nGUID ) ;
                    nLevel = 1 ;
                }
                rParams.SetSkillLevel( nLevel ) ;
                //根据心法等级,取实际技能数据
                SkillID_t nSkillInstance = pSkillTemplate->GetSkillInstance( rParams.GetSkillLevel() - 1 ) ;
                Skill_Module::SkillInstanceData_T const* pSkillInstance = GetSkillInstanceByID( nSkillInstance ) ;
                if ( NULL == pSkillInstance )
                {
                    // Warning Skill data don't match the template data, plz check the data table.
                    AssertEx( FALSE,"[SkillCore_T::InstanceSkill]: Can't find skill instance!" ) ;
                    g_pLog->FastSaveLog( LOG_FILE_1, "[SkillCore_T::InstanceSkill]: Warning Skill Data don't match SkillTemplate Data TemplateID = %d, XinFaLvl = %d, SkillDataID = %d.",
                        nSkill, rParams.GetSkillLevel() - 1, nSkillInstance ) ;
                    return FALSE ;
                }
                rSkillInfoOut = *pSkillInstance ; //transfer data from skilldata to runtime skill instance

                return TRUE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }
        BOOL SkillCore_T::ActiveSkillNow( Obj_Character& rMe ) const
        {
            __ENTER_FUNCTION

                SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                if ( FALSE == rMe.IsAlive() || FALSE == rMe.IsActiveObj() )
                {
                    rParams.SetErrCode( OR_DIE ) ;
                    return FALSE ;
                }
                rSkillInfo.Init() ;
                if ( FALSE == InstanceSkill( rSkillInfo, rMe, rParams.GetActivatedSkill(), rParams.GetSkillLevel() ) )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL ) ;
                    rParams.SetErrParam( rParams.GetActivatedSkill() ) ;
                    return FALSE ;
                }
                //refix skill instance
                rMe.RefixSkill( rSkillInfo ) ;
                //perform checking
                INT nLogicID = rSkillInfo.GetLogicID() ;
                SkillLogic_T const* pLogic = g_SkillLogicList.GetLogicById( nLogicID ) ;
                if ( NULL == pLogic )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL) ;
                    rParams.SetErrParam( rParams.GetActivatedSkill() ) ;
                    return FALSE ;
                }
                if ( TRUE == pLogic->IsPassive() )
                {
                    AssertEx( FALSE, "[ SkillCore_T::HeartBeat ]: Found passive Skill!!!Data error!!" ) ;
                    rParams.SetErrCode( OR_ERROR ) ;
                    return FALSE ;
                }
                if ( TRUE == pLogic->CancelSkillEffect( rMe ) )
                {
                    rParams.SetErrCode( OR_OK ) ;
                    return TRUE ;
                }
                //Prefix end
                if ( FALSE == rMe.Skill_IsSkillCooldowned( rParams.GetActivatedSkill() ) &&
                    FALSE == rParams.GetIgnoreConditionCheckFlag() )
                {
                    rParams.SetErrCode( OR_COOL_DOWNING ) ;
                    return FALSE ;
                }
                if ( TRUE == rSkillInfo.GetMustUseWeaponFlag() )
                {
                    if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                    {
                        Obj_Human* pHuman = ( Obj_Human* )&rMe ;
                        Item* pItem = HumanItemLogic::GetEquip( pHuman, HEQUIP_WEAPON ) ;
                        if ( NULL == pItem )
                        {
                            rParams.SetErrCode( OR_NEED_A_WEAPON ) ;
                            return FALSE ;
                        }
                        else if ( TRUE == pItem->IsEmpty() )
                        {
                            rParams.SetErrCode( OR_NEED_A_WEAPON ) ;
                            return FALSE ;
                        }
                    }
                }
                if ( FALSE == rParams.GetIgnoreConditionCheckFlag() )
                {
                    if ( FALSE == pLogic->IsConditionSatisfied( rMe ) )
                    {
                        return FALSE ;
                    }
                    if ( FALSE == pLogic->SpecificOperationOnSkillStart( rMe ) )
                    {
                        return FALSE ;
                    }
                }
                switch ( rSkillInfo.GetSkillType() )
                {
                    case SKILL_INSTANT_LAUNCHING:
                        pLogic->StartLaunching( rMe ) ;
                        break ;
                    case SKILL_NEED_CHARGING:
                        pLogic->StartCharging( rMe ) ;
                        break ;
                    case SKILL_NEED_CHANNELING:
                        pLogic->StartChanneling( rMe ) ;
                        break ;
                    default:
                        AssertEx( FALSE, "[ SkillCore_T::ActiveSkillNow ]: Try to active a un-active skill!" ) ;
                        break ;
                }

                return TRUE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }
        VOID SkillCore_T::OnException( Obj_Character& rMe ) const
        {
            __ENTER_FUNCTION

                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                {
                    SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                    TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                    if ( OR_FAILED( rParams.GetErrCode() ) )
                    {
                        Obj_Human& rHuman = static_cast< Obj_Human& >( rMe ) ;
                        rHuman.SendOperateResultMsg( rParams.GetErrCode() ) ;
                    }
                }
            __LEAVE_FUNCTION
        }
        BOOL Skill_IsSkillInCollection( SkillInfo_T const& rSkillInfo, INT nCollection )
        {
            __ENTER_FUNCTION
                INT nID = INVALID_ID ;
                IDCollection_T const* pCollection = NULL ;
                pCollection = g_IDCollectionMgr.GetInstanceByID( nCollection ) ;
                if ( NULL != pCollection )
                {
                    switch ( pCollection->GetType() )
                    {
                        case IDCollection_T::TYPE_SKILL_ID:
                            nID = rSkillInfo.GetSkillID() ;
                            break ;
                        case IDCollection_T::TYPE_BUFF_ID:
                        case IDCollection_T::TYPE_IMPACT_LOGIC_ID:
                        case IDCollection_T::TYPE_IMPACT_MUTEX_ID:
                        case IDCollection_T::TYPE_DIRECT_IMPACT_ID:
                        case IDCollection_T::TYPE_SKILL_LOGIC_ID:
                        default:
                            nID = INVALID_ID ;
                            break ;
                    }
                    if ( INVALID_ID != nID )
                    {
                        if ( 0 < pCollection->GetCollectionSize() )
                        {
                            return pCollection->IsThisIDInCollection( nID ) ;
                        }
                    }
                }

                return FALSE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }

        INT Skill_GetSkillInfoDescriptorValueByIndex( SkillInfo_T const& rSkillInfo, INT nIndex )
        {
            __ENTER_FUNCTION
                Descriptor_T const* pDescriptor = rSkillInfo.GetDescriptorByIndex(nIndex) ;
                if ( NULL != pDescriptor )
                {
                    return pDescriptor->GetValue() ;
                }

                return 0 ;

            __LEAVE_FUNCTION

                return 0 ;
        }
        ConDepTerm_T const* Skill_GetConDepTermByIndex( SkillInfo_T const& rSkillInfo, INT nIndex )
        {
            __ENTER_FUNCTION

                return rSkillInfo.GetConDepTermByIndex( nIndex ) ;

            __LEAVE_FUNCTION

                return NULL ;
        }
    }
}
Combat_Module::Skill_Module::SkillCore_T g_SkillCore ;
<commit_msg>fix bug<commit_after>#include "stdafx.h"

#include "Type.h"
#include "Skill_Core.h"
#include "Scene.h"
#include "LogicManager.h"
#include "Log.h"
#include "OResultDef.h"
#include "HumanItemLogic.h"
#include "GameTable.h"
#include "ActionDelegator.h"
#include "Obj_Human.h"

namespace Combat_Module
{
    namespace Skill_Module
    {
        using namespace Combat_Module ;
        using namespace Packets ;
        using namespace Action_Module ;
        //class SkillCore_T
        BOOL SkillCore_T::ProcessSkillRequest( Obj_Character& rMe,
                                               SkillID_t nSkillID,
                                               BYTE nLevel,
                                               ObjID_t nTargetID,
                                               WORLD_POS const& rTargetPos,
                                               FLOAT fTargetDir,
                                               GUID_t guidTarget ) const
        {
            __ENTER_FUNCTION

                BOOL bRet = TRUE ;
                SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                Skill_Module::SkillTemplateData_T const* pSkillTemplate = g_SkillTemplateDataMgr.GetInstanceByID( nSkillID ) ;
                if ( NULL == pSkillTemplate )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL ) ;
                    return FALSE ;
                }

                if ( INVALID_ID == nSkillID )
                {
                    rParams.SetErrCode( OR_OK ) ;
                    return TRUE ;
                }
                if ( FALSE == rMe.IsAlive() )
                {
                    rParams.SetErrCode( OR_DIE ) ;
                    return FALSE ;
                }
                //是否当前状态不允许使用这个技能
                if ( FALSE == rMe.Skill_CanUseThisSkillInThisStatus( nSkillID ) )
                {
                    rParams.SetErrCode( OR_LIMIT_USE_SKILL ) ;
                    return FALSE ;
                }
                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() && A_SKILL_FOR_PLAYER == pSkillTemplate->GetClassByUser() )
                {
                    if ( FALSE == rMe.Skill_HaveSkill( nSkillID, nLevel ) && FALSE == rParams.GetIgnoreConditionCheckFlag() )
                    {    //角色不会这个技能
                        rParams.SetErrCode( OR_INVALID_SKILL ) ;
                        return FALSE ;
                    }
                }
                if ( FALSE == rMe.Skill_IsSkillCooldowned( nSkillID ) )
                {
                    rParams.SetErrCode( OR_COOL_DOWNING ) ;
                    return FALSE ;
                }
                if ( FALSE == GetGlobalActionDelegator().CanDoNextAction( rMe ) )
                {
                    rParams.SetErrCode( OR_BUSY ) ;
                    return FALSE ;
                }
                if ( INVALID_ID == pSkillTemplate->GetSkillClass() &&
                    INVALID_ID == pSkillTemplate->GetMenPai() )
                {
                    nLevel = 1 ;
                }
                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                {
                    SkillID_t nSkillInstance = pSkillTemplate->GetSkillInstance( nLevel - 1 ) ;
                    Skill_Module::SkillInstanceData_T const* pSkillInstance = GetSkillInstanceByID( nSkillInstance ) ;
                    Obj_Human& rHuman = ( Obj_Human& )rMe ;
                    if ( NULL == pSkillInstance )
                    {
                        rParams.SetErrCode( OR_INVALID_SKILL ) ;
                        return FALSE ;
                    }
                    if ( rHuman.GetLevel() < pSkillInstance->GetStudyLevel() )
                    {
                        rParams.SetErrCode( OR_NEED_HIGH_LEVEL_XINFA ) ;
                        return FALSE ;
                    }
                }
                rParams.SetActivatedSkill( nSkillID ) ;
                rParams.SetSkillLevel( nLevel ) ;
                rParams.SetTargetObj( nTargetID ) ;
                rParams.SetTargetPosition( rTargetPos ) ;
                rParams.SetTargetDirection( fTargetDir ) ;
                rParams.SetTargetGuid( guidTarget ) ;
                bRet=ActiveSkillNow( rMe ) ;
                if ( FALSE == bRet )
                {
                    g_SkillCore.OnException( rMe ) ;
                }

                return bRet ;

            __LEAVE_FUNCTION

                return FALSE ;
        }

        BOOL SkillCore_T::InstanceSkill( SkillInfo_T& rSkillInfoOut, Obj_Character& rMe, SkillID_t nSkill, BYTE nLevel ) const
        {
            __ENTER_FUNCTION

                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                Skill_Module::SkillTemplateData_T const* pSkillTemplate = GetSkillTemplateByID( nSkill ) ;
                if ( NULL == pSkillTemplate )
                {
                    AssertEx( FALSE,"[ CombatCore_T::InstanceSkill ]: Can't find skill date in the SkillTemplateDateMgr!" ) ;
                    return FALSE ;
                }
                //复制技能模板信息

                rSkillInfoOut = *pSkillTemplate ; // Copy Skill data to output buffer
                //根据技能模板信息取心法信息
                //ID_t nSkillClass = rSkillInfoOut.GetSkillClass() ;
                //INT nXinFaParam = rSkillInfoOut.GetXinFaParam() ;
                //计算心法等级: 没有心法的,心法级别为0
                //INT nXinFaLvl = 0 ;
                //if(Obj::OBJ_TYPE_HUMAN == rMe.GetObjType())
                //{
                //    nXinFaLvl= rMe.Skill_GetXinFaLevel(nXinFaID) ;
                //    if(0<=nXinFaLvl)
                //    {
                //        nXinFaLvl = (nXinFaLvl+nXinFaParam)/10 ;
                //    }
                //    else
                //    {
                //        nXinFaLvl = 0 ;//暂时先这样
                //    }
                //}
                //if(0>nXinFaLvl)
                //{
                //    nXinFaLvl = 0 ;
                //}
                //if(MAX_XINFA_LEVEL_NUM/10 <= nXinFaLvl)
                //{
                //    nXinFaLvl = MAX_XINFA_LEVEL_NUM/10 -1 ;
                //}

                //保存相关的心法等级
                if ( 0 == nLevel || MAX_CHAR_SKILL_LEVEL < nLevel )
                {
                    GUID_t nGUID = 0 ;
                    if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                    {
                        Obj_Human* pTempHuman = ( Obj_Human* )&rMe ;
                        nGUID = pTempHuman->GetGUID() ;
                    }
                    g_pLog->FastSaveLog( LOG_FILE_1, "[ SkillCore_T::InstanceSkill ]: Warning Skill Level outof Range. Skill = %d, Level = %d, GUID = %X",
                        nSkill, nLevel, nGUID ) ;
                    nLevel = 1 ;
                }
                rParams.SetSkillLevel( nLevel ) ;
                //根据心法等级,取实际技能数据
                SkillID_t nSkillInstance = pSkillTemplate->GetSkillInstance( rParams.GetSkillLevel() - 1 ) ;
                Skill_Module::SkillInstanceData_T const* pSkillInstance = GetSkillInstanceByID( nSkillInstance ) ;
                if ( NULL == pSkillInstance )
                {
                    // Warning Skill data don't match the template data, plz check the data table.
                    AssertEx( FALSE,"[ SkillCore_T::InstanceSkill ]: Can't find skill instance!" ) ;
                    g_pLog->FastSaveLog( LOG_FILE_1, "[ SkillCore_T::InstanceSkill ]: Warning Skill Data don't match SkillTemplate Data TemplateID = %d, XinFaLvl = %d, SkillDataID = %d.",
                        nSkill, rParams.GetSkillLevel() - 1, nSkillInstance ) ;

                    return FALSE ;
                }
                rSkillInfoOut = *pSkillInstance ; //transfer data from skilldata to runtime skill instance

                return TRUE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }
        BOOL SkillCore_T::ActiveSkillNow( Obj_Character& rMe ) const
        {
            __ENTER_FUNCTION

                SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                if ( FALSE == rMe.IsAlive() || FALSE == rMe.IsActiveObj() )
                {
                    rParams.SetErrCode( OR_DIE ) ;
                    return FALSE ;
                }
                rSkillInfo.Init() ;
                if ( FALSE == InstanceSkill( rSkillInfo, rMe, rParams.GetActivatedSkill(), rParams.GetSkillLevel() ) )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL ) ;
                    rParams.SetErrParam( rParams.GetActivatedSkill() ) ;
                    return FALSE ;
                }
                //refix skill instance
                rMe.RefixSkill( rSkillInfo ) ;
                //perform checking
                INT nLogicID = rSkillInfo.GetLogicID() ;
                SkillLogic_T const* pLogic = g_SkillLogicList.GetLogicById( nLogicID ) ;
                if ( NULL == pLogic )
                {
                    rParams.SetErrCode( OR_INVALID_SKILL) ;
                    rParams.SetErrParam( rParams.GetActivatedSkill() ) ;
                    return FALSE ;
                }
                if ( TRUE == pLogic->IsPassive() )
                {
                    AssertEx( FALSE, "[ SkillCore_T::HeartBeat ]: Found passive Skill!!!Data error!!" ) ;
                    rParams.SetErrCode( OR_ERROR ) ;
                    return FALSE ;
                }
                if ( TRUE == pLogic->CancelSkillEffect( rMe ) )
                {
                    rParams.SetErrCode( OR_OK ) ;
                    return TRUE ;
                }
                //Prefix end
                if ( FALSE == rMe.Skill_IsSkillCooldowned( rParams.GetActivatedSkill() ) &&
                    FALSE == rParams.GetIgnoreConditionCheckFlag() )
                {
                    rParams.SetErrCode( OR_COOL_DOWNING ) ;
                    return FALSE ;
                }
                if ( TRUE == rSkillInfo.GetMustUseWeaponFlag() )
                {
                    if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                    {
                        Obj_Human* pHuman = ( Obj_Human* )&rMe ;
                        Item* pItem = HumanItemLogic::GetEquip( pHuman, HEQUIP_WEAPON ) ;
                        if ( NULL == pItem )
                        {
                            rParams.SetErrCode( OR_NEED_A_WEAPON ) ;
                            return FALSE ;
                        }
                        else if ( TRUE == pItem->IsEmpty() )
                        {
                            rParams.SetErrCode( OR_NEED_A_WEAPON ) ;
                            return FALSE ;
                        }
                    }
                }
                if ( FALSE == rParams.GetIgnoreConditionCheckFlag() )
                {
                    if ( FALSE == pLogic->IsConditionSatisfied( rMe ) )
                    {
                        return FALSE ;
                    }
                    if ( FALSE == pLogic->SpecificOperationOnSkillStart( rMe ) )
                    {
                        return FALSE ;
                    }
                }
                switch ( rSkillInfo.GetSkillType() )
                {
                    case SKILL_INSTANT_LAUNCHING:
                        pLogic->StartLaunching( rMe ) ;
                        break ;
                    case SKILL_NEED_CHARGING:
                        pLogic->StartCharging( rMe ) ;
                        break ;
                    case SKILL_NEED_CHANNELING:
                        pLogic->StartChanneling( rMe ) ;
                        break ;
                    default:
                        AssertEx( FALSE, "[ SkillCore_T::ActiveSkillNow ]: Try to active a un-active skill!" ) ;
                        break ;
                }

                return TRUE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }
        VOID SkillCore_T::OnException( Obj_Character& rMe ) const
        {
            __ENTER_FUNCTION

                if ( Obj::OBJ_TYPE_HUMAN == rMe.GetObjType() )
                {
                    SkillInfo_T& rSkillInfo = rMe.GetSkillInfo() ;
                    TargetingAndDepletingParams_T& rParams = rMe.GetTargetingAndDepletingParams() ;
                    if ( OR_FAILED( rParams.GetErrCode() ) )
                    {
                        Obj_Human& rHuman = static_cast< Obj_Human& >( rMe ) ;
                        rHuman.SendOperateResultMsg( rParams.GetErrCode() ) ;
                    }
                }
            __LEAVE_FUNCTION
        }
        BOOL Skill_IsSkillInCollection( SkillInfo_T const& rSkillInfo, INT nCollection )
        {
            __ENTER_FUNCTION
                INT nID = INVALID_ID ;
                IDCollection_T const* pCollection = NULL ;
                pCollection = g_IDCollectionMgr.GetInstanceByID( nCollection ) ;
                if ( NULL != pCollection )
                {
                    switch ( pCollection->GetType() )
                    {
                        case IDCollection_T::TYPE_SKILL_ID:
                            nID = rSkillInfo.GetSkillID() ;
                            break ;
                        case IDCollection_T::TYPE_BUFF_ID:
                        case IDCollection_T::TYPE_IMPACT_LOGIC_ID:
                        case IDCollection_T::TYPE_IMPACT_MUTEX_ID:
                        case IDCollection_T::TYPE_DIRECT_IMPACT_ID:
                        case IDCollection_T::TYPE_SKILL_LOGIC_ID:
                        default:
                            nID = INVALID_ID ;
                            break ;
                    }
                    if ( INVALID_ID != nID )
                    {
                        if ( 0 < pCollection->GetCollectionSize() )
                        {
                            return pCollection->IsThisIDInCollection( nID ) ;
                        }
                    }
                }

                return FALSE ;

            __LEAVE_FUNCTION

                return FALSE ;
        }

        INT Skill_GetSkillInfoDescriptorValueByIndex( SkillInfo_T const& rSkillInfo, INT nIndex )
        {
            __ENTER_FUNCTION
                Descriptor_T const* pDescriptor = rSkillInfo.GetDescriptorByIndex(nIndex) ;
                if ( NULL != pDescriptor )
                {
                    return pDescriptor->GetValue() ;
                }

                return 0 ;

            __LEAVE_FUNCTION

                return 0 ;
        }
        ConDepTerm_T const* Skill_GetConDepTermByIndex( SkillInfo_T const& rSkillInfo, INT nIndex )
        {
            __ENTER_FUNCTION

                return rSkillInfo.GetConDepTermByIndex( nIndex ) ;

            __LEAVE_FUNCTION

                return NULL ;
        }
    }
}
Combat_Module::Skill_Module::SkillCore_T g_SkillCore ;
<|endoftext|>


<commit_before>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */

#include "ruby_module.h"
#include <cstring>
#include <iostream>
#include <sstream>

namespace kroll
{

	RubyEvaluator::RubyEvaluator() :
		next_id(0)
	{
	}

	RubyEvaluator::~RubyEvaluator()
	{
	}

	static SharedKObject global_object;
	static VALUE m_missing(int argc, VALUE* argv, VALUE self)
	{
		if (global_object.isNull())
			return Qnil;

		// store the method name and arguments in separate variables
		VALUE method_name, args;
		rb_scan_args(argc, argv, "1*", &method_name, &args);

		const char* name = rb_id2name(SYM2ID(method_name));

		// This is an assignment
		if (name[strlen(name) - 1] == '=')
		{
			char* chopped_name = strdup(name);
			chopped_name[strlen(name) - 1] = '\0';
			VALUE rval = rb_ary_entry(args, 0);
			SharedValue val = RubyUtils::ToKrollValue(rval);
			global_object->Set(chopped_name, val);
			return rval;
		}

		// This is an access
		SharedValue v = global_object->Get(name);
		if (v->IsMethod()) // It's a method, call it
		{
			try
			{
				ValueList kargs;
				for (int i = 0; i < RARRAY(args)->len; i++)
				{
					VALUE rarg = rb_ary_entry(args, i);
					SharedValue arg = RubyUtils::ToKrollValue(rarg);
					kargs.push_back(arg);
				}
				v = v->ToMethod()->Call(kargs);
			}
			catch (ValueException& e)
			{
				VALUE rex = RubyUtils::ToRubyValue(e.GetValue());
				rb_raise(rex, "Kroll exception");
			}
		}

		VALUE rv = RubyUtils::ToRubyValue(v);
		return rv;
	}

	std::string RubyEvaluator::GetContextId(SharedKObject global)
	{
		int id = 0;
		SharedValue idv = global->Get("__ruby_module_id__");
		if (idv->IsUndefined())
		{
			id = this->next_id++;
			global->Set("__ruby_module_id__", Value::NewInt(id));
		}
		else
		{
			id = idv->ToInt();
		}
		return std::string("$windowProc") + KList::IntToChars(id);
	}

	VALUE RubyEvaluator::GetContext(SharedKObject global)
	{
		std::string id = this->GetContextId(global);
		VALUE ctx = rb_gv_get(id.c_str());
		if (ctx == Qnil)
		{
			VALUE ctx_class = rb_define_class("KrollRubyContext", rb_cObject);
			rb_define_method(ctx_class, "method_missing", VALUEFUNC(m_missing), -1);
			ctx = rb_obj_alloc(ctx_class);
			rb_gv_set(id.c_str(), ctx);
		}
		return ctx;
	}

	VALUE reval_do_call(VALUE args)
	{
		VALUE ctx = rb_ary_shift(args);
		VALUE code = rb_ary_shift(args);
		return rb_funcall(ctx, rb_intern("instance_eval"), 1, code);
	}
	VALUE reval_handle_exception(VALUE args)
	{
		ValueException e = RubyUtils::GetException(1);
		SharedString ss = e.DisplayString();
		std::cout << "An error occured while parsing "
		          << "Ruby on the page: " << std::endl;

		std::cout << *ss << std::endl;
		return Qnil;
	}
	SharedValue RubyEvaluator::Call(const ValueList& args)
	{
		try
		{
			if (args.size() != 3
				|| !args.at(1)->IsString()
				|| !args.at(2)->IsObject())
				return Value::Undefined;
			const char* code = args.at(1)->ToString();
			global_object = args.at(2)->ToObject();
			VALUE ctx = this->GetContext(global_object);

			// Push new methods into the window global scope.
			VALUE rargs = rb_ary_new();
			rb_ary_push(rargs, ctx);
			rb_ary_push(rargs, rb_str_new2(code));
			VALUE ret_val = rb_rescue(
				VALUEFUNC(reval_do_call), rargs,
				VALUEFUNC(reval_handle_exception), rargs);

			RubyEvaluator::ContextToGlobal(ctx, global_object);
			return RubyUtils::ToKrollValue(ret_val);

		}
		catch (ValueException& e)
		{
			// While Ruby exceptions will be caputured by
			// rb_rescue, exceptions from the Kroll layer
			// will have to be caught here.
			SharedString ss = e.DisplayString();
			std::cout << "An error occured while parsing "
			          << "Ruby on the page: " << std::endl;

			std::cout << *ss << std::endl;
			return Value::Undefined;
		}
	}

	void RubyEvaluator::ContextToGlobal(VALUE ctx, SharedKObject o)
	{
		if (global_object.isNull())
			return;

		// Next copy all methods over -- they override variables
		VALUE methods = rb_funcall(ctx, rb_intern("singleton_methods"), 0);
		for (long i = 0; i < RARRAY(methods)->len; i++)
		{
			VALUE meth_symbol = rb_ary_entry(methods, i);
			const char* meth_name = STR2CSTR(meth_symbol);

			// Skip our special method_missing method
			if (strcmp(meth_name, "method_missing") == 0)
				continue;

			VALUE rmeth = rb_funcall(ctx, rb_intern("method"), 1, meth_symbol);
			SharedValue meth = Value::NewMethod(new KRubyMethod(rmeth));
			o->Set(meth_name, meth);
		}
	}

	void RubyEvaluator::Set(const char *name, SharedValue value)
	{
	}

	SharedValue RubyEvaluator::Get(const char *name)
	{
		return Value::Undefined;
	}

	SharedStringList RubyEvaluator::GetPropertyNames()
	{
		return SharedStringList();
	}
}
<commit_msg>Fixed build for OS X<commit_after>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */

#include "ruby_module.h"
#include <cstring>
#include <iostream>
#include <sstream>

namespace kroll
{

	RubyEvaluator::RubyEvaluator() :
		next_id(0)
	{
	}

	RubyEvaluator::~RubyEvaluator()
	{
	}

	static SharedKObject global_object;
	static VALUE m_missing(int argc, VALUE* argv, VALUE self)
	{
		if (global_object.isNull())
			return Qnil;

		// store the method name and arguments in separate variables
		VALUE method_name, args;
		rb_scan_args(argc, argv, "1*", &method_name, &args);

		const char* name = rb_id2name(SYM2ID(method_name));

		// This is an assignment
		if (name[strlen(name) - 1] == '=')
		{
			char* chopped_name = strdup(name);
			chopped_name[strlen(name) - 1] = '\0';
			VALUE rval = rb_ary_entry(args, 0);
			SharedValue val = RubyUtils::ToKrollValue(rval);
			global_object->Set(chopped_name, val);
			return rval;
		}

		// This is an access
		SharedValue v = global_object->Get(name);
		if (v->IsMethod()) // It's a method, call it
		{
			try
			{
				ValueList kargs;
				for (int i = 0; i < RARRAY(args)->len; i++)
				{
					VALUE rarg = rb_ary_entry(args, i);
					SharedValue arg = RubyUtils::ToKrollValue(rarg);
					kargs.push_back(arg);
				}
				v = v->ToMethod()->Call(kargs);
			}
			catch (ValueException& e)
			{
				VALUE rex = RubyUtils::ToRubyValue(e.GetValue());
				rb_raise(rex, "Kroll exception");
			}
		}

		VALUE rv = RubyUtils::ToRubyValue(v);
		return rv;
	}

	std::string RubyEvaluator::GetContextId(SharedKObject global)
	{
		int cid = 0;
		SharedValue idv = global->Get("__ruby_module_id__");
		if (idv->IsUndefined())
		{
			cid = this->next_id++;
			global->Set("__ruby_module_id__", Value::NewInt(cid));
		}
		else
		{
			cid = idv->ToInt();
		}
		return std::string("$windowProc") + KList::IntToChars(cid);
	}

	VALUE RubyEvaluator::GetContext(SharedKObject global)
	{
		std::string id = this->GetContextId(global);
		VALUE ctx = rb_gv_get(id.c_str());
		if (ctx == Qnil)
		{
			VALUE ctx_class = rb_define_class("KrollRubyContext", rb_cObject);
			rb_define_method(ctx_class, "method_missing", VALUEFUNC(m_missing), -1);
			ctx = rb_obj_alloc(ctx_class);
			rb_gv_set(id.c_str(), ctx);
		}
		return ctx;
	}

	VALUE reval_do_call(VALUE args)
	{
		VALUE ctx = rb_ary_shift(args);
		VALUE code = rb_ary_shift(args);
		return rb_funcall(ctx, rb_intern("instance_eval"), 1, code);
	}
	VALUE reval_handle_exception(VALUE args)
	{
		ValueException e = RubyUtils::GetException(1);
		SharedString ss = e.DisplayString();
		std::cout << "An error occured while parsing "
		          << "Ruby on the page: " << std::endl;

		std::cout << *ss << std::endl;
		return Qnil;
	}
	SharedValue RubyEvaluator::Call(const ValueList& args)
	{
		try
		{
			if (args.size() != 3
				|| !args.at(1)->IsString()
				|| !args.at(2)->IsObject())
				return Value::Undefined;
			const char* code = args.at(1)->ToString();
			global_object = args.at(2)->ToObject();
			VALUE ctx = this->GetContext(global_object);

			// Push new methods into the window global scope.
			VALUE rargs = rb_ary_new();
			rb_ary_push(rargs, ctx);
			rb_ary_push(rargs, rb_str_new2(code));
			VALUE ret_val = rb_rescue(
				VALUEFUNC(reval_do_call), rargs,
				VALUEFUNC(reval_handle_exception), rargs);

			RubyEvaluator::ContextToGlobal(ctx, global_object);
			return RubyUtils::ToKrollValue(ret_val);

		}
		catch (ValueException& e)
		{
			// While Ruby exceptions will be caputured by
			// rb_rescue, exceptions from the Kroll layer
			// will have to be caught here.
			SharedString ss = e.DisplayString();
			std::cout << "An error occured while parsing "
			          << "Ruby on the page: " << std::endl;

			std::cout << *ss << std::endl;
			return Value::Undefined;
		}
	}

	void RubyEvaluator::ContextToGlobal(VALUE ctx, SharedKObject o)
	{
		if (global_object.isNull())
			return;

		// Next copy all methods over -- they override variables
		VALUE methods = rb_funcall(ctx, rb_intern("singleton_methods"), 0);
		for (long i = 0; i < RARRAY(methods)->len; i++)
		{
			VALUE meth_symbol = rb_ary_entry(methods, i);
			const char* meth_name = STR2CSTR(meth_symbol);

			// Skip our special method_missing method
			if (strcmp(meth_name, "method_missing") == 0)
				continue;

			VALUE rmeth = rb_funcall(ctx, rb_intern("method"), 1, meth_symbol);
			SharedValue meth = Value::NewMethod(new KRubyMethod(rmeth));
			o->Set(meth_name, meth);
		}
	}

	void RubyEvaluator::Set(const char *name, SharedValue value)
	{
	}

	SharedValue RubyEvaluator::Get(const char *name)
	{
		return Value::Undefined;
	}

	SharedStringList RubyEvaluator::GetPropertyNames()
	{
		return SharedStringList();
	}
}
<|endoftext|>


<commit_before>#include "connect_dialog.h"
#include "ui_connect_dialog.h"
#include "memcacheclient.h"
#include <QLabel>
#include <QSpacerItem>
#include <QRegExp>
#include <QHBoxLayout>
#include <QLineEdit>

ConnectDialog::ConnectDialog(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::ConnectDialog),
    mc(new MemcacheClient())
{
    m_ui->setupUi(this);
    connect(m_ui->addserver_button, SIGNAL(clicked()), this, SLOT(addServerClicked()));
    connect(m_ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(memcache_connect()));
    m_ui->scrolling_contents->setLayout(new QVBoxLayout);
    m_ui->scrolling_contents->layout()->setContentsMargins(0, 0, 0, 0);

    connect(mc, SIGNAL(hasNewStats()), parent, SLOT(displayStats()));
}

void ConnectDialog::addServerClicked()
{
    this->addHostEntry();
}

void ConnectDialog::memcache_connect()
{
    mc->mc_connect(&servers);
}

void ConnectDialog::retab()
{
    QWidget *last;
    QWidget::setTabOrder(m_ui->buttonBox, m_ui->addserver_button);
    last = m_ui->addserver_button;
    for (QVector<HostEntry *>::iterator i = servers.begin(); i != servers.end(); i++) {
        QWidget::setTabOrder(last, (*i)->host);
        QWidget::setTabOrder((*i)->host, (*i)->port);
        last = (*i)->port;
    }
    QWidget::setTabOrder(last, m_ui->buttonBox);
}

void ConnectDialog::addHostEntry()
{
    QHBoxLayout *server_info_horiz_layout;
    QLabel *host_label;
    QSpacerItem *host_port_spacer;
    QLabel *port_label;
    QWidget *host_widget = new QWidget();
    HostEntry *host;

    m_ui->scrolling_contents->layout()->addWidget(host_widget);
    host = new HostEntry();
    server_info_horiz_layout = new QHBoxLayout(host_widget);
    server_info_horiz_layout->setObjectName(QString::fromUtf8("server_info_horiz_layout %1").arg(servers.count()));
    server_info_horiz_layout->setContentsMargins(0, 0, 0, 0);
    host_label = new QLabel(host_widget);
    host_label->setObjectName(QString::fromUtf8("host_label %1").arg(servers.count()));
    host_label->setText(QString::fromUtf8("Host %1: ").arg(servers.count()+1));

    server_info_horiz_layout->addWidget(host_label);

    host->host = new QLineEdit(host_widget);
    host->host->setObjectName(QString::fromUtf8("host_edit %1").arg(servers.count()));

    server_info_horiz_layout->addWidget(host->host);

    host_port_spacer = new QSpacerItem(28, 20, QSizePolicy::Minimum, QSizePolicy::Minimum);

    server_info_horiz_layout->addItem(host_port_spacer);

    port_label = new QLabel(host_widget);
    port_label->setObjectName(QString::fromUtf8("port_label %1").arg(servers.count()));
    port_label->setText(QString::fromUtf8("Port %1: ").arg(servers.count()+1));

    server_info_horiz_layout->addWidget(port_label);

    host->port = new QLineEdit(host_widget);
    host->port->setObjectName(QString::fromUtf8("port_edit %1").arg(servers.count()));
    host->port->setEnabled(true);
    QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
    sizePolicy1.setHorizontalStretch(0);
    sizePolicy1.setVerticalStretch(0);
    sizePolicy1.setHeightForWidth(host->port->sizePolicy().hasHeightForWidth());
    host->port->setSizePolicy(sizePolicy1);
    host->port->setMaximumSize(QSize(70, 16777215));
    host->port->setMaxLength(5);

    host->port->setValidator(new QRegExpValidator(HostEntry::port_regex, this));

    server_info_horiz_layout->addWidget(host->port);
    host->host->setFocus();
    servers.append(host);

    retab();
}

ConnectDialog::~ConnectDialog()
{
    HostEntry *h;

    foreach (h, servers) {
        delete h;
    }
    delete m_ui;
}

void ConnectDialog::changeEvent(QEvent *e)
{
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
<commit_msg>retabbed<commit_after>#include "connect_dialog.h"
#include "ui_connect_dialog.h"
#include "memcacheclient.h"
#include <QLabel>
#include <QSpacerItem>
#include <QRegExp>
#include <QHBoxLayout>
#include <QLineEdit>

ConnectDialog::ConnectDialog(QWidget *parent) :
	QDialog(parent),
	m_ui(new Ui::ConnectDialog),
	mc(new MemcacheClient())
{
	m_ui->setupUi(this);
	connect(m_ui->addserver_button, SIGNAL(clicked()), this, SLOT(addServerClicked()));
	connect(m_ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(memcache_connect()));
	m_ui->scrolling_contents->setLayout(new QVBoxLayout);
	m_ui->scrolling_contents->layout()->setContentsMargins(0, 0, 0, 0);
	m_ui->scrolling_contents->layout()->setSizeConstraint(QLayout::SetMinimumSize);

	connect(mc, SIGNAL(hasNewStats()), parent, SLOT(displayStats()));
}

void ConnectDialog::addServerClicked()
{
	this->addHostEntry();
}

void ConnectDialog::memcache_connect()
{
	mc->mc_connect(&servers);
}

void ConnectDialog::retab()
{
	QWidget *last;
	QWidget::setTabOrder(m_ui->buttonBox, m_ui->addserver_button);
	last = m_ui->addserver_button;
	for (QVector<HostEntry *>::iterator i = servers.begin(); i != servers.end(); i++) {
		QWidget::setTabOrder(last, (*i)->host);
		QWidget::setTabOrder((*i)->host, (*i)->port);
		last = (*i)->port;
	}
	QWidget::setTabOrder(last, m_ui->buttonBox);
}

void ConnectDialog::addHostEntry()
{
	QHBoxLayout *server_info_horiz_layout;
	QLabel *host_label;
	QSpacerItem *host_port_spacer;
	QLabel *port_label;
	QWidget *host_widget = new QWidget();
	HostEntry *host;

	m_ui->scrolling_contents->layout()->addWidget(host_widget);
	host = new HostEntry();
	server_info_horiz_layout = new QHBoxLayout(host_widget);
	server_info_horiz_layout->setObjectName(QString::fromUtf8("server_info_horiz_layout %1").arg(servers.count()));
	server_info_horiz_layout->setContentsMargins(0, 0, 0, 0);
	host_label = new QLabel(host_widget);
	host_label->setObjectName(QString::fromUtf8("host_label %1").arg(servers.count()));
	host_label->setText(QString::fromUtf8("Host %1: ").arg(servers.count()+1));

	server_info_horiz_layout->addWidget(host_label);

	host->host = new QLineEdit(host_widget);
	host->host->setObjectName(QString::fromUtf8("host_edit %1").arg(servers.count()));

	server_info_horiz_layout->addWidget(host->host);

	host_port_spacer = new QSpacerItem(28, 20, QSizePolicy::Minimum, QSizePolicy::Minimum);

	server_info_horiz_layout->addItem(host_port_spacer);

	port_label = new QLabel(host_widget);
	port_label->setObjectName(QString::fromUtf8("port_label %1").arg(servers.count()));
	port_label->setText(QString::fromUtf8("Port %1: ").arg(servers.count()+1));

	server_info_horiz_layout->addWidget(port_label);

	host->port = new QLineEdit(host_widget);
	host->port->setObjectName(QString::fromUtf8("port_edit %1").arg(servers.count()));
	host->port->setEnabled(true);
	QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
	sizePolicy1.setHorizontalStretch(0);
	sizePolicy1.setVerticalStretch(0);
	sizePolicy1.setHeightForWidth(host->port->sizePolicy().hasHeightForWidth());
	host->port->setSizePolicy(sizePolicy1);
	host->port->setMaximumSize(QSize(70, 16777215));
	host->port->setMaxLength(5);

	host->port->setValidator(new QRegExpValidator(HostEntry::port_regex, this));

	server_info_horiz_layout->addWidget(host->port);
	host->host->setFocus();
	servers.append(host);

	retab();
}

ConnectDialog::~ConnectDialog()
{
	HostEntry *h;

	foreach (h, servers) {
		delete h;
	}
	delete m_ui;
}

void ConnectDialog::changeEvent(QEvent *e)
{
	switch (e->type()) {
	case QEvent::LanguageChange:
		m_ui->retranslateUi(this);
		break;
	default:
		break;
	}
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <string>
#include <iostream>
#include <stdio.h>
#include "wcl/network/TCPServer.h"

using namespace wcl;

void usage() {
    printf("NAME\n\tpcontrol - Network command controller for NEC projectors\n\n"
            "SYNOPSIS\n\t pcontrol [options] -a <address> -p <port>\n\n"
            "When no options, address or port are specified, the defaults of:\n"
            "127.0.0.1:7142\n"
            "are used.\n\n"
            "Options:\n"
            "\t-h\n\t--help\n"
            "\t\tDisplay usage options.\n"
            "\t-a\n\t--address\n"
            "\t\tThe address of the projector to communicate with.\n"
            "\t-p\n\t--port\n"
            "\t\tThe port to communicate on.\n"
    );
}

int main(int argc, char** argv) {

    std::string address = "";
    unsigned int port = 0;
    if ( argc >= 2 ) {

        for ( int counter = 0; counter <= argc ; ++counter ) {

            if ( strcmp ( argv[counter], "--help" ) == 0 || strcmp ( argv[counter], "-h" ) == 0 ) {
                usage();
                return 1;
            }

            if ( strcmp ( argv[counter], "--address" ) == 0 || strcmp (argv[counter], "-a" ) == 0 ) {
                if ( counter+1 <= argc ) {
                    //TODO double check that argc[counter+1] is a valid IP address.
                    address=argv[counter+1];
                    counter++;
                } else {
                    usage();
                    return 1;
                }
            }

            if ( strcmp ( argv[counter], "--port" ) == 0 || strcmp (argv[counter], "-p" ) == 0 ) {
                if ( counter+1 <= argc ) {
                    char *pEnd;
                    port = strtol ( argv[counter+1], &pEnd, 10 );
                    counter++;
                } else {
                    usage();
                    return 1;
                }
            }
        }
   } else {
       usage();
       return -1;
    }

    unsigned char buffer[4096];

    TCPSocket projector(address,port);

    // We want to write: 02H 00H 00H 00H 00H 00H 02H
    // to the projector. Converting this to decimal.
    unsigned char toSend[] = { (unsigned char)2, 0, 0, 0, 0, (unsigned char)2 };
    projector.write((char*) toSend, 6);

    projector.read((char *)buffer, 4096);
    std::cout << "Projector responded: " << (int)buffer[0] << "," << buffer[1] << std::endl;
    projector.close();
    return 0;

}
<commit_msg>Added ON / OFF commands, removed segfaults.<commit_after>#include <cstdlib>
#include <string>
#include <iostream>
#include <stdio.h>
#include "wcl/network/TCPServer.h"

using namespace wcl;

void usage() {
    printf("NAME\n\tpcontrol - Network command controller for NEC projectors\n\n"
            "SYNOPSIS\n\t pcontrol [options] -a <address> -p <port> [COMMAND]\n\n"
            "When no options, address or port are specified, the defaults of:\n"
            "127.0.0.1:7142\n"
            "are used.\n\n"
            "Options:\n"
            "\t-h\n\t--help\n"
            "\t\tDisplay usage options.\n"
            "\t-a\n\t--address\n"
            "\t\tThe address of the projector to communicate with.\n"
            "\t-p\n\t--port\n"
            "\t\tThe port to communicate on.\n"
            "COMMANDS\n[COMMAND] can be any single value of the following:"
            "\t--ON\nPower ON\n"
            "\t--OFF\nPower OFF\n"
          );
}

int main(int argc, char** argv) {

    std::string address = "127.0.0.1";
    unsigned int port = 7142;
    if ( argc >= 2 ) {

        for ( int counter = 0; counter < argc ; ++counter ) {

            if ( strcmp ( argv[counter], "--help" ) == 0 || strcmp ( argv[counter], "-h" ) == 0 ) {
                usage();
                return 1;
            }

            if ( strcmp ( argv[counter], "--address" ) == 0 || strcmp (argv[counter], "-a" ) == 0 ) {
                if ( counter+1 <= argc ) {
                    //TODO double check that argc[counter+1] is a valid IP address.
                    address=argv[counter+1];
                    counter++;
                } else {
                    usage();
                    return 1;
                }
            }

            if ( strcmp ( argv[counter], "--port" ) == 0 || strcmp (argv[counter], "-p" ) == 0 ) {
                if ( counter+1 <= argc ) {
                    char *pEnd;
                    port = strtol ( argv[counter+1], &pEnd, 10 );
                    counter++;
                } else {
                    usage();
                    return 1;
                }
            }
        }

        try {

            TCPSocket projector(address,port);
            // Get the last value, which should be our command, and use it for our command to run.
            if ( strcmp (argv[argc-1], "--ON" ) == 0 ) {
                // 02H 00H 00H 00H 00H 00H 02H
                unsigned char toSend[] = { (unsigned char)2, 0, 0, 0, 0, (unsigned char)2 };
                projector.write((char*) toSend, 6);
            }
            if ( strcmp (argv[argc-1], "--OFF" ) == 0 ) {

                // 02H 01H 00H 00H 00H 03H
                unsigned char toSend[] = { (unsigned char)2, (unsigned char)1, 0, 0, 0, (unsigned char)3 };
                projector.write((char*) toSend, 6);
            }
            // Read the response from the projector.
            unsigned char buffer[4096];
            projector.read((char *)buffer, 4096);
            std::cout << "Projector responded: " << (int)buffer[0] << "," << buffer[1] << std::endl;
            projector.close();
        } catch (SocketException* e) {
            fprintf( stderr, "%s", e->what() );
        }

        }

        return 0;
    }
<|endoftext|>