a
    kÄ#dÚ€  ã                   @   s°  d dl Z d dlZd dlZd dlZd dlmZ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mZmZmZmZ d dlmZ d dlmZ d dlmZmZ d dlm  mZ d dl m!Z! d d	l"m#Z#m$Z$ d d
l%m&Z&m'Z'm(Z(m)Z) d dl*m+Z+ d dl,m-Z- edde#fde!fdee! fdeee.f fdeeee.f  fgƒZ/edde#fde!fde!fdeee.f fdeee.f fgƒZ0e 1e j2¡G dd„ de&ƒƒZ3e 1e j2¡G dd„ de3e'ƒƒZ4dS )é    N)ÚdefaultdictÚOrderedDict)Úchain)ÚAnyÚUnionÚListÚOptionalÚIterableÚDictÚTupleÚSetÚCallableÚcastÚ
NamedTupleÚorb)Úlog_automotive)ÚScapy_Exception)Úmake_lined_tableÚEDecimal)ÚPacket)ÚEcuStateÚEcuResponse)ÚAutomotiveTestCaseÚStateGeneratorÚ_SocketUnionÚ_TransitionTuple)Ú'AutomotiveTestCaseExecutorConfiguration)Ú_EdgeÚ_AutomotiveTestCaseScanResultÚstateÚreqÚrespÚreq_tsÚresp_tsÚ%_AutomotiveTestCaseFilteredScanResultc                       sT  e Zd ZdZe ej¡Ze ee	fdd„ fedd„ fedfe
efdfe
efdfedfedfedfedfedfejrxejnejdfedfe
eefdfedfdœ¡ ejd Z‡ fdd	„Zeejd
d„ ƒƒZeejdd„ ƒƒZdd„ Zdd„ Zdd„ Zeejdd„ ƒƒZejdd„ ƒZ‡ fdd„Z e!dd„ ƒZ"e!‡ fdd„ƒZ#dd„ Z$d d!„ Z%d"d#„ Z&d$d%„ Z'd&d'„ Z(d(d)„ Z)d*d+„ Z*ee*_d,d-„ Z+d.d/„ Z,d0d1„ Z-d2d3„ Z.d4d5„ Z/d6d7„ Z0d8d9„ Z1d:d;„ Z2d<d=„ Z3e!d>d?„ ƒZ4e!d@dA„ ƒZ5e!dBdC„ ƒZ6e!dDdE„ ƒZ7e!dFdG„ ƒZ8e!dHdI„ ƒZ9e!dJdK„ ƒZ:dLdM„ Z;dNdO„ Z<dPdQ„ Z=d[dTdU„Z>d\dWdX„Z?e!dYdZ„ ƒZ@‡  ZAS )]ÚServiceEnumeratorzN
    Base class for ServiceEnumerators of automotive diagnostic protocols
    c                 C   s   | dkS ©Nr   © ©Úxr'   r'   úb/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/automotive/scanner/enumerator.pyÚ<lambda>9   ó    zServiceEnumerator.<lambda>c                 C   s   | dkS r&   r'   r(   r'   r'   r*   r+   :   r,   N)ÚtimeoutÚcountÚexecution_timeÚstate_allow_listÚstate_block_listÚretry_if_none_receivedÚexit_if_no_answer_receivedÚexit_if_service_not_supportedÚ$exit_scan_on_first_negative_responseÚretry_if_busy_returncodeÚ
