qmsk/net/socket/af_inet6.pyx
changeset 24 f18b5787c46c
child 49 e2f79e68418a
equal deleted inserted replaced
23:15d8bb96b8d4 24:f18b5787c46c
       
     1 cimport qmsk.net.py as py
       
     2 
       
     3 cdef class sockaddr_in6 (sockaddr) :
       
     4 
       
     5     def __init__ (self, object addr=None, platform.in_port_t port=0, unsigned int scope_id = 0) :
       
     6         """
       
     7             Construct using given literal IPv6 address and TCP/UDP port
       
     8 
       
     9                 addr        - IPv6 address, defaults to platform.in6addr_any (::)
       
    10                 port        - TCP/UDP port, defaults to 0 (ephemeral)
       
    11                 scope_id    - (optional) scope ID representing interface index for link-local addresses
       
    12         """
       
    13 
       
    14         # zero
       
    15         libc.memset(&self.sockaddr, 0, sizeof(self.sockaddr))
       
    16 
       
    17         # store our family
       
    18         # XXX: this should be a class attribute...
       
    19         self._init_family(platform.AF_INET6)
       
    20 
       
    21         # constant af
       
    22         self.sockaddr.sin6_family = self.family
       
    23         
       
    24         # set the sin_port
       
    25         self.sockaddr.sin6_port = platform.htons(port)
       
    26         
       
    27         if addr :
       
    28             # set the sin_addr
       
    29             # this automatically converts the addr from str -> char *
       
    30             platform.inet_pton(self.family, addr, &self.sockaddr.sin6_addr)
       
    31 
       
    32         else :
       
    33             # set as INADDR_ANY
       
    34             self.sockaddr.sin6_addr = platform.in6addr_any
       
    35 
       
    36         # scope ID
       
    37         self.sockaddr.sin6_scope_id = scope_id
       
    38 
       
    39     cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 :
       
    40         if sa_ptr :
       
    41             sa_ptr[0] = <platform.sockaddr *> &self.sockaddr
       
    42 
       
    43         if sa_len :
       
    44             sa_len[0] = sizeof(self.sockaddr)
       
    45 
       
    46         return 0
       
    47 
       
    48     cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 :
       
    49         assert sa_len == sizeof(self.sockaddr)
       
    50 
       
    51         libc.memcpy(&self.sockaddr, sa, sa_len)
       
    52 
       
    53     property port :
       
    54         """
       
    55             The integer port number.
       
    56 
       
    57             This will represent it correctly in host byte order.
       
    58 
       
    59             >>> sockaddr_in6(port=1234).port
       
    60             1234
       
    61         """
       
    62 
       
    63         def __get__ (self) :
       
    64             return platform.ntohs(self.sockaddr.sin6_port)
       
    65 
       
    66 
       
    67     property flowinfo :
       
    68         """
       
    69             The integer flowinfo
       
    70 
       
    71             XXX: byteorder?
       
    72             
       
    73             >>> sockaddr_in6().flowinfo
       
    74             0
       
    75         """
       
    76 
       
    77         def __get__ (self) :
       
    78             return self.sockaddr.sin6_flowinfo
       
    79 
       
    80 
       
    81     property scope_id :
       
    82         """
       
    83             The scope ID - corresponds to an interface index for link-scope addresses.
       
    84 
       
    85             This should be in host byte order...
       
    86 
       
    87             >>> sockaddr_in6(scope_id=1337).scope_id
       
    88             1337
       
    89         """
       
    90 
       
    91         def __get__ (self) :
       
    92             return self.sockaddr.sin6_scope_id
       
    93 
       
    94     def __cmp__ (self, other_obj) :
       
    95         """
       
    96             A sockaddr_in6 is equal to any other sockaddr_in6 which has the same addr, port and scope ID.
       
    97 
       
    98             XXX: flowinfo?
       
    99 
       
   100             XXX: A sockaddr_in6 is also equal to a sockaddr_in if the sockaddr_in6 represents the given v4-mapped address.
       
   101             
       
   102             >>> assert sockaddr_in6() == sockaddr_in6()
       
   103             >>> assert sockaddr_in6('0:0:0::1', 80) == sockaddr_in6('::1', 80)
       
   104             >>> assert sockaddr_in6('::127.0.0.1') == sockaddr_in('127.0.0.1')
       
   105         """
       
   106 
       
   107         if not isinstance(other_obj, sockaddr_in6) :
       
   108             return <object> py.Py_NotImplemented
       
   109 
       
   110         cdef sockaddr_in6 other = other_obj
       
   111         cdef platform.sockaddr_in6 *sa1 = &self.sockaddr, *sa2 = &other.sockaddr
       
   112 
       
   113         if other is self :
       
   114             return 0
       
   115 
       
   116         return (
       
   117                 libc.memcmp(<void *> &sa1.sin6_port,        <void *> &sa2.sin6_port,        sizeof(sa1.sin6_port))
       
   118             or  libc.memcmp(<void *> &sa1.sin6_addr,        <void *> &sa2.sin6_addr,        sizeof(sa1.sin6_addr))
       
   119             or  libc.memcmp(<void *> &sa1.sin6_scope_id,    <void *> &sa2.sin6_scope_id,    sizeof(sa1.sin6_scope_id))
       
   120         )
       
   121 
       
   122     def __str__ (self) :
       
   123         """
       
   124             Return the literal ASCII representation for this sockaddr as a '[<addr>]:<port> string
       
   125 
       
   126             >>> str(sockaddr_in6())
       
   127             '[::]:0'
       
   128 
       
   129             >>> str(sockaddr_in6('2001:0::05:1'))
       
   130             '[2001::5:1]'
       
   131 
       
   132             >>> str(sockaddr_in6('fe80::abcd', scope_id=5))
       
   133             '[fe80::abcd%5]'
       
   134         """
       
   135 
       
   136         addr, port = self.getnameinfo()
       
   137         scope_id = self.scope_id
       
   138 
       
   139         # format with scope_id
       
   140         return "[%s%s]:%s" % (
       
   141             addr,
       
   142             "%%%d" % scope_id if scope_id else "",
       
   143             port
       
   144         )
       
   145 
       
   146