@@ -102,8 +102,53 @@ cdef class TCPTransport(UVStream):
102
102
handle = TCPTransport.__new__ (TCPTransport)
103
103
handle._init(loop, protocol, server, waiter)
104
104
__tcp_init_uv_handle(< UVStream> handle, loop)
105
+ handle.__peername_set = 0
106
+ handle.__sockname_set = 0
105
107
return handle
106
108
109
+ cdef _call_connection_made(self ):
110
+ # asyncio saves peername & sockname when transports are instantiated,
111
+ # so that they're accessible even after the transport is closed.
112
+ # We are doing the same thing here, except that we create Python
113
+ # objects lazily, on request in get_extra_info()
114
+
115
+ cdef:
116
+ int err
117
+ int buf_len
118
+
119
+ buf_len = sizeof(system.sockaddr_storage)
120
+ err = uv.uv_tcp_getsockname(< uv.uv_tcp_t* > self ._handle,
121
+ < system.sockaddr* > & self .__sockname,
122
+ & buf_len)
123
+ if err >= 0 :
124
+ # Ignore errors, this is an optional thing.
125
+ # If something serious is going on, the transport
126
+ # will crash later (in roughly the same way how
127
+ # an asyncio transport would.)
128
+ self .__sockname_set = 1
129
+
130
+ buf_len = sizeof(system.sockaddr_storage)
131
+ err = uv.uv_tcp_getpeername(< uv.uv_tcp_t* > self ._handle,
132
+ < system.sockaddr* > & self .__peername,
133
+ & buf_len)
134
+ if err >= 0 :
135
+ # Same as few lines above -- we don't really care
136
+ # about error case here.
137
+ self .__peername_set = 1
138
+
139
+ UVBaseTransport._call_connection_made(self )
140
+
141
+ def get_extra_info (self , name , default = None ):
142
+ if name == ' sockname' :
143
+ if self .__sockname_set:
144
+ return __convert_sockaddr_to_pyaddr(
145
+ < system.sockaddr* > & self .__sockname)
146
+ elif name == ' peername' :
147
+ if self .__peername_set:
148
+ return __convert_sockaddr_to_pyaddr(
149
+ < system.sockaddr* > & self .__peername)
150
+ return super ().get_extra_info(name, default)
151
+
107
152
cdef _new_socket(self ):
108
153
return __tcp_get_socket(< UVSocketHandle> self )
109
154
0 commit comments