stop_eventÚdebugZ
scan_rangeZunittesta
  
        :param timeout: Timeout until a response will arrive after a request
        :type timeout: integer or float
        :param integer count: Number of request to be sent in one execution
        :param int execution_time: Time in seconds until the execution of
                                   this enumerator is stopped.
        :param state_allow_list: List of EcuState objects or EcuState object
                                 in which the the execution of this enumerator
                                 is allowed. If provided, other states will not
                                 be executed.
        :type state_allow_list: EcuState or list
        :param state_block_list: List of EcuState objects or EcuState object
                                 in which the the execution of this enumerator
                                 is blocked.
        :type state_block_list: EcuState or list
        :param bool retry_if_none_received: Specifies if a request will be send
                                            again, if None was received
                                            (usually because of a timeout).
        :param bool exit_if_no_answer_received: Specifies to finish the
                                                execution of this enumerator
                                                once None is  received.
        :param bool exit_if_service_not_supported: Specifies to finish the
                                                   execution of this
                                                   enumerator, once the
                                                   negative return code
                                                   'serviceNotSupported' is
                                                   received.
        :param bool exit_scan_on_first_negative_response: Specifies to finish
                                                          the execution once a
                                                          negative response is
                                                          received.
        :param bool retry_if_busy_returncode: Specifies to retry a request, if
                                              the 'busyRepeatRequest' negative
                                              response code is received.
        :param bool debug: Enables debug functions during execute.
        :param Event stop_event: Signals immediate stop of the execution.
        :param scan_range: Specifies the identifiers to be scanned.
        :type scan_range: list or tuple or range or iterablec                    sD   t t| ƒ ¡  tƒ | _tƒ | _tƒ | _t	tƒ| _
ddg| _d | _d S )Né   é   )Úsuperr%   Ú__init__r   Ú_result_packetsÚlistÚ_resultsÚdictÚ_request_iteratorsr   Ú
_retry_pktÚ_negative_response_blacklistÚ_requests_per_state_estimated©Úself©Ú	__class__r'   r*   r<   p   s    

zServiceEnumerator.__init__c                 C   s
   t ƒ ‚d S ©N©ÚNotImplementedError©r!   r'   r'   r*   Ú_get_negative_response_codez   s    z-ServiceEnumerator._get_negative_response_codec                 C   s
   t ƒ ‚d S rI   rJ   )Únrcr'   r'   r*   Ú_get_negative_response_desc€   s    z-ServiceEnumerator._get_negative_response_descc                 C   s   t |d ƒS )z±
        Provides a table entry for the column which gets print during `show()`.
        :param tup: A results tuple
        :return: A string which describes the state
        r   )Ústr©rF   Útupr'   r'   r*   Ú_get_table_entry_x†   s    z$ServiceEnumerator._get_table_entry_xc                 C   s   t |d ƒS )z±
        Provides a table entry for the line which gets print during `show()`.
        :param tup: A results tuple
        :return: A string which describes the request
        é   ©ÚreprrQ   r'   r'   r*   Ú_get_table_entry_y�   s    z$ServiceEnumerator._get_table_entry_yc                 C   s   t |d ƒS )z³
        Provides a table entry for the field which gets print during `show()`.
        :param tup: A results tuple
        :return: A string which describes the response
        é   rU   rQ   r'   r'   r*   Ú_get_table_entry_z˜   s    z$ServiceEnumerator._get_table_entry_zc                 C   s
   t ƒ ‚d S rI   rJ   )Úresponser'   r'   r*   Ú_get_negative_response_label¡   s    z.ServiceEnumerator._get_negative_response_labelc                 K   s   t dƒ‚d S )NzOverwrite this methodrJ   )rF   Úkwargsr'   r'   r*   Ú_get_initial_requests§   s    z'ServiceEnumerator._get_initial_requestsc                    sš   t t| ƒ ¡ \}}}z,t |d ¡D ]\}}t|ƒ|d |< q$W n tyR   Y n0 z(|d D ]}t|  |¡ƒ|d |< q^W n tyŽ   Y n0 |||fS )NrA   rB   )r;   r%   Ú
