a
    kÄ#dç2  ã                   @   s8  d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ dd
lmZmZmZmZmZmZmZmZ ddlmZ ddlmZ ddlm Z! ddlm"Z# ddl$m%Z& ddgZ'G dd„ de(ƒZ)G dd„ dƒZ*G dd„ de(ƒZ+e+ƒ Z,G dd„ de#ƒZ-G dd„ deƒZ.e.Z/dS )z
Python-CAN CANSocket Wrapper.
é    N)Úreduce)Úadd)Úconf)ÚSuperSocket)ÚCAN)ÚPacket)Úwarning)ÚListÚTypeÚTupleÚDictÚAnyÚOptionalÚcastÚorb)Úqueue)ÚMessage)ÚCanError)ÚBusABC)ÚBusÚ	CANSocketÚPythonCANSocketc                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚPriotizedCanMessagean  Helper object for comparison of CAN messages. If the timestamps of two
    messages are equal, the counter value of a priority counter, is used
    for comparison. It's only important that this priority counter always
    get increased for every CAN message in the receive heapq. This compensates
    a low resolution of `time.time()` on some operating systems.
    c                 C   s   || _ || _d S ©N)ÚmsgÚcount)Úselfr   r   © r   úY/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/cansocket_python_can.pyÚ__init__,   s    zPriotizedCanMessage.__init__c                 C   s*   t |tƒsdS | jj|jjko(| j|jkS ©NF©Ú
isinstancer   r   Ú	timestampr   ©r   Úotherr   r   r   Ú__eq__1   s
    

ÿzPriotizedCanMessage.__eq__c                 C   s:   t |tƒsdS | jj|jjk p8| jj|jjko8| j|jk S r    r!   r$   r   r   r   Ú__lt__8   s    

þzPriotizedCanMessage.__lt__c                 C   s   | |kp| |k S r   r   r$   r   r   r   Ú__le__@   s    zPriotizedCanMessage.__le__c                 C   s
   | |k S r   r   r$   r   r   r   Ú__gt__D   s    zPriotizedCanMessage.__gt__c                 C   s
   | |k  S r   r   r$   r   r   r   Ú__ge__H   s    zPriotizedCanMessage.__ge__N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r&   r'   r(   r)   r*   r   r   r   r   r   %   s   r   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚSocketMapperzbInternal Helper class to map a python-can bus object to
    a list of SocketWrapper instances
    c                 C   s   || _ || _dS )z÷Initializes the SocketMapper helper class

        :param bus: A python-can Bus object
        :param sockets: A list of SocketWrapper objects which want to receive
                        messages from the provided python-can Bus object.
        N)ÚbusÚsockets)r   r0   r1   r   r   r   r   Q   s    zSocketMapper.__init__c              
   C   sŒ   d}zP| j jdd�}|du r"W dS | jD ](}| |¡r(|d7 }|j t||ƒ¡ q(W q  ty„ } ztd| ƒ W Y d}~q d}~0 0 q dS )zÉMultiplexer function. Tries to receive from its python-can bus
        object. If a message is received, this message gets forwarded to
        all receive queues of the SocketWrapper objects.
        r   )ÚtimeoutNé   z%[MUX] python-can exception caught: %s)	r0   Úrecvr1   Ú_matches_filtersÚrx_queueÚputr   Ú	Exceptionr   )r   Z
prio_countr   ÚsockÚer   r   r   Úmux\   s    

zSocketMapper.muxN)r+   r,   r-   r.   r   r;   r   r   r   r   r/   M   s   r/   c                   @   s:   e Zd ZdZdd„ Zddd„Zdd„ Zd	d
„ Zdd„ ZdS )Ú_SocketsPoolzCHelper class to organize all SocketWrapper and SocketMapper objectsc                 C   s   t ƒ | _t ¡ | _d S r   )ÚdictÚpoolÚ	threadingÚLockÚ
pool_mutex©r   r   r   r   r   r   s    z_SocketsPool.__init__r   c                 C   sÜ   |j du rtdƒ‚| j�° zP| j|j  }|j |¡ |jD ],}||krHq:| |¡sTq:|j 	t
||ƒ¡ q:W nN tyŠ   td|j  ƒ Y n0 ty¸ } ztd| ƒ W Y d}~n
d}~0 0 W d  ƒ n1 sÎ0    Y  dS )aX  Internal send function.

        A given SocketWrapper wants to send a CAN message. The python-can
        Bus object is obtained from an internal pool of SocketMapper objects.
        The given message is sent on the python-can Bus object and also
        inserted into the message queues of all other SocketWrapper objects
        which are connected to the same python-can bus object
        by the SocketMapper.

        :param sender: SocketWrapper which initiated a send of a CAN message
        :param msg: CAN message to be sent
        :param prio: Priority count for internal heapq
        Nú'SocketWrapper.name should never be Nonez![SND] Socket %s not found in poolz%[SND] python-can exception caught: %s)ÚnameÚ	TypeErrorrA   r>   r0   Úsendr1   r5   r6   r7   r   ÚKeyErrorr   Úcan_CanError)r   Zsenderr   ÚprioZmapperr9   r:   r   r   r   Úinternal_sendw   s     


