ó
¨œž[c           @` sD  d  Z  d d l m Z m Z m Z d d l Z d d l 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 d d l 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 e j d
 ƒ Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ e d k r@e j e ƒ e ƒ  n  d S(   s5   Non-blocking HTTP client implementation using pycurl.i    (   t   absolute_importt   divisiont   print_functionN(   t   BytesIO(   t   httputil(   t   ioloop(   t   stack_context(   t   utf8t
   native_str(   t   HTTPResponset	   HTTPErrort   AsyncHTTPClientt   mains   tornado.curl_httpclientt   CurlAsyncHTTPClientc           B` s¤   e  Z d  d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 d	 „  Z d
 „  Z d d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   i
   c         C` s  t  t |  ƒ j d | ƒ t j ƒ  |  _ |  j j t j |  j ƒ |  j j t j	 |  j
 ƒ g  t | ƒ D] } |  j ƒ  ^ qg |  _ |  j |  _ t j ƒ  |  _ i  |  _ d  |  _ t j |  j d ƒ |  _ |  j j ƒ  t j ƒ  } |  j j | ƒ |  j j | ƒ d  S(   Nt   defaultsiè  (   t   superR   t
   initializet   pycurlt	   CurlMultit   _multit   setoptt   M_TIMERFUNCTIONt   _set_timeoutt   M_SOCKETFUNCTIONt   _handle_sockett   ranget   _curl_createt   _curlst
   _free_listt   collectionst   dequet	   _requestst   _fdst   Nonet   _timeoutR   t   PeriodicCallbackt   _handle_force_timeoutt   _force_timeout_callbackt   startt   Curlt
   add_handlet   remove_handle(   t   selft   max_clientsR   t   it   dummy_curl_handle(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR   '   s    (		c         C` s†   |  j  j ƒ  |  j d  k	 r2 |  j j |  j ƒ n  x |  j D] } | j ƒ  q< W|  j j ƒ  t	 t
 |  ƒ j ƒ  d  |  _  d  |  _ d  S(   N(   R%   t   stopR"   R!   t   io_loopt   remove_timeoutR   t   closeR   R   R   (   R*   t   curl(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR1   C   s    	c         C` s=   |  j  j | | |  j j ƒ  f ƒ |  j ƒ  |  j d ƒ d  S(   Ni    (   R   t   appendR/   t   timet   _process_queueR   (   R*   t   requestt   callback(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyt
   fetch_implR   s    "
c         C` sä   i t  j j t j 6t  j j t j 6t  j j t j 6t  j j t  j j Bt j	 6} | t j
 k rŽ | |  j k rà |  j j | ƒ |  j | =qà nR | | } | |  j k rº |  j j | ƒ n  |  j j | |  j | ƒ | |  j | <d S(   s_   Called by libcurl when it wants to change the file descriptors
        it cares about.
        N(   R   t   IOLoopt   NONER   t	   POLL_NONEt   READt   POLL_INt   WRITEt   POLL_OUTt
   POLL_INOUTt   POLL_REMOVER    R/   t   remove_handlert   add_handlert   _handle_events(   R*   t   eventt   fdt   multit   datat	   event_mapt   ioloop_event(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR   W   s    
	c         C` sU   |  j  d k	 r% |  j j |  j  ƒ n  |  j j |  j j ƒ  | d |  j ƒ |  _  d S(   s(   Called by libcurl to schedule a timeout.g     @@N(   R"   R!   R/   R0   t   add_timeoutR4   t   _handle_timeout(   R*   t   msecs(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR   u   s    	c         C` s¹   d } | t  j j @r& | t j O} n  | t  j j @rF | t j O} n  xb t rª y |  j j	 | | ƒ \ } } Wn# t j
 k
 r“ } | j d } n X| t j k rI PqI qI W|  j ƒ  d S(   sX   Called by IOLoop when there is activity on one of our
        file descriptors.
        i    N(   R   R9   R<   R   t
   CSELECT_INR>   t   CSELECT_OUTt   TrueR   t   socket_actiont   errort   argst   E_CALL_MULTI_PERFORMt   _finish_pending_requests(   R*   RF   t   eventst   actiont   rett   num_handlest   e(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRD   |   s    	c      	   C` s½   t  j ƒ  € d |  _ xe t r} y" |  j j t j d ƒ \ } } Wn# t j	 k
 rf } | j
 d } n X| t j k r Pq q W|  j ƒ  Wd QX|  j j ƒ  } | d k r¹ |  j | ƒ n  d S(   s7   Called by IOLoop when the requested timeout has passed.i    N(   R   t   NullContextR!   R"   RP   R   RQ   R   t   SOCKET_TIMEOUTRR   RS   RT   RU   t   timeoutR   (   R*   RX   RY   RZ   t   new_timeout(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRL   Ž   s    			c      	   C` s€   t  j ƒ  n x\ t rk y |  j j ƒ  \ } } Wn# t j k
 rT } | j d } n X| t j k r Pq q W|  j	 ƒ  Wd QXd S(   sp   Called by IOLoop periodically to ask libcurl to process any
        events it may have forgotten about.
        i    N(
   R   R[   RP   R   t
   socket_allR   RR   RS   RT   RU   (   R*   RX   RY   RZ   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR$   ­   s    	c         C` sŽ   x} t  r |  j j ƒ  \ } } } x | D] } |  j | ƒ q( Wx* | D]" \ } } } |  j | | | ƒ qF W| d k r Pq q W|  j ƒ  d S(   sb   Process any requests that were completed by the last
        call to multi.socket_action.
        i    N(   RP   R   t	   info_readt   _finishR5   (   R*   t   num_qt   ok_listt   err_listR2   t   errnumt   errmsg(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRU   »   s    	c         C` sS  t  j ƒ  Ax9t rHd } x|  j r:|  j r:| d 7} |  j j ƒ  } |  j j ƒ  \ } } } i t j ƒ  d 6t	 ƒ  d 6| d 6| d 6| d 6t
 j
 ƒ  d 6|  j j ƒ  j
 ƒ  d	 6| _ y( |  j | | | j d | j d ƒ WnB t k
 r&} |  j j | ƒ | t d | d
 d d | ƒ ƒ q X|  j j | ƒ q W| s Pq q WWd  QXd  S(   Ni    i   t   headerst   bufferR6   R7   t   queue_start_timet   curl_start_timet   curl_start_ioloop_timet   codeiW  RR   (   R   R[   RP   R   R   t   popt   popleftR   t   HTTPHeadersR   R4   R/   t   currentt   infot   _curl_setup_requestt	   ExceptionR3   R	   R   R(   (   R*   t   startedR2   R6   R7   Ri   RZ   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR5   É   s8    	

		c   
      C` sê  | j  } d  | _  |  j j | ƒ |  j j | ƒ | d } | rs t | | ƒ } | j } d  } | j ƒ  d  } n7 d  } | j	 t
 j ƒ } | j	 t
 j ƒ } | j d ƒ t d | d | d d | j	 t
 j ƒ d | j	 t
 j ƒ d | j	 t
 j ƒ d	 | j	 t
 j ƒ d
 | j	 t
 j ƒ d | j	 t
 j ƒ d | j	 t
 j ƒ ƒ }	 y~ | d t d | d d | d | d d | d | d | d | d j d d  ƒ d |  j j ƒ  | d d | d d |	 ƒ 
ƒ Wn" t k
 rå|  j | d ƒ n Xd  S(   NRh   i    t   queueRk   Ri   t
   namelookupt   connectt
   appconnectt   pretransfert   starttransfert   totalt   redirectR7   R6   Rl   Rg   t   effective_urlRR   t   reasons   X-Http-Reasont   request_timet
   start_timeRj   t	   time_info(   Rq   R!   R   R)   R   R3   t	   CurlErrorRl   R1   t   getinfoR   t	   HTTP_CODEt   EFFECTIVE_URLt   seekt   dictt   NAMELOOKUP_TIMEt   CONNECT_TIMEt   APPCONNECT_TIMEt   PRETRANSFER_TIMEt   STARTTRANSFER_TIMEt
   TOTAL_TIMEt   REDIRECT_TIMER	   t   getR/   R4   Rs   t   handle_callback_exception(
   R*   R2   t
   curl_errort   curl_messageRq   Rh   RR   Rl   R}   R   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRa   ò   sD    		
	
	
c         C` s   |  j  j | ƒ d  S(   N(   R/   R   (   R*   R7   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR     s    c         C` sš   t  j ƒ  } t j t j ƒ rJ | j t  j d ƒ | j t  j |  j	 ƒ n  t
 t  d ƒ r– | j t  j t  j t  j Bƒ | j t  j t  j t  j Bƒ n  | S(   Ni   t	   PROTOCOLS(   R   R'   t   curl_logt   isEnabledFort   loggingt   DEBUGR   t   VERBOSEt   DEBUGFUNCTIONt   _curl_debugt   hasattrR“   t
   PROTO_HTTPt   PROTO_HTTPSt   REDIR_PROTOCOLS(   R*   R2   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR     s     c         ` s¼  ˆ  j  t j t ˆ j ƒ ƒ d ˆ j k r; d ˆ j d <n  d ˆ j k rZ d ˆ j d <n  ˆ  j  t j g  ˆ j j ƒ  D]( \ } } d t | ƒ t | ƒ f ^ qv ƒ ˆ  j  t j t	 j
 ˆ j | ˆ j ƒ ƒ ˆ j rë ‡ ‡ f d †  } n	 | j } ˆ  j  t j | ƒ ˆ  j  t j ˆ j ƒ ˆ  j  t j ˆ j ƒ ˆ  j  t j t d ˆ j ƒ ƒ ˆ  j  t j t d ˆ j ƒ ƒ ˆ j r›ˆ  j  t j t ˆ j ƒ ƒ n ˆ  j  t j d ƒ ˆ j rÐˆ  j  t j ˆ j ƒ n  ˆ j rïˆ  j  t j d ƒ n ˆ  j  t j d	 ƒ ˆ j rìˆ j  rìˆ  j  t j! ˆ j ƒ ˆ  j  t j" ˆ j  ƒ ˆ j# rwt$ j% ˆ j# ˆ j& ƒ } ˆ  j  t j' | ƒ n  ˆ j( d  k s•ˆ j( d
 k r®ˆ  j  t j* t j+ ƒ qˆ j( d k rÖˆ  j  t j* t j, ƒ qt- d ˆ j( ƒ ‚ n# ˆ  j  t j! d ƒ ˆ  j. t j' ƒ ˆ j/ rAˆ  j  t j0 d ƒ ˆ  j  t j1 d ƒ n& ˆ  j  t j0 d ƒ ˆ  j  t j1 d ƒ ˆ j2 d  k	 rˆ  j  t j3 ˆ j2 ƒ n  ˆ j4 t5 k r·ˆ  j  t j6 t j7 ƒ n ˆ  j  t j6 t j8 ƒ i t j9 d 6t j: d 6t j; d 6t j< d 6}	 t= d d d g ƒ }
 x$ |	 j> ƒ  D] } ˆ  j  | t5 ƒ qWˆ j? |	 k rpˆ  j. t j@ ƒ ˆ  j  |	 ˆ j? tA ƒ nD ˆ jB sˆˆ j? |
 k r¡ˆ  j  t j@ ˆ j? ƒ n tC d ˆ j? ƒ ‚ ˆ j? d  k } ˆ jD d  k	 } ˆ jB s | rè| sõ| r | r t- d | rd n d ˆ j? f ƒ ‚ q n  | s,| rˆ j? d k rJt- d ƒ ‚ n  tE tF ˆ jD p\d ƒ ƒ ‰ ‡  ‡ f d †  } ˆ  j  t jG ˆ jH ƒ ˆ  j  t jI | ƒ ˆ j? d k rÔˆ  j  t jJ tK ˆ jD pÊd ƒ ƒ qˆ  j  t j; tA ƒ ˆ  j  t jL tK ˆ jD pd ƒ ƒ n  ˆ jM d  k	 rÚˆ jN d  k s9ˆ jN d
 k rRˆ  j  t jO t j+ ƒ n; ˆ jN d k rzˆ  j  t jO t j, ƒ n t- d ˆ jN ƒ ‚ t$ j% ˆ jM ˆ jP ƒ } ˆ  j  t jQ | ƒ tR jS d ˆ j? ˆ j ˆ jM ƒ n) ˆ  j. t jQ ƒ tR jS d ˆ j? ˆ j ƒ ˆ jT d  k	 r+ˆ  j  t jU ˆ jT ƒ n  ˆ jV d  k	 rSˆ  j  t jW ˆ jV ƒ n  ˆ jX d  k	 rqt- d ƒ ‚ n  tY jZ ƒ  d k r™ˆ  j  t j[ d ƒ n  ˆ j\ d  k	 r¸ˆ j\ ˆ  ƒ n  d  S(!   Nt   Expectt    t   Pragmas   %s: %sc         ` s   ˆ j  j ˆ  j |  ƒ d  S(   N(   R/   t   add_callbackt   streaming_callback(   t   chunk(   R6   R*   (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyt   write_functionA  s    iè  s    Mozilla/5.0 (compatible; pycurl)s   gzip,deflatet   nonet   basict   digests   Unsupported proxy_auth_mode %si   i   i    t   GETt   POSTt   PUTt   HEADt   DELETEt   OPTIONSt   PATCHs   unknown method sL   Body must %sbe None for method %s (unless allow_nonstandard_methods is true)s   not s!   Body must be None for GET requestc         ` s#   |  ˆ  j  k r ˆ j d ƒ n  d  S(   Ni    (   t   IOCMD_RESTARTREADR†   (   t   cmd(   R2   t   request_buffer(    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyt   ioctl©  s    s   Unsupported auth_mode %ss   %s %s (username: %r)s   %s %ss,   ssl_options not supported in curl_httpclient(   Rª   R¯   R«   (]   R   R   t   URLR   t   urlRg   t
   HTTPHEADERt   get_allt   HEADERFUNCTIONt	   functoolst   partialt   _curl_header_callbackt   header_callbackR£   t   writet   WRITEFUNCTIONt   FOLLOWLOCATIONt   follow_redirectst	   MAXREDIRSt   max_redirectst   CONNECTTIMEOUT_MSt   intt   connect_timeoutt
   TIMEOUT_MSt   request_timeoutt
   user_agentt	   USERAGENTt   network_interfacet	   INTERFACEt   decompress_responset   ENCODINGt
   proxy_hostt
   proxy_portt   PROXYt	   PROXYPORTt   proxy_usernameR   t   encode_username_passwordt   proxy_passwordt   PROXYUSERPWDt   proxy_auth_modeR!   t	   PROXYAUTHt   HTTPAUTH_BASICt   HTTPAUTH_DIGESTt
   ValueErrort   unsetoptt   validate_certt   SSL_VERIFYPEERt   SSL_VERIFYHOSTt   ca_certst   CAINFOt
   allow_ipv6t   Falset	   IPRESOLVEt   IPRESOLVE_V4t   IPRESOLVE_WHATEVERt   HTTPGETRª   t   UPLOADt   NOBODYt   sett   valuest   methodt   CUSTOMREQUESTRP   t   allow_nonstandard_methodst   KeyErrort   bodyR   R   t   READFUNCTIONt   readt   IOCTLFUNCTIONt   POSTFIELDSIZEt   lent
   INFILESIZEt   auth_usernamet	   auth_modet   HTTPAUTHt   auth_passwordt   USERPWDR”   t   debugt   client_certt   SSLCERTt
   client_keyt   SSLKEYt   ssl_optionst	   threadingt   activeCountt   NOSIGNALt   prepare_curl_callback(   R*   R2   R6   Rh   Rg   t   kt   vR¥   t   credentialst   curl_optionst   custom_methodst   ot   body_expectedt   body_presentR³   t   userpwd(    (   R2   R6   R²   R*   s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRr   '  sÚ    
<		  					



	%%%	c         C` s¸   t  | j d ƒ ƒ } | d  k	 r7 |  j j | | ƒ n  | j ƒ  } | j d ƒ r | j ƒ  y& t j	 | ƒ \ } } } d | } Wq t j
 k
 r™ d  SXn  | s§ d  S| j | ƒ d  S(   Nt   latin1s   HTTP/s   X-Http-Reason: %s(   R   t   decodeR!   R/   R¢   t   rstript
   startswitht   clearR   t   parse_response_start_linet   HTTPInputErrort
   parse_line(   R*   Rg   R¼   t   header_linet   __R~   (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR»   Û  s    
c         C` sª   d } | d k r7 t  | ƒ } t j d | j ƒ  ƒ no | d k r€ t  | ƒ } xT | j ƒ  D] } t j d | | | ƒ q\ Wn& | d	 k r¦ t j d
 | | | ƒ n  d  S(   Nt   It   <t   >i    s   %si   i   s   %s %si   s   %s %r(   R  R  R  R  R  (   i   i   (   R   R”   Rû   t   stript
   splitlines(   R*   t
   debug_typet	   debug_msgt   debug_typest   line(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyRš   í  s    N(   t   __name__t
   __module__R!   R   R1   R8   R   R   RD   RL   R$   RU   R5   Ra   R   R   Rr   R»   Rš   (    (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR   &   s    									)(		
	´	R‚   c           B` s   e  Z d  „  Z RS(   c         C` s    t  j |  d | ƒ | |  _ d  S(   NiW  (   R
   t   __init__t   errno(   R*   R$  t   message(    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR#  û  s    (   R!  R"  R#  (    (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyR‚   ú  s   t   __main__(   t   __doc__t
   __future__R    R   R   R   R¹   R–   R   R  R4   t   ioR   t   tornadoR   R   R   t   tornado.escapeR   R   t   tornado.httpclientR	   R
   R   R   t	   getLoggerR”   R   R‚   R!  t	   configure(    (    (    s6   lib/python2.7/site-packages/tornado/curl_httpclient.pyt   <module>   s(   "ÿ Õ