void Connection::close() { TRACE_ENTERLEAVE(); disable(); onClose(); }
Request::Request( Connection& connection ) : m_body( NULL ), m_connection( connection ) { TRACE_ENTERLEAVE( ); m_timestamp = sys::General::getMillisecondTimestamp( ); }
void Listener::listen( const Base& base) { TRACE_ENTERLEAVE(); General::setSocketNonBlocking( m_socket ); if ( m_socket.bind( m_port ) == sys::Socket::StatusFailed ) { TRACE_ERROR( "cannot bind to socket, error %d", sys::General::getLastError() ); throw BindError; } if ( m_socket.listen() == sys::Socket::StatusFailed ) { throw ListenError; } m_listenerEvent = event_new( base, m_socket.s(), EV_READ | EV_PERSIST, onAcceptStatic, this ); if ( !m_listenerEvent ) { throw GeneralError; } event_add( m_listenerEvent, NULL ); }
void LuaState::loadlibs() const { TRACE_ENTERLEAVE(); luaL_openlibs( m_lua ); }
void LuaState::execute( const std::string& script ) const { TRACE_ENTERLEAVE(); TRACE( "%s", script.c_str() ); // // debug.traceback function // lua_getglobal( m_lua, "debug"); lua_getfield( m_lua, -1, "traceback"); luaL_loadstring( m_lua, script.c_str() ); int res = lua_pcall( m_lua, 0, LUA_MULTRET, -2 ); if ( res ) { std::string error = lua_tostring( m_lua, -1 ); lua_pop( m_lua, 3 ); TRACE_ERROR( "%s", error.c_str() ); throw std::runtime_error( error ); } // // pop result or error from the stack // lua_pop( m_lua, 2 ); }
void Server::onAccept( ) { TRACE_ENTERLEAVE( ); // // accept new connection and add it to connection thread // sys::Socket* socket = m_socket.accept( ); if ( !socket ) { TRACE_ERROR( "accept failed, error %d", sys::Socket::getLastError( ) ); return; } // // get first connection thread // ConnectionThread* thread; { sys::LockEnterLeave lock( m_lock ); if ( m_connectionThreads.size() < m_connectionThreadCount ) { thread = new ConnectionThread( *this ); } else { thread = m_connectionThreads.front( ); m_connectionThreads.pop_front( ); } } // // create new connection and assign it to connection thread. it mantains referencre count and will delete itself when no longer referenced // Connection* connection = newConnection( *thread, socket ); if ( m_storeConnections ) { thread->add( connection ); } // // enable events processing on this connection // connection->enable( ); // // add connection thread to back // { sys::LockEnterLeave lock( m_lock ); m_connectionThreads.push_back( thread ); } }
void Connection::onWrite( ) { TRACE_ENTERLEAVE( ); if ( !m_initialized ) { // // set timeouts if needed // if ( m_thread.server( ).getConnectionReadTimeout( ) > 0 ) { setReadTimeout( m_thread.server( ).getConnectionReadTimeout( ) ); } if ( m_thread.server( ).getConnectionWriteTimeout( ) > 0 ) { setWriteTimeout( m_thread.server( ).getConnectionWriteTimeout( ) ); } } if ( m_close ) { disable( ); onClose( ); } }
void LuaState::setGlobal( const std::string& name, unsigned int value ) { TRACE_ENTERLEAVE(); getGlobalTable(); lua_pushinteger( m_lua, value ); lua_setfield( m_lua, -2, name.c_str() ); lua_pop( m_lua, 1 ); }
Server::~Server( ) { TRACE_ENTERLEAVE( ); stop( ); libevent::General::shutdown( ); }
void Server::ConnectionThread::add( Connection* connection ) { TRACE_ENTERLEAVE( ); sys::LockEnterLeave lock( m_lock ); m_connections[ connection->id( ) ] = connection; }
LuaState& LuaState::luaFromThread( const sys::Thread& thread, unsigned int threadId ) { TRACE_ENTERLEAVE(); LuaState& lua = *( ( LuaState* ) thread.data() ); lua.reload( threadId ); return lua; }
Server::Server( unsigned int port, EventHandler& handler ) : libevent::Listener( port ), m_connectionThreadCount( 10 ), m_connectionReadTimeout( 0 ), m_connectionWriteTimeout( 0 ), m_poolThreadCount( 25 ), m_eventHandler( handler ), m_timerThread( NULL ), m_storeConnections( false ) { TRACE_ENTERLEAVE( ); libevent::General::initThreads( ); }
void Server::TimerThread::onTimer( unsigned int interval, void* data ) { TRACE_ENTERLEAVE( ); // // call back // m_server.eventHandler().onTimer( interval, data ); }
Server::ConnectionThread::ConnectionThread( Server& server ) : m_server( server ) { TRACE_ENTERLEAVE( ); m_stackSize = 1024 * 1024 * 2; start( ); }
void Server::ConnectionThread::routine( ) { TRACE_ENTERLEAVE( ); // // start event loop // m_base.start( ); }
Request::~Request( ) { TRACE_ENTERLEAVE( ); if ( m_body ) { delete[] m_body; } }
void LuaState::create() { if ( m_lua ) { return; } TRACE_ENTERLEAVE(); // // create new lua state // m_lua = luaL_newstate( ); // // // // register api functons // // static const luaL_Reg functions[] = { {"serverAddTimer", serverAddTimer }, {"serverCreate", serverCreate }, {"serverConnectionSendData", serverConnectionSendData }, {"serverConnectionGetAddress", serverConnectionGetAddress}, {"serverConnectionGetId", serverConnectionGetId}, {"serverSendTo", serverSendTo}, {"clientCreate", clientCreate }, {"clientConnect", clientConnect }, {"clientAddTimer", clientAddTimer }, {"clientConnectionSendData", clientConnectionSendData }, {"clientConnectionClose", clientConnectionClose }, {"getpid", getpid }, {"processorCount", processorCount}, {"httpRequestGetUrl", httpRequestGetUrl}, {"httpRequestGetHeaders", httpRequestGetHeaders}, {"httpRequestGetBody", httpRequestGetBody}, {"httpRequestGetMethod", httpRequestGetMethod}, {"httpRequestGetAddress", httpRequestGetAddress}, {"httpResponseSetBody", httpResponseSetBody}, {"httpResponseSetStatus", httpResponseSetStatus}, {"httpResponseSetHeaders", httpResponseSetHeaders}, {"httpResponseAddHeader", httpResponseAddHeader}, {"getVersion", getVersion}, {"dictionaryGet", dictionaryGet}, {"dictionarySet", dictionarySet}, {"dictionaryRemove", dictionaryRemove}, {"dictionaryGetKeys", dictionaryGetKeys}, {"processStart", processStart}, {"processWrite", processWrite}, {NULL, NULL } }; luaL_register( m_lua, "__api", functions ); loadlibs(); }
void Base::stop( ) const { TRACE_ENTERLEAVE( ); if ( m_base ) { event_base_loopexit( m_base, NULL ); } }
void Connection::setReadTimeout( unsigned int value ) { TRACE_ENTERLEAVE(); timeval timeout; timeout.tv_sec = ( long ) value; timeout.tv_usec = 0; bufferevent_set_timeouts( m_handle, &timeout, NULL ); }
Server::ConnectionThread::~ConnectionThread( ) { TRACE_ENTERLEAVE( ); m_base.stop(); while ( !m_connections.empty( ) ) { remove( m_connections.begin( )->second, true ); } }
void Server::onTaskProcess( sys::ThreadPool::Task* task, sys::ThreadPool::Worker& thread ) { TRACE_ENTERLEAVE( ); Task* serverTask = ( Task* ) task; // // invoke callback // eventHandler().onRequest( *serverTask->request, *serverTask->response, thread ); delete serverTask; }
void Server::ConnectionThread::broadcast( const Message& message ) { TRACE_ENTERLEAVE(); sys::LockEnterLeave lock( m_lock ); TRACE( "%d", m_connections.size() ); for ( std::map< intptr_t, Connection* >::iterator i = m_connections.begin(); i != m_connections.end(); i++ ) { i->second->write( message.contents, message.length ); } }
LuaState::LuaState( const std::string& filename, const ScriptArguments* arguments ) : m_lua( NULL ), m_close( true ), m_filename( filename ) { TRACE_ENTERLEAVE(); if ( arguments ) { m_arguments = *arguments; } create(); }
void Connection::writeFormat( const char* format, ... ) { TRACE_ENTERLEAVE(); va_list args; va_start(args, format); vprintf( format, args ); int written = evbuffer_add_vprintf( m_output, format, args ); va_end(args); }
Connection::~Connection( ) { TRACE_ENTERLEAVE( ); m_thread.remove( this ); if ( m_request ) { delete m_request; } }
void LuaState::destroy() { TRACE_ENTERLEAVE(); if ( m_lua && m_close ) { // // close lua state if it was created by this instance // lua_close( m_lua ); m_lua = NULL; } }
void Server::addTimer( unsigned int interval, void* data ) { TRACE_ENTERLEAVE( ); // // create timer thread // if ( !m_timerThread ) { m_timerThread = new TimerThread( *this ); } m_timerThread->add( interval, data ); }
void LuaState::addPaths( const char* name ) const { TRACE_ENTERLEAVE(); // // modify package search path // lua_getglobal( m_lua, "package" ); lua_getfield( m_lua, -1, name ); if ( lua_isnil( m_lua, -1 ) ) { TRACE( "package.%s is not set in lua", name ); lua_pop( m_lua, 1 ); return; } std::string path = lua_tostring( m_lua, -1 ); std::string separator = "/"; #ifdef WIN32 separator = "\\"; #endif std::string initName = path.substr( path.find_last_of( separator ) ); const char* ext = strstr( initName.c_str(), "." ); for ( std::list< std::string >::const_iterator i = Leda::instance()->paths().begin( ); i != Leda::instance()->paths().end( ); i++ ) { path.append( ";" ); path.append( *i ); path.append( separator ); path.append( "?" ); path.append( ext ); path.append( ";" ); path.append( *i ); path.append( separator ); path.append( "?" ); path.append( initName ); } TRACE( "%s: %s", name, path.c_str( ) ); lua_pop( m_lua, 1 ); lua_pushstring( m_lua, path.c_str( ) ); lua_setfield( m_lua, -2, name ); lua_pop( m_lua, 1 ); }
void Connection::onError( short error ) { TRACE_ENTERLEAVE(); if ( error & BEV_EVENT_EOF || error & BEV_EVENT_ERROR) { close(); return; } if ( error & BEV_EVENT_TIMEOUT ) { close(); } }
void Server::broadcast( const Message& message ) { TRACE_ENTERLEAVE(); if ( !m_storeConnections || m_connectionThreads.empty() ) { return; } sys::LockEnterLeave lock( m_lock ); for ( std::list< ConnectionThread* >::iterator i = m_connectionThreads.begin( ); i != m_connectionThreads.end( ); i++ ) { ( *i )->broadcast( message ); } }