z_SocketsPool.internal_sendc                 C   sB   | j �( | j ¡ D ]}| ¡  qW d  ƒ n1 s40    Y  dS )z]This calls the mux() function of all SocketMapper
        objects in this SocketPool
        N)rA   r>   Úvaluesr;   )r   Útr   r   r   Úmultiplex_rx_packets™   s    z!_SocketsPool.multiplex_rx_packetsc                 O   sÂ   t | dd¡ƒd t | dd¡ƒ }| j�„ || jv rz| j| }|j |¡ dd„ |jD ƒ}|rr|j tt	|ƒ¡ ||_
n&t|i |¤Ž}||_
t||gƒ| j|< W d  ƒ n1 s´0    Y  dS )	aÙ  Registers a SocketWrapper object. Every SocketWrapper describes to
        a python-can bus object. This python-can bus object can only exist
        once. In case this object already exists in this SocketsPool, organized
        by a SocketMapper object, the new SocketWrapper is inserted in the
        list of subscribers of the SocketMapper. Otherwise a new python-can
        Bus object is created from the provided args and kwargs and inserted,
        encapsulated in a SocketMapper, into this SocketsPool.

        :param socket: SocketWrapper object which needs to be registered.
        :param args: Arguments for the python-can Bus object
        :param kwargs: Keyword arguments for the python-can Bus object
        ZbustypeZunknown_bustypeÚ_ZchannelZunknown_channelc                 S   s   g | ]}|j d ur|j ‘qS r   )Úfilters©Ú.0Úsr   r   r   Ú
<listcomp>¶   s   
ÿz)_SocketsPool.register.<locals>.<listcomp>N)ÚstrÚgetrA   r>   r1   Úappendr0   Zset_filtersr   r   rD   Úcan_Busr/   )r   ÚsocketÚargsÚkwargsÚkrL   rO   r0   r   r   r   Úregister¢   s    ÿ

z_SocketsPool.registerc              	   C   s”   |j du rtdƒ‚| j�h z6| j|j  }|j |¡ |jsN|j ¡  | j|j = W n  typ   t	d|j  ƒ Y n0 W d  ƒ n1 s†0    Y  dS )zèUnregisters a SocketWrapper from its subscription to a SocketMapper.

        If a SocketMapper doesn't have any subscribers, the python-can Bus
        get shutdown.

        :param socket: SocketWrapper to be unregistered
        NrC   z#Socket %s already removed from pool)
rD   rE   rA   r>   r1   Úremover0   ÚshutdownrG   r   )r   rX   rL   r   r   r   Ú
unregisterÀ   s    	

z_SocketsPool.unregisterN)r   )	r+   r,   r-   r.   r   rJ   rM   r\   r_   r   r   r   r   r<   p   s   
"	r<   c                       s:   e Zd ZdZ‡ fdd„Zdd„ Zddd„Zd	d
„ Z‡  ZS )ÚSocketWrapperz6Helper class to wrap a python-can Bus object as socketc                    sH   t t| ƒj|i |¤Ž t ¡ | _d| _d| _tj	| g|¢R i |¤Ž dS )aH  Initializes a new python-can based socket, described by the provided
        arguments and keyword arguments. This SocketWrapper gets automatically
        registered in the SocketsPool.

        :param args: Arguments for the python-can Bus object
        :param kwargs: Keyword arguments for the python-can Bus object
        Nr   )
Úsuperr`   r   r   ÚPriorityQueuer6   rD   Úprio_counterÚSocketsPoolr\   )r   rY   rZ   ©Ú	__class__r   r   r   Ý   s
    	
zSocketWrapper.__init__c                 C   s@   t  ¡  z| jjd|d�}|jdfW S  tjy:   Y dS 0 dS )ap  Internal blocking receive method,
        following the ``can_BusABC`` interface of python-can.

        This triggers the multiplex function of the general SocketsPool.

        :param timeout: Time to wait for a packet
        :return: Returns a tuple of either a can_Message or None and a bool to
                 indicate if filtering was already applied.
        T)Úblockr2   )NTN)rd   rM   r6   rU   r   r   ÚEmpty)r   r2   Úpmr   r   r   Ú_recv_internalì   s    zSocketWrapper._recv_internalNc                 C   s"   |  j d7  _ t | || j ¡ dS )z˜Send function, following the ``can_BusABC`` interface of python-can.

        :param msg: Message to be sent.
        :param timeout: Not used.
        r3   N)rc   rd   rJ   )r   r   r2   r   r   r   rF   þ   s    zSocketWrapper.sendc                 C   s   t  | ¡ dS )zYShutdown function, following the ``can_BusABC`` interface of
        python-can.
        N)rd   r_   rB   r   r   r   r^     s    zSocketWrapper.shutdown)N)	r+   r,   r-   r.   r   rj   rF   r^   Ú__classcell__r   r   re   r   r`   Ú   s
   

