<s> import time <EOL> from twisted . web import resource <EOL> from twisted . web . server import NOT_DONE_YET <EOL> from config import Config <EOL> from connection import Connection <EOL> from client_channel import ClientChannel , ExistingChannelError , ExistingClientError <EOL> from held_connection_channel import HeldConnectionChannel <EOL> class CometServer ( object , resource . Resource ) : <EOL> isLeaf = True <EOL> current_message_id = property ( lambda self : self . _current_message_id ) <EOL> config = property ( lambda self : self . _config ) <EOL> def __init__ ( self , config ) : <EOL> resource . Resource . __init__ ( self ) <EOL> self . _config = config <EOL> self . client_channel = ClientChannel ( config ) <EOL> self . held_connection_channel = HeldConnectionChannel ( ) <EOL> self . _current_message_id = int ( time . time ( ) * config . max_messages_per_second ) <EOL> self . _current_connection_id = <NUM_LIT:0> <EOL> self . comet_server = self <EOL> def render_POST ( self , request ) : <EOL> connection_id = self . pop_connection_id ( ) <EOL> connection = Connection ( self , request , connection_id ) <EOL> try : <EOL> format = connection . get_format ( self . config . clients_uri_path ) <EOL> except ValueError , e : <EOL> return connection . error ( - <NUM_LIT:1> , str ( e ) ) <EOL> if format : <EOL> return self . register_client ( connection ) <EOL> try : <EOL> ( channel_id , format ) = connection . get_channel_id_and_format ( ) <EOL> except ValueError , e : <EOL> return connection . error ( - <NUM_LIT:1> , str ( e ) ) <EOL> if not channel_id : <EOL> if not "<STR_LIT>" in request . args : <EOL> return connection . error ( - <NUM_LIT:1> , "<STR_LIT>" ) <EOL> ( channel_id , ) = request . args [ "<STR_LIT>" ] <EOL> use_sessions = False <EOL> if "<STR_LIT>" in request . args : <EOL> use_sessions = bool ( request . args [ "<STR_LIT>" ] [ <NUM_LIT:0> ] ) <EOL> if "<STR_LIT>" in request . args : <EOL> try : <EOL> max_messages = int ( request . args [ "<STR_LIT>" ] [ <NUM_LIT:0> ] ) <EOL> if max_messages < <NUM_LIT:1> : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> except ValueError : <EOL> return connection . error ( - <NUM_LIT:1> , "<STR_LIT>" ) <EOL> else : <EOL> max_messages = self . config . default_max_messages_per_channel <EOL> return self . register_channel_id ( connection = connection , <EOL> channel_id = channel_id , max_messages = max_messages , <EOL> use_sessions = use_sessions ) <EOL> try : <EOL> channel = self . client_channel . channel_id_to_channel ( channel_id ) <EOL> except KeyError : <EOL> return connection . error ( - <NUM_LIT:2> , "<STR_LIT>" ) <EOL> if not "<STR_LIT:content>" in request . args : <EOL> return connection . error ( - <NUM_LIT:1> , "<STR_LIT>" ) <EOL> ( content , ) = request . args [ "<STR_LIT:content>" ] <EOL> message_id = self . pop_message_id ( ) <EOL> channel . push_message_content ( message_id , content ) <EOL> held_connections = self . held_connection_channel . channel_id_to_held_connections ( channel_id ) <EOL> new_messages = channel . messages_since ( self . current_message_id - <NUM_LIT:1> ) <EOL> channels_messages = { channel_id : new_messages } <EOL> for held_connection in held_connections : <EOL> result = held_connection . success ( { "<STR_LIT>" : channels_messages , <EOL> "<STR_LIT>" : held_connection . meta [ "<STR_LIT>" ] , <EOL> "<STR_LIT>" : self . current_message_id } ) <EOL> held_connection . send_cache_headers ( ) <EOL> held_connection . delayed_reply ( result ) <EOL> self . held_connection_channel . remove_held_connection_id ( held_connection . id ) <EOL> return connection . success ( { "<STR_LIT>" : message_id } ) <EOL> def render_GET ( self , request ) : <EOL> connection_id = self . pop_connection_id ( ) <EOL> connection = Connection ( self , request , connection_id ) <EOL> if self . config . enable_status : <EOL> try : <EOL> format = connection . get_format ( self . config . status_uri_path ) <EOL> except ValueError , e : <EOL> return connection . error ( - <NUM_LIT:1> , str ( e ) ) <EOL> if format : <EOL> return self . show_status ( connection ) <EOL> try : <EOL> ( channels_ids_s , format ) = connection . get_channel_id_and_format ( ) <EOL> except ValueError , e : <EOL> return connection . error ( - <NUM_LIT:1> , str ( e ) ) <EOL> if not channels_ids_s : <EOL> return connection . error ( - <NUM_LIT:2> , "<STR_LIT>" ) <EOL> channels_ids = channels_ids_s . split ( self . config . channels_sep ) <EOL> if not channels_ids : <EOL> return connection . error ( - <NUM_LIT:2> , "<STR_LIT>" ) <EOL> return self . handle_channels_read ( connection , channels_ids ) <EOL> def render_DELETE ( self , request ) : <EOL> connection_id = self . pop_connection_id ( ) <EOL> connection = Connection ( self , request , connection_id ) <EOL> try : <EOL> ( channel_id , format ) = connection . get_channel_id_and_format ( ) <EOL> except ValueError , e : <EOL> return connection . error ( - <NUM_LIT:1> , str ( e ) ) <EOL> removed = self . remove_channel_id ( channel_id ) <EOL> return connection . success ( { "<STR_LIT>" : channel_id , <EOL> "<STR_LIT>" : removed } , <EOL> return_code = int ( removed ) + <NUM_LIT:1> ) <EOL> def pop_message_id ( self ) : <EOL> self . _current_message_id = self . _current_message_id + <NUM_LIT:1> <EOL> return self . current_message_id <EOL> def pop_connection_id ( self ) : <EOL> self . _current_connection_id = self . _current_connection_id + <NUM_LIT:1> <EOL> return self . _current_connection_id <EOL> def handle_channels_read ( self , connection , channels_ids ) : <EOL> request = connection . request <EOL> since = <NUM_LIT:0> <EOL> if "<STR_LIT>" in request . args : <EOL> try : <EOL> since = int ( request . args [ "<STR_LIT>" ] [ <NUM_LIT:0> ] ) <EOL> except ValueError : <EOL> pass <EOL> since = min ( since , self . _current_message_id ) <EOL> if not "<STR_LIT>" in request . args : <EOL> client_id = None <EOL> client = None <EOL> else : <EOL> ( client_id , ) = request . args [ "<STR_LIT>" ] <EOL> if not client_id : <EOL> return connection . error ( - <NUM_LIT:1> , "<STR_LIT>" ) <EOL> try : <EOL> client = self . client_channel . client_id_to_client ( client_id ) <EOL> except KeyError : <EOL> return connection . error ( - <NUM_LIT:3> , "<STR_LIT>" ) <EOL> client . ping ( ) <EOL> authorized_channels_ids = list ( ) <EOL> for channel_id in channels_ids : <EOL> try : <EOL> channel = self . client_channel . channel_id_to_channel ( channel_id ) <EOL> except KeyError : <EOL> continue <EOL> if channel . use_sessions != False and client_id == None : <EOL> continue <EOL> authorized_channels_ids . append ( channel_id ) <EOL> if client_id : <EOL> self . client_channel . register_client_id_for_channel_id ( client_id , channel_id ) <EOL> channels_messages = dict ( ) <EOL> empty = True <EOL> for channel_id in authorized_channels_ids : <EOL> try : <EOL> channel = self . client_channel . channel_id_to_channel ( channel_id ) <EOL> except KeyError : <EOL> continue <EOL> new_messages = channel . messages_since ( since ) <EOL> channels_messages [ channel_id ] = new_messages <EOL> if new_messages : <EOL> empty = False <EOL> if not empty : <EOL> connection . send_cache_headers ( ) <EOL> return connection . success ( { "<STR_LIT>" : channels_messages , <EOL> "<STR_LIT>" : since , <EOL> "<STR_LIT>" : self . current_message_id } ) <EOL> connection . meta = { "<STR_LIT>" : since } <EOL> self . held_connection_channel . register_held_connection_for_channels_ids ( connection , authorized_channels_ids ) <EOL> request . notifyFinish ( ) . addBoth ( self . connection_finished , connection . id ) <EOL> return NOT_DONE_YET <EOL> def connection_finished ( self , failure , connection_id ) : <EOL> self . held_connection_channel . remove_held_connection_id ( connection_id ) <EOL> def register_channel_id ( self , connection , channel_id , max_messages , use_sessions ) : <EOL> try : <EOL> self . client_channel . register_channel_id ( channel_id , max_messages , use_sessions ) <EOL> except ExistingChannelError , e : <EOL> return connection . error ( - <NUM_LIT:2> , str ( e ) ) <EOL> return connection . success ( { "<STR_LIT>" : channel_id } ) <EOL> def remove_channel_id ( self , channel_id ) : <EOL> try : <EOL> self . client_channel . channel_id_to_channel ( channel_id ) <EOL> except KeyError : <EOL> return False <EOL> self . client_channel . remove_channel_id ( channel_id ) <EOL> return True <EOL> def client_timeout_cb ( self , client , teardown_cb ) : <EOL> empty_channels_ids = self . client_channel . remove_client_id_and_return_empty_channels_ids ( client . id ) <EOL> teardown_cb ( ) <EOL> def register_client ( self , connection ) : <EOL> request = connection . request <EOL> if not "<STR_LIT>" in request . args : <EOL> return connection . error ( - <NUM_LIT:1> , "<STR_LIT>" ) <EOL> ( client_id , ) = request . args [ "<STR_LIT>" ] <EOL> try : <EOL> self . client_channel . register_client_id ( self , client_id , self . client_timeout_cb ) <EOL> except ExistingClientError , e : <EOL> return connection . error ( - <NUM_LIT:2> , str ( e ) ) <EOL> return connection . success ( { "<STR_LIT>" : client_id } ) <EOL> def show_status ( self , connection ) : <EOL> channels = self . client_channel . channel_id_to_clients_ids <EOL> clients = self . client_channel . client_id_to_channel_id_to_channels_ids <EOL> held_connections_count = self . held_connection_channel . held_connections_count <EOL> status = { "<STR_LIT>" : channels . keys ( ) , "<STR_LIT>" : clients . keys ( ) , <EOL> "<STR_LIT>" : held_connections_count } <EOL> return connection . success ( { "<STR_LIT:status>" : status } ) </s>
