o
    i$                     @   sV   d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
 G dd dZdS )z
Control Socket Server

Runs in the arbiter process and accepts commands via Unix socket.
Uses asyncio in a background thread to handle client connections.
    N)CommandHandlers)ControlProtocolmake_responsemake_error_responsec                   @   s   e Zd ZdZd ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dedefddZdedefddZdedefddZdedefddZdedefddZdS )!ControlSocketServerz
    Control socket server running in arbiter process.

    The server runs an asyncio event loop in a background thread,
    accepting connections and dispatching commands to handlers.
      c                 C   s8   || _ || _|| _t|| _d| _d| _d| _d| _dS )z
        Initialize control socket server.

        Args:
            arbiter: The Gunicorn arbiter instance
            socket_path: Path for the Unix socket
            socket_mode: Permission mode for socket (default 0o600)
        NF)	arbitersocket_pathsocket_moder   handlers_server_loop_thread_running)selfr   r	   r
    r   G/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/ctl/server.py__init__!   s   	

zControlSocketServer.__init__c                 C   s0   | j rdS d| _ tj| jdd| _| j  dS )z:Start server in background thread with asyncio event loop.NT)targetdaemon)r   	threadingThread	_run_loopr   startr   r   r   r   r   4   s
   zControlSocketServer.startc                 C   s~   | j sdS d| _ | jr| jr| j| j | jr"| jjdd d| _tj	| j
r=z	t| j
 W dS  ty<   Y dS w dS )zStop server and cleanup socket.NFg       @timeout)r   r   r   call_soon_threadsafe	_shutdownr   joinospathexistsr	   unlinkOSErrorr   r   r   r   stop=   s   zControlSocketServer.stopc                 C   s   | j r
| j   dS dS )z0Shutdown server (called from event loop thread).N)r   closer   r   r   r   r   S   s   zControlSocketServer._shutdownc              
   C   sb   z
t |   W dS  ty0 } z| jjr%| jjd| W Y d}~dS W Y d}~dS d}~ww )z0Run the asyncio event loop in background thread.zControl server error: %sN)asynciorun_serve	Exceptionr   logerror)r   er   r   r   r   X   s   zControlSocketServer._run_loopc                    s@  t  | _tj| jrt| j t j| j	| jdI dH | _
t| j| j | jjr5| jjd| j zPz'| j
4 I dH  | j
 I dH  W d  I dH  n1 I dH sWw   Y  W n
 t jyg   Y nw W tj| jrz	t| j W dS  ty   Y dS w dS tj| jrzt| j W w  ty   Y w w w )zMain async server loop.)r!   NzControl socket listening at %s)r'   get_running_loopr   r    r!   r"   r	   r#   start_unix_server_handle_clientr   chmodr
   r   r+   infoserve_foreverCancelledErrorr$   r   r   r   r   r)   `   sF   

(zControlSocketServer._servec                    s,  z}zD| j rEztjt|ddI dH }W n tjy   Y n& tjy(   Y n ty0   Y nw | |I dH }t	||I dH  | j sW n tyd } z| j
jrZ| j
jd| W Y d}~nd}~ww W |  z
| I dH  W dS  ty~   Y dS w |  z	| I dH  W w  ty   Y w w )z
        Handle client connection.

        Args:
            reader: asyncio StreamReader
            writer: asyncio StreamWriter
        g     r@r   NzControl client error: %s)r   r'   wait_forr   read_message_asyncTimeoutErrorIncompleteReadErrorr*   	_dispatchwrite_message_asyncr   r+   debugr&   wait_closed)r   readerwritermessageresponser-   r   r   r   r0      sJ   z"ControlSocketServer._handle_clientr?   returnc              
      s   | dd}| dd }| dg }|st|dS z$t|}|r.|dd |D  |s6t|dW S | |}t||W S  tyZ } zt|d	| W  Y d
}~S d
}~w t	y~ } z| j
jrl| j
jd t|d| W  Y d
}~S d
}~ww )z
        Dispatch command to appropriate handler.

        Args:
            message: Request message dict

        Returns:
            Response dictionary
        idr   command argsEmpty commandc                 s   s    | ]}t |V  qd S )N)str).0ar   r   r   	<genexpr>   s    z0ControlSocketServer._dispatch.<locals>.<genexpr>zInvalid argument: NzCommand errorzCommand failed: )getstripr   shlexsplitextend_execute_commandr   
ValueErrorr*   r   r+   	exception)r   r?   
request_idrC   rE   partsresultr-   r   r   r   r9      s.   



zControlSocketServer._dispatchrT   c                 C   s   |st d|d  }|dd }|dkr| |S |dkr$| |S |dkr-| |S |dkr6| j S |d	kr?| j S |d
krQ|rI|d nd}| j|S |dkrZ| j	 S t d| )z
        Execute a parsed command.

        Args:
            parts: Command parts (e.g., ["show", "workers"])

        Returns:
            Handler result dictionary
        rF   r      NshowworkerdirtyreloadreopenshutdowngracefulhelpzUnknown command: )
rQ   lower_handle_show_handle_worker_handle_dirtyr   rZ   r[   r\   r^   )r   rT   cmdrestmoder   r   r   rP      s(   






z$ControlSocketServer._execute_commandrE   c                 C   s   |st d|d  }|dkr| j S |dkr| j S |dkr'| j S |dkr0| j S |dkr9| j S |dkrB| j S t d	| )
zHandle 'show' commands.z>Missing show target (all|workers|dirty|config|stats|listeners)r   allworkersrY   configstats	listenerszUnknown show target: )	rQ   r_   r   show_allshow_workers
show_dirtyshow_config
show_statsshow_listeners)r   rE   r   r   r   r   r`      s    





z ControlSocketServer._handle_showc                 C   s   |st d|d  }|dd }|dkr&|rt|d nd}| j|S |dkr:|r2t|d nd}| j|S |dkrP|sDt dt|d }| j|S t d	| )
zHandle 'worker' commands.z'Missing worker action (add|remove|kill)r   rV   NaddremovekillzMissing PID for worker killzUnknown worker action: )rQ   r_   intr   
worker_addworker_removeworker_kill)r   rE   actionaction_argscountpidr   r   r   ra     s    z"ControlSocketServer._handle_workerc                 C   s   |st d|d  }|dd }|dkr&|rt|d nd}| j|S |dkr:|r2t|d nd}| j|S t d| )zHandle 'dirty' commands.z!Missing dirty action (add|remove)r   rV   Nrq   rr   zUnknown dirty action: )rQ   r_   rt   r   	dirty_adddirty_remove)r   rE   rx   ry   rz   r   r   r   rb     s   z!ControlSocketServer._handle_dirtyN)r   )__name__
__module____qualname____doc__r   r   r%   r   r   r)   r0   dictr9   listrP   r`   ra   rb   r   r   r   r   r      s    
	!)%#r   )r   r'   r    rM   r   gunicorn.ctl.handlersr   gunicorn.ctl.protocolr   r   r   r   r   r   r   r   <module>   s   