r`   c                       sT   e Zd ZdZdZdZdd„ Zddd„Zd	d
„ Ze	e
jfdd„ƒZ‡ fdd„Z‡  ZS )r   al  Initializes a python-can bus object as Scapy PythonCANSocket.

    All provided keyword arguments, except *basecls* are forwarded to
    the python-can can_Bus init function. For further details on python-can
    check: https://python-can.readthedocs.io/

    Example:
        >>> socket = PythonCANSocket(bustype='socketcan', channel='vcan0', bitrate=250000)
    zIread/write packets at a given CAN interface using a python-can bus objectTc                 K   s0   t ttt  | dt¡ƒ| _tf i |¤Ž| _d S )NÚbasecls)	r   r   r
   r   Úpopr   rl   r`   Ú	can_iface)r   rZ   r   r   r   r     s    zPythonCANSocket.__init__éÿÿ  c                 C   s¢   | j  ¡ }|jd> |jd> B |jd> B |jB }tjd d rTt 	dt 
d|¡¡d }|jd	> |jd
> B |jd> B |jd> B }t 
d||¡t|jƒ }| j||jfS )z0Returns a tuple containing (cls, pkt_data, time)é   é   é   r   z
swap-bytesz<Iz>Ir   é   é   é   é   z!II)rn   r4   Úis_extended_idÚis_remote_frameÚis_error_frameÚarbitration_idr   ZcontribsÚstructÚunpackÚpackÚdlcÚis_fdÚerror_state_indicatorÚbitrate_switchÚbytesÚdatarl   r#   )r   Úxr   Úhdrr~   Zpkt_datar   r   r   Úrecv_raw#  s    
ÿÿÿÿzPythonCANSocket.recv_rawc                 C   s®   t |ƒ}t|jdk|jdk|jdk|jt|d ƒd@ dkt|d ƒd@ dkt|d ƒd@ dk|j|dd … d�	}t ¡ |_z|j|_W n t	y˜   Y n0 | j
 |¡ t|ƒS )Né   é   r3   é   r   é   )	rx   rw   ry   rz   r   r€   r�   r~   rƒ   )r‚   Úcan_MessageÚflagsÚ
identifierr   ÚlengthÚtimer#   Z	sent_timeÚAttributeErrorrn   rF   Úlen)r   r„   Úbxr   r   r   r   rF   3  s$    

ø	
zPythonCANSocket.sendc                 C   s   t  ¡  dd„ | D ƒS )a0  This function is called during sendrecv() routine to select
        the available sockets.

        :param sockets: an array of sockets that need to be selected
        :returns: an array of sockets that were selected and
            the function to be called next to get the packets (i.g. recv)
        c                 S   s&   g | ]}t |tƒr|jj ¡ s|‘qS r   )r"   r   rn   r6   ÚemptyrP   r   r   r   rS   R  s   ÿz*PythonCANSocket.select.<locals>.<listcomp>)rd   rM   )r1   Zremainr   r   r   ÚselectG  s    
zPythonCANSocket.selectc                    s&   | j r
dS tt| ƒ ¡  | j ¡  dS )zCloses this socketN)Úclosedra   r   Úclosern   r^   rB   re   r   r   r–   U  s    zPythonCANSocket.close)ro   )r+   r,   r-   r.   ÚdescZnonblocking_socketr   r†   rF   Ústaticmethodr   Zrecv_poll_rater”   r–   rk   r   r   re   r   r     s   	
)0r.   r�   r{   r?   Ú	functoolsr   Úoperatorr   Zscapy.configr   Zscapy.supersocketr   Zscapy.layers.canr   Zscapy.packetr   Zscapy.errorr   Zscapy.compatr	   r
   r   r   r   r   r   r   Zscapy.libs.six.movesr   Zcanr   r‹   r   rH   r   Z
can_BusABCZcan.interfacer   rW   Ú__all__Úobjectr   r/   r<   rd   r`   r   r   r   r   r   r   Ú<module>	   s0   ((#g6N