__reduce__ÚsixÚ	iteritemsr>   ÚKeyErrorÚ_get_retry_iterator)rF   ÚfÚtÚdÚkÚvrG   r'   r*   r^   ¬   s    zServiceEnumerator.__reduce__c                 C   s   | j S rI   )rC   rE   r'   r'   r*   Únegative_response_blacklist»   s    z-ServiceEnumerator.negative_response_blacklistc                    s2   t ˆ jƒr"t‡ fdd„ˆ jD ƒƒS ttˆ ƒjS d S )Nc                    s   g | ]}ˆ   |¡‘qS r'   )Zhas_completed)Ú.0ÚsrE   r'   r*   Ú
<listcomp>Ä   r,   z/ServiceEnumerator.completed.<locals>.<listcomp>)Úlenr?   ÚallÚscanned_statesr;   r%   Ú	completedrE   rG   rE   r*   ro   À   s    
zServiceEnumerator.completedc              	   C   sŒ   t |ƒ| jvr|| jt |ƒ< |r<t |ƒ| jvr<|| jt |ƒ< | j t|| jt |ƒ |d urh| jt |ƒ nd |jprd|d ur€|jnd ƒ¡ d S )Ng        )Úbytesr=   r?   Úappendr   Z	sent_timeÚtime)rF   r   r    Úresr'   r'   r*   Ú_store_resultÈ   s    ûzServiceEnumerator._store_resultc                 C   s6   | j | }t|tƒr$t d¡ |gS t d¡ |S d S )NzProvide retry packetzProvide retry iterator)rB   Ú
isinstancer   r   r8   )rF   r   Zretry_entryr'   r'   r*   rb   ×   s    



z%ServiceEnumerator._get_retry_iteratorc                 K   s.   || j vr$t| jf i |¤Žƒ| j |< | j | S rI   )rA   Úiterr]   ©rF   r   r\   r'   r'   r*   Ú_get_initial_request_iteratorâ   s
    
ÿ
z/ServiceEnumerator._get_initial_request_iteratorc                 K   s   t |  |¡| j|fi |¤ŽƒS rI   )r   rb   rx   rw   r'   r'   r*   Ú_get_request_iteratorê   s    
ÿz'ServiceEnumerator._get_request_iteratorc                 K   sD   | j d u r@z"| jf i |¤Ž}tt|ƒƒ| _ W n ty>   Y n0 d S rI   )rD   r]   rl   r>   rK   )rF   r\   Zinitial_requestsr'   r'   r*   Ú_prepare_runtime_estimationï   s    
z-ServiceEnumerator._prepare_runtime_estimationc                 C   s@   | j d u rd S tt| jƒ| j  dƒ}t| jƒ}||t|ƒ| fS )NrT   )rD   Úmaxrl   rn   ÚresultsÚfloat)rF   Zpkts_tbsZpkts_sntr'   r'   r*   Úruntime_estimationø   s    
ÿ
z$ServiceEnumerator.runtime_estimationc                 K   sÔ  |   |¡ | dd¡}| dd ¡}| dd¡}| dd ¡}| jf i |¤Ž | dtƒ ¡}|r‚||v r‚d| j|< t d	t|ƒ¡ d S | d
tƒ ¡}	|	rº||	vrºd| j|< t dt|ƒ¡ d S | j	|fi |¤Ž}
t
 
¡ }t dt
 |¡¡ |
D ]¾}|  ||||¡}|  |||¡ | j|||fi |¤Ž�r4t d¡  d S |d u�r`|d8 }|dk�r`t d¡  d S || t
 
¡ k �rˆt dt
 ¡ ¡  d S |d urê| ¡ rêt d¡  d S qêt d¡ d| j|< t dt| jƒ¡ d S )Nr-   rT   r.   r/   i°  r7   r1   TzState %s in block list!r0   zState %s not in allow list!z!Start execution of enumerator: %sz7Stop test_case execution because of response evaluationr   z&Finished execution count of enumeratorz-[i] Finished execution time of enumerator: %sz.Stop test_case execution because of stop eventzFinished iterator executionzStates completed %s)Zcheck_kwargsÚpoprz   Úgetr>   Ú_state_completedr   r8   rV   ry   rr   ÚctimeÚsr1_with_retry_on_errorrt   Ú_evaluate_responseÚis_setÚinfo)rF   Úsocketr   r\   r-   r.   r/   r7   r1   r0   ÚitÚ
