@@ -144,6 +144,13 @@ def ssl_options(self):
144144 """
145145 return None
146146
147+ @property
148+ def socket_family (self ):
149+ """
150+ The socket family of the endpoint.
151+ """
152+ return socket .AF_UNSPEC
153+
147154 def resolve (self ):
148155 """
149156 Resolve the endpoint to an address/port. This is called
@@ -299,6 +306,47 @@ def create_from_sni(self, sni):
299306 return SniEndPoint (self ._proxy_address , sni , self ._port )
300307
301308
309+ @total_ordering
310+ class UnixSocketEndPoint (EndPoint ):
311+ """
312+ Unix Socket EndPoint implementation.
313+ """
314+
315+ def __init__ (self , unix_socket_path ):
316+ self ._unix_socket_path = unix_socket_path
317+
318+ @property
319+ def address (self ):
320+ return self ._unix_socket_path
321+
322+ @property
323+ def port (self ):
324+ return None
325+
326+ @property
327+ def socket_family (self ):
328+ return socket .AF_UNIX
329+
330+ def resolve (self ):
331+ return self .address , None
332+
333+ def __eq__ (self , other ):
334+ return (isinstance (other , UnixSocketEndPoint ) and
335+ self ._unix_socket_path == other ._unix_socket_path )
336+
337+ def __hash__ (self ):
338+ return hash (self ._unix_socket_path )
339+
340+ def __lt__ (self , other ):
341+ return self ._unix_socket_path < other ._unix_socket_path
342+
343+ def __str__ (self ):
344+ return str ("%s" % (self ._unix_socket_path ,))
345+
346+ def __repr__ (self ):
347+ return "<%s: %s>" % (self .__class__ .__name__ , self ._unix_socket_path )
348+
349+
302350class _Frame (object ):
303351 def __init__ (self , version , flags , stream , opcode , body_offset , end_pos ):
304352 self .version = version
@@ -557,13 +605,22 @@ def factory(cls, endpoint, timeout, *args, **kwargs):
557605 else :
558606 return conn
559607
560- def _connect_socket (self ):
561- sockerr = None
562- inet_address , port = self .endpoint .resolve ()
563- addresses = socket .getaddrinfo (inet_address , port , socket .AF_UNSPEC , socket .SOCK_STREAM )
608+ def _get_socket_addresses (self ):
609+ address , port = self .endpoint .resolve ()
610+
611+ if self .endpoint .socket_family == socket .AF_UNIX :
612+ return [(socket .AF_UNIX , socket .SOCK_STREAM , 0 , None , address )]
613+
614+ addresses = socket .getaddrinfo (address , port , self .endpoint .socket_family , socket .SOCK_STREAM )
564615 if not addresses :
565616 raise ConnectionException ("getaddrinfo returned empty list for %s" % (self .endpoint ,))
566- for (af , socktype , proto , canonname , sockaddr ) in addresses :
617+
618+ return addresses
619+
620+ def _connect_socket (self ):
621+ sockerr = None
622+ addresses = self ._get_socket_addresses ()
623+ for (af , socktype , proto , _ , sockaddr ) in addresses :
567624 try :
568625 self ._socket = self ._socket_impl .socket (af , socktype , proto )
569626 if self .ssl_context :
@@ -587,7 +644,8 @@ def _connect_socket(self):
587644 sockerr = err
588645
589646 if sockerr :
590- raise socket .error (sockerr .errno , "Tried connecting to %s. Last error: %s" % ([a [4 ] for a in addresses ], sockerr .strerror or sockerr ))
647+ raise socket .error (sockerr .errno , "Tried connecting to %s. Last error: %s" %
648+ ([a [4 ] for a in addresses ], sockerr .strerror or sockerr ))
591649
592650 if self .sockopts :
593651 for args in self .sockopts :
0 commit comments