ó
ŒGUc           @   s›   d  Z  d Z d Z d Z d Z d Z d Z d d l m Z d d	 l Z d d	 l	 Z	 d d
 l
 m Z d d l m Z e j e ƒ Z d e f d „  ƒ  YZ d	 S(   s’   PyOpenSSL utilities including HTTPSSocket class which wraps PyOpenSSL
SSL connection into a httplib-like interface suitable for use with urllib2

s   P J Kershaws   21/12/10s2   (C) 2012 Science and Technology Facilities Councils-   BSD - see LICENSE file in top-level directorys   Philip.Kershaw@stfc.ac.uks   $Id$iÿÿÿÿ(   t   datetimeN(   t   BytesIO(   t   SSLt	   SSLSocketc           B   s.  e  Z d  Z d Z d d „ Z d „  Z e d „  ƒ Z e j	 d „  ƒ Z d „  Z
 d „  Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z e d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z  d „  Z! d „  Z" RS(    s:  SSL Socket class wraps pyOpenSSL's SSL.Connection class implementing
    the makefile method so that it is compatible with the standard socket
    interface and usable with httplib.

    @cvar default_buf_size: default buffer size for recv operations in the
    makefile method
    @type default_buf_size: int
    i    c         C   sƒ   | d k	 r | |  _ n7 t j t j t j ƒ |  _ |  j j t j t j d ƒ t j | |  j ƒ |  _	 |  j
 j |  _ d |  _ d S(   s¹   Create SSL socket object

        @param ctx: SSL context
        @type ctx: OpenSSL.SSL.Context
        @param sock: underlying socket object
        @type sock: socket.socket
        i   i    N(   t   Nonet   sockett   AF_INETt   SOCK_STREAMt
   setsockoptt
   SOL_SOCKETt   SO_REUSEADDRR   t
   Connectiont   _SSLSocket__ssl_connt	   __class__t   default_buf_sizet   buf_sizet   _makefile_refs(   t   selft   ctxt   sock(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyt   __init__!   s    c         C   s   |  j  ƒ  d S(   sC   Close underlying socket when this object goes out of scope
        N(   t   close(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyt   __del__3   s    c         C   s   |  j  S(   s1   Buffer size for makefile method recv() operations(   t   _SSLSocket__buf_size(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR   8   s    c         C   s5   t  | t ƒ s( t d t | ƒ ƒ ‚ n  | |  _ d S(   s1   Buffer size for makefile method recv() operationss1   Expecting int type for "buf_size"; got %r insteadN(   t
   isinstancet   intt	   TypeErrort   typeR   (   R   t   value(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR   =   s    c         C   sV   |  j  d k  rC y |  j j ƒ  WqR t j t j f k
 r? qR Xn |  j  d 8_  d S(   sV   Shutdown the SSL connection and call the close method of the
        underlying socketi   N(   R   R   t   shutdownR   t   Errort   SysCallError(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR   E   s    c         C   s   |  j  j | ƒ d S(   s“   Set the shutdown state of the Connection.
        @param mode: bit vector of either or both of SENT_SHUTDOWN and
        RECEIVED_SHUTDOWN
        N(   R   t   set_shutdown(   R   t   mode(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR    Q   s    c         C   s   |  j  j ƒ  S(   s   Get the shutdown state of the Connection.
        @return: bit vector of either or both of SENT_SHUTDOWN and
        RECEIVED_SHUTDOWN
        (   R   t   get_shutdown(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR"   X   s    c         C   s   |  j  j | ƒ d S(   sŠ   bind to the given address - calls method of the underlying socket
        @param addr: address/port number tuple
        @type addr: tupleN(   R   t   bind(   R   t   addr(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR#   _   s    c         C   s   |  j  j | ƒ d S(   sð   Listen for connections made to the socket.

        @param backlog: specifies the maximum number of queued connections and
        should be at least 1; the maximum value is system-dependent (usually 5).
        @param backlog: int
        N(   R   t   listen(   R   t   backlog(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR%   e   s    c         C   s   |  j  j ƒ  d S(   sl   Set the connection to work in server mode. The handshake will be
        handled automatically by read/writeN(   R   t   set_accept_state(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR'   n   s    c         C   s   |  j  j ƒ  S(   sÒ   Accept an SSL connection.

        @return: pair (ssl, addr) where ssl is a new SSL connection object and
        addr is the address bound to the other end of the SSL connection.
        @rtype: tuple
        (   R   t   accept(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR(   s   s    c         C   s   |  j  j ƒ  d S(   sl   Set the connection to work in client mode. The handshake will be
        handled automatically by read/writeN(   R   t   set_connect_state(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR)   |   s    c         C   s   |  j  j | ƒ d S(   sù   Call the connect method of the underlying socket and set up SSL on
        the socket, using the Context object supplied to this Connection object
        at creation.

        @param addr: address/port number pair
        @type addr: tuple
        N(   R   t   connect(   R   R$   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR*      s    c         C   s   |  j  j ƒ  S(   sÜ  Send the shutdown message to the Connection.

        @param how: for socket.socket this flag determines whether read, write
        or both type operations are supported.  OpenSSL.SSL.Connection doesn't
        support this so this parameter is IGNORED
        @return: true if the shutdown message exchange is completed and false
        otherwise (in which case you call recv() or send() when the connection
        becomes readable/writeable.
        @rtype: bool
        (   R   R   (   R   t   how(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR   ‹   s    c         C   s   |  j  j ƒ  S(   s-   Renegotiate this connection's SSL parameters.(   R   t   renegotiate(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR,   ˜   s    c         C   s   |  j  j ƒ  S(   sk   @return: numbers of bytes that can be safely read from the SSL
        buffer.
        @rtype: int
        (   R   t   pending(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR-   œ   s    c         G   s   |  j  j | ƒ S(   sÝ   Send data to the socket. Nb. The optional flags argument is ignored.
        - retained for compatibility with socket.socket interface

        @param data: data to send down the socket
        @type data: string
        (   R   t   send(   R   t   datat	   flags_arg(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR.   £   s    c         C   s   |  j  j | ƒ d  S(   N(   R   t   sendall(   R   R/   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR1   ¬   s    c         C   s   |  j  j | ƒ S(   sÁ   Receive data from the Connection.

        @param size: The maximum amount of data to be received at once
        @type size: int
        @return: data received.
        @rtype: string
        (   R   t   recv(   R   t   size(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR2   ¯   s    c         C   s   |  j  j | ƒ d S(   s}   Set this connection's underlying socket blocking _mode_.

        @param mode: blocking mode
        @type mode: int
        N(   R   t   setblocking(   R   R!   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR4   ¹   s    c         C   s   |  j  j ƒ  S(   s_   
        @return: file descriptor number for the underlying socket
        @rtype: int
        (   R   t   fileno(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR5   Á   s    c         G   s   |  j  j | Œ  S(   s%   See socket.socket.getsockopt
        (   R   t
   getsockopt(   R   t   args(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR6   È   s    c         G   s   |  j  j | Œ  S(   ss   See socket.socket.setsockopt

        @return: value of the given socket option
        @rtype: int/string
        (   R   R   (   R   R7   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR   Í   s    c         C   s   |  j  j ƒ  S(   s(   Return the SSL state of this connection.(   R   t   state_string(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR8   Õ   s    c         G   så   |  j  d 7_  |  j } d } t ƒ  } t j ƒ  } yL |  j j | ƒ } x3 | r} | d 7} | j | ƒ |  j j | ƒ } qK WWn t j	 t j
 f k
 rž n Xt j ƒ  t j k rÔ t j d | t j ƒ  | ƒ n  | j d ƒ | S(   sh  Specific to Python socket API and required by httplib: convert
        response into a file-like object.  This implementation reads using recv
        and copies the output into a StringIO buffer to simulate a file object
        for consumption by httplib

        Nb. Ignoring optional file open mode (StringIO is generic and will
        open for read and write unless a string is passed to the constructor)
        and buffer size - httplib set a zero buffer size which results in recv
        reading nothing

        @return: file object for data returned from socket
        @rtype: cStringIO.StringO
        i   i    s-   Socket.makefile %d recv calls completed in %s(   R   R   R   R    t   utcnowR   R2   t   writeR   t   ZeroReturnErrorR   t   logt   getEffectiveLevelt   loggingt   DEBUGt   debugt   seek(   R   R7   t	   _buf_sizet   it   streamt	   startTimet   dat(    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyt   makefileÙ   s$    			
c         C   s   |  j  j ƒ  S(   sC   
        @return: the socket's own address
        @rtype:
        (   R   t   getsockname(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyRH     s    c         C   s   |  j  j ƒ  S(   sJ   
        @return: remote address to which the socket is connected
        (   R   t   getpeername(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyRI     s    c         C   s   |  j  j ƒ  S(   s=   Retrieve the Context object associated with this Connection. (   R   t   get_context(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyRJ     s    c         C   s   |  j  j ƒ  S(   s0   Retrieve the other side's certificate (if any)  (   R   t   get_peer_certificate(   R   (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyRK     s    N(#   t   __name__t
   __module__t   __doc__R   R   R   R   t   propertyR   t   setterR   R    R"   R#   R%   R'   R(   R)   R*   R   R,   R-   R.   R1   R2   R4   R5   R6   R   R8   RG   RH   RI   RJ   RK   (    (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyR      s>   												
						
						.			(   RN   t
   __author__t   __date__t   __copyright__t   __license__t   __contact__t   __revision__R    R>   R   t   ioR   t   OpenSSLR   t	   getLoggerRL   R<   t   objectR   (    (    (    s>   /usr/lib/python2.7/dist-packages/ndg/httpsclient/ssl_socket.pyt   <module>   s   