start_timer    rs   r'   r'   r*   Úexecute  sl    


ÿ
ÿÿ

ÿþÿ

ÿzServiceEnumerator.executec              
   C   sb   z|j ||dddd�}W nD tttfy\ } z&|  ||¡sDt d¡ |‚W Y d }~n
d }~0 0 |S )NFT)r-   ÚverboseÚchainEXZchainCCz#Exception during retry. This is bad)Úsr1ÚOSErrorÚ
ValueErrorr   Ú_populate_retryr   Ú	exception)rF   r    r‡   r   r-   rs   Úer'   r'   r*   rƒ   G  s    
ÿ
ÿz)ServiceEnumerator.sr1_with_retry_on_errorc                 K   s’   |du rHt t| dd¡ƒr6t dt|ƒ¡ |  ||¡S t t| dd¡ƒS | j||fi |¤Žr`dS | j|||fi |¤ŽrzdS g | j	|< |  
|||¡S )aO  
        Evaluates the response and determines if the current scan execution
        should be stopped.
        :param state: Current state of the ECU under test
        :param request: Sent request
        :param response: Received response
        :param kwargs: Arguments to modify the behavior of this function.
                       Supported arguments:
                         - retry_if_none_received: True/False
                         - exit_if_no_answer_received: True/False
                         - exit_if_service_not_supported: True/False
                         - exit_scan_on_first_negative_response: True/False
                         - retry_if_busy_returncode: True/False
        :return: True, if current execution needs to be interrupted.
                 False, if enumerator should proceed with the execution.
        Nr2   FzRetry %s because None receivedr3   T)r   Úboolr   r   r8   rV   r�   Ú _evaluate_negative_response_codeÚ_evaluate_retryrB   Ú!_evaluate_ecu_state_modifications)rF   r   ÚrequestrZ   r\   r'   r'   r*   r„   S  s"    ÿÿÿ
z$ServiceEnumerator._evaluate_responsec                 C   s.   t  |¡r*|t  |||¡kr*t d¡ dS dS )Nz%Exit execute. Ecu state was modified!TF)r   Úis_modifier_pktÚget_modified_ecu_stater   r8   )rF   r   r—   rZ   r'   r'   r*   r–   ~  s    
ÿÿz3ServiceEnumerator._evaluate_ecu_state_modificationsc                 K   sv   |  dd¡}|  dd¡}|r*|jdkr*dS |rr|jdkrr|  |¡}|dv rrdddœ}t d	|| ¡ d| j|< dS dS )
Nr4   Fr5   é   T)r:   rš   ZserviceNotSupportedZ"serviceNotSupportedInActiveSessionz3Exit execute because negative response %s received!)r   ÚservicerM   r   r8   r�   )rF   r   rZ   r\   r4   r5   Zresponse_codeÚnamesr'   r'   r*   r”   ‹  s&    
ÿ
ÿ
ÿþ
z2ServiceEnumerator._evaluate_negative_response_codec                 C   s4   |   |¡s"|| j|< t d¡ dS t d¡ dS dS )aw  
        Populates internal storage with request for a retry.

        :param state: Current state
        :param request: Request which needs a retry
        :return: True, if storage was populated. If False is returned, the
                 retry storage is still populated. This indicates that the
                 current execution was already a retry execution.
        z%Exit execute. Retry packet next time!TzUnsuccessful retry!FN)rb   rB   r   r8   )rF   r   r—   r'   r'   r*   r�   §  s    

ÿ
z!ServiceEnumerator._populate_retryc                 K   sH   |  dd¡}|rD|jdkrD|  |¡dkrDt dt|ƒ¡ |  ||¡S dS )Nr6   Trš   é!   z2Retry %s because retry_if_busy_returncode receivedF)r   r›   rM   r   r8   rV   r�   )rF   r   r—   rZ   r\   r6   r'   r'   r*   r•   À  s    
ÿÿþz!ServiceEnumerator._evaluate_retryc                    sì  d| j fg}| j ¡ D ]&‰ | tˆ ƒ‡ fdd„| j D ƒf¡ qtƒ }|D �]œ\}}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}	d	d„ |D ƒ}
| |d
tt|ƒƒf¡ | |dtt|ƒƒf¡ | |dtt|
ƒƒf¡ tg d¢|||	gƒD ]â\}}ztt	t
|ƒdƒƒ}W n t�y8   d}Y n0 ztt	t|ƒdƒƒ}W n t�yh   d}Y n0 ztt	t|ƒt|ƒ dƒƒ}W n ttf�y¤   d}Y n0 | |d| |f¡ | |d| |f¡ | |d| |f¡ �qqH|S )Nrm   c                    s   g | ]}|j ˆ kr|‘qS r'   ©r   ©ri   Úrrž   r'   r*   rk   ×  r,   z9ServiceEnumerator._compute_statistics.<locals>.<listcomp>c                 S   s*   g | ]"}|j d ur|jd urtt|ƒ‘qS rI   )r!   r#   r   r$   rŸ   r'   r'   r*   rk   Ü  s   
þc                 S   s   g | ]}|j d u r|‘qS rI   rL   rŸ   r'   r'   r*   rk   ß  r,   c                 S   s    g | ]}t |jƒt |jƒ ‘qS r'   )r}   r#   r"   ©ri   r)   r'   r'   r*   rk   à  s   ÿc                 S   s,   g | ]$}|j jd krt|jƒt|jƒ ‘qS ©rš   ©r!   r›   r}   r#   r"   r¡   r'   r'   r*   rk   â  s   ÿc                 S   s,   g | ]$}|j jd krt|jƒt|jƒ ‘qS r¢   r£   r¡   r'   r'   r*   rk   ä  s   ÿc                 S   s   g | ]}|j jd kr|j ‘qS r¢   ©r!   r›   rŸ   r'   r'   r*   rk   ç  r,   Znum_answeredZnum_unansweredZnum_negative_resps)Ú Z_nrZ_pré   ú-Zanswertime_minZanswertime_maxZanswertime_avg)r?   r�   Úkeysrq   rV   r>   rP   rl   ÚzipÚroundr{   r�   ÚminÚsumÚZeroDivisionError)rF   Z	data_setsÚstatsÚdescÚdataZansweredZ
unansweredZanswertimesZanswertimes_nrZanswertimes_prZnrsZpostfixÚtimesÚmaÚmiZavgr'   rž   r*   Ú_compute_statisticsÑ  sX    
ÿÿÿÿÿþ


z%ServiceEnumerator._compute_statisticsc                 K   sZ   |   ¡ }dt| jƒt| jƒt| jƒf d }|d7 }|t|dd„ dttd�pNd7 }|d S )	Nz1%d requests were sent, %d answered, %d unansweredÚ
zStatistics per state
c                 S   s   | S rI   r'   r(   r'   r'   r*   r+     r,   z4ServiceEnumerator._show_statistics.<locals>.<lambda>T)ÚdumpÚsortxZsortyr¥   )r´   rl   r?   Úresults_with_responseÚresults_without_responser   rP   )rF   r\   r®   rj   r'   r'   r*   Ú_show_statistics  s     þÿýÿÿz"ServiceEnumerator._show_statisticsc                 C   s¬   t tƒ}| jD ]}||  |j¡  d7  < qt| jƒ}| ¡ D ]h\}}|| jvr||dkr||| dkr|t 	d|¡ | j 
|¡ || jv r>|dk r>t 	d|¡ | j |¡ q>d S )NrT   é   g333333Ó?zAdded NRC 0x%02x to filteré
   zRemoved NRC 0x%02x to filter)r   ÚintÚresults_with_negative_responserM   r!   rl   Úitemsrh   r   r†   rq   Úremove)rF   Únrc_dictÚnrZtotal_nr_countrN   Únr_countr'   r'   r*   Ú$_prepare_negative_response_blacklist  s    


ÿ
ÿz6ServiceEnumerator._prepare_negative_response_blacklistc                 C   s   | j S rI   ©r?   rE   r'   r'   r*   r|   $  s    zServiceEnumerator.resultsc                 C   sB   t ƒ }| jD ]0}|jd u rq|jd u r(qtt|ƒ}| |¡ q|S rI   )r>   r?   r!   r#   r   r$   rq   )rF   Úfiltered_resultsr    Úfrr'   r'   r*   r¸   )  s    



z'ServiceEnumerator.results_with_responsec                 C   s6   | j }| jD ]$}|  |j¡}|| jvr| |¡ q|S rI   )Úresults_with_positive_responser¾   rM   r!   rh   rq   )rF   rÆ   r    rN   r'   r'   r*   rÆ   6  s    

z"ServiceEnumerator.filtered_resultsc                 C   s   t dd„ | jD ƒƒS )zj
        Helper function to get all sacnned states in results
        :return: all scanned states
        c                 S   s   g | ]
}|j ‘qS r'   rž   )ri   rR   r'   r'   r*   rk   H  r,   z4ServiceEnumerator.scanned_states.<locals>.<listcomp>)Úsetr?   rE   r'   r'   r*   rn   A  s    z ServiceEnumerator.scanned_statesc                 C   s   dd„ | j D ƒS )z
        Helper function to get all results with negative response
        :return: all results with negative response
        c                 S   s"   g | ]}|j r|j jd kr|‘qS r¢   r¤   rŸ   r'   r'   r*   rk   Q  s   ÿzDServiceEnumerator.results_with_negative_response.<locals>.<listcomp>©r¸   rE   r'   r'   r*   r¾   J  s    z0ServiceEnumerator.results_with_negative_responsec                 C   s   dd„ | j D ƒS )z
        Helper function to get all results with positive response
        :return: all results with positive response
        c                 S   s"   g | ]}|j r|j jd kr|‘qS r¢   r¤   rŸ   r'   r'   r*   rk   [  s   ÿzDServiceEnumerator.results_with_positive_response.<locals>.<listcomp>rÊ   rE   r'   r'   r*   rÈ   T  s    z0ServiceEnumerator.results_with_positive_responsec                 C   s   dd„ | j D ƒS )zs
        Helper function to get all results without response
        :return: all results without response
        c                 S   s   g | ]}|j d u r|‘qS rI   rL   rŸ   r'   r'   r*   rk   e  r,   z>ServiceEnumerator.results_without_response.<locals>.<listcomp>rÅ   rE   r'   r'   r*   r¹   ^  s    z*ServiceEnumerator.results_without_responsec                 K   s†   t tƒ}| jD ]}||  |j¡  d7  < qdd dd„ | ¡ D ƒ¡ d }| ¡ D ](\}}|d||  |¡|f 7 }|d7 }qT|d S )NrT   z,These negative response codes were received ú c                 S   s   g | ]}t |ƒ‘qS r'   )Úhex)ri   Úcr'   r'   r*   rk   n  r,   zEServiceEnumerator._show_negative_response_details.<locals>.<listcomp>rµ   z!	NRC 0x%02x: %s received %d times)	r   r½   r¾   rM   r!   Újoinr¨   r¿   rO   )rF   r\   rÁ   rÂ   rj   rN   rÃ   r'   r'   r*   Ú_show_negative_response_detailsg  s    
ÿÿÿ
z1ServiceEnumerator._show_negative_response_detailsc                    sl   |  dd¡}dtˆ jƒ }|d7 }|ˆ jf i |¤Žp6d7 }|rdtˆ jƒrd|d‡ fdd„ˆ jD ƒ 7 }|d S )NÚfilteredTz$%d negative responses were received
rµ   z:The following negative response codes are blacklisted: %s
c                    s   g | ]}ˆ   |¡‘qS r'   )rO   )ri   rÂ   rE   r'   r*   rk   �  s   ÿzIServiceEnumerator._show_negative_response_information.<locals>.<listcomp>)r€   rl   r¾   rÏ   rh   )rF   r\   rÐ   rj   r'   rE   r*   Ú#_show_negative_response_informationv  s    ÿ
ÿÿz5ServiceEnumerator._show_negative_response_informationc                    sP   ‡ fdd„}|  dd¡}d}|s&ˆ jnˆ j}t|ƒrHt||dtd�pFd}|d S )	Nc                    s   ˆ   | ¡ˆ  | ¡ˆ  | ¡fS rI   )rS   rW   rY   )rR   rE   r'   r*   Ú_get_table_entryˆ  s    þzEServiceEnumerator._show_results_information.<locals>._get_table_entryrÐ   Tz=== No data to display ===
)r¶   r·   r¥   rµ   )r€   r?   rÆ   rl   r   rP   )rF   r\   rÒ   rÐ   rj   r°   r'   rE   r*   Ú_show_results_information†  s    ÿÿz+ServiceEnumerator._show_results_informationFTc                    sd   ˆ r|   ¡  | j| j| j| jg}|r0| | j¡ d ‡ fdd„|D ƒ¡}|rT|d S t|ƒ d S d S )Nrµ   c                 3   s   | ]}|ˆ d �V  qdS )©rÐ   Nr'   r¡   rÔ   r'   r*   Ú	<genexpr>¥  r,   z)ServiceEnumerator.show.<locals>.<genexpr>)	rÄ   Z_show_headerrº   rÑ   rÓ   rq   Z_show_state_informationrÎ   Úprint)rF   r¶   rÐ   r‹   Zshow_functionsrj   r'   rÔ   r*   Úshow˜  s    ýzServiceEnumerator.showúPR: PositiveResponsec                 C   s\   |d u rdS t t|ƒd ƒdkr*|  |¡S t|tjƒr@tt|ƒS t|ƒrP||ƒS t	dƒ‚d S )NÚTimeoutr   rš   zCUnsupported Type for positive_case. Provide a string or a function.)
r   rp   r[   ru   r_   Ústring_typesr   rP   Úcallabler   )rF   rZ   Zpositive_caser'   r'   r*   Ú
_get_label­  s    

zServiceEnumerator._get_labelc                    sV   t ƒ }dd„ | j ¡ D ƒ}|D ]2‰ t t‡ fdd„| jD ƒƒƒ}| t|ˆ d�¡ q|S )Nc                 S   s$   g | ]}t t|ƒd  ƒd@ r|‘qS )r   é@   )r   rp   )ri   Úpr'   r'   r*   rk   À  s   ÿz9ServiceEnumerator.supported_responses.<locals>.<listcomp>c                    s   g | ]}|j ˆ kr|j‘qS r'   )r!   r   )ri   rd   rL   r'   r*   rk   Ã  s   
ÿ)r   Ú	responses)r>   r=   ÚvaluesrÉ   r¸   rq   r   )rF   Zsupported_respsZall_responsesZstatesr'   rL   r*   Úsupported_responses¼  s    z%ServiceEnumerator.supported_responses)FTF)rØ   )BÚ__name__Ú
__module__Ú__qualname__Ú__doc__Úcopyr   Z_supported_kwargsÚupdater½   r}   r>   r   r“   r_   ÚPY2Ú	threadingZ_EventÚEventÚtupleÚrangeZ_supported_kwargs_docr<   ÚstaticmethodÚabcÚabstractmethodrM   rO   rS   rW   rY   r[   r]   r^   Úpropertyrh   ro   rt   rb   rx   ry   rz   r~   rŠ   rƒ   r„   r–   r”   r�   r•   r´   rº   rÄ   r|   r¸   rÆ   rn   r¾   rÈ   r¹   rÏ   rÑ   rÓ   r×   rÜ   rá   Ú__classcell__r'   r'   rG   r*   r%   1   sš   


ò
'
			

	B+3





	
	


r%   c                       sH   e Zd Z‡ fdd„Zdd„ Zedd„ ƒZdd„ Zd	d
„ Zdd„ Z	‡  Z
S )Ú StateGeneratingServiceEnumeratorc                    s   t t| ƒ ¡  tƒ | _d S rI   )r;   rò   r<   r@   Ú_edge_requestsrE   rG   r'   r*   r<   Ë  s    z)StateGeneratingServiceEnumerator.__init__c           	      C   s€   zt t| ƒjd \}}}}}W n ty2   Y dS 0 |durxt |¡rxt |||¡}||kr`dS ||f}|| j|< |S ndS dS )a‚  
        Basic identification of a new edge. The last response is evaluated.
        If this response packet can modify the state of an Ecu, this new
        state is returned, otherwise None.

        :param socket: Socket to the DUT (unused)
        :param config: Global configuration of the executor (unused)
        :return: tuple of old EcuState and new EcuState, or None
        éÿÿÿÿN)r   r%   r|   Ú
IndexErrorr   r˜   r™   ró   )	rF   r‡   Úconfigr   r    r!   Ú_Ú	new_stateÚedger'   r'   r*   Úget_new_edgeÕ  s    
z-StateGeneratingServiceEnumerator.get_new_edgec              
   C   s|   |  dd¡}|du rdS z&| j|dddd�}|duo<|jdkW S  tttfyv } zt d|¡ W Y d}~dS d}~0 0 dS )	a  
        Very basic transition function. This function sends a given request
        in kwargs and evaluates the response.

        :param sock: Connection to the DUT
        :param config: Global configuration of the executor (unused)
        :param kwargs: Dictionary with arguments. This function only uses
                       the argument *"req"* which must contain a Packet,
                       causing an EcuState transition of the DUT.
        :return: True in case of a successful transition, else False
        r    NFé   T)r-   r‹   rŒ   rš   z$Exception in transition function: %s)r€   r�   r›   rŽ   r�   r   r   r‘   )Úsockrö   r\   r    rs   r’   r'   r'   r*   Útransition_functionó  s    ÿz4StateGeneratingServiceEnumerator.transition_functionc                 C   s   t | j| ƒS rI   )rV   ró   )rF   rù   r'   r'   r*   Ú#get_transition_function_description  s    zDStateGeneratingServiceEnumerator.get_transition_function_descriptionc                 C   s   | j | }|  |¡|dœ}|S )N)r¯   r    )ró   rþ   )rF   rù   r    r\   r'   r'   r*   Úget_transition_function_kwargs  s
    
þz?StateGeneratingServiceEnumerator.get_transition_function_kwargsc                 C   s.   z| j |  |¡d fW S  ty(   Y d S 0 d S rI   )rý   rÿ   ra   )rF   r‡   rù   r'   r'   r*   Úget_transition_function  s    
ÿz8StateGeneratingServiceEnumerator.get_transition_function)râ   rã   rä   r<   rú   rí   rý   rþ   rÿ   r   rñ   r'   r'   rG   r*   rò   É  s   

	rò   )5rî   ré   rr   ræ   Úcollectionsr   r   Ú	itertoolsr   Zscapy.compatr   r   r   r   r	   r
   r   r   r   r   r   r   Zscapy.contrib.automotiver   Zscapy.errorr   Zscapy.utilsr   r   Zscapy.libs.sixZlibsr_   Zscapy.packetr   Zscapy.contrib.automotive.ecur   r   Z*scapy.contrib.automotive.scanner.test_caser   r   r   r   Z.scapy.contrib.automotive.scanner.configurationr   Z&scapy.contrib.automotive.scanner.graphr   r}   r   r$   Úadd_metaclassÚABCMetar%   rò   r'   r'   r'   r*   Ú<module>
   sT   8
üþüþ	
     
