1import socket
2import warnings
3
4
5class TransportSocket:
6
7    """A socket-like wrapper for exposing real transport sockets.
8
9    These objects can be safely returned by APIs like
10    `transport.get_extra_info('socket')`.  All potentially disruptive
11    operations (like "socket.close()") are banned.
12    """
13
14    __slots__ = ('_sock',)
15
16    def __init__(self, sock: socket.socket):
17        self._sock = sock
18
19    def _na(self, what):
20        warnings.warn(
21            f"Using {what} on sockets returned from get_extra_info('socket') "
22            f"will be prohibited in asyncio 3.9. Please report your use case "
23            f"to bugs.python.org.",
24            DeprecationWarning, source=self)
25
26    @property
27    def family(self):
28        return self._sock.family
29
30    @property
31    def type(self):
32        return self._sock.type
33
34    @property
35    def proto(self):
36        return self._sock.proto
37
38    def __repr__(self):
39        s = (
40            f"<asyncio.TransportSocket fd={self.fileno()}, "
41            f"family={self.family!s}, type={self.type!s}, "
42            f"proto={self.proto}"
43        )
44
45        if self.fileno() != -1:
46            try:
47                laddr = self.getsockname()
48                if laddr:
49                    s = f"{s}, laddr={laddr}"
50            except socket.error:
51                pass
52            try:
53                raddr = self.getpeername()
54                if raddr:
55                    s = f"{s}, raddr={raddr}"
56            except socket.error:
57                pass
58
59        return f"{s}>"
60
61    def __getstate__(self):
62        raise TypeError("Cannot serialize asyncio.TransportSocket object")
63
64    def fileno(self):
65        return self._sock.fileno()
66
67    def dup(self):
68        return self._sock.dup()
69
70    def get_inheritable(self):
71        return self._sock.get_inheritable()
72
73    def shutdown(self, how):
74        # asyncio doesn't currently provide a high-level transport API
75        # to shutdown the connection.
76        self._sock.shutdown(how)
77
78    def getsockopt(self, *args, **kwargs):
79        return self._sock.getsockopt(*args, **kwargs)
80
81    def setsockopt(self, *args, **kwargs):
82        self._sock.setsockopt(*args, **kwargs)
83
84    def getpeername(self):
85        return self._sock.getpeername()
86
87    def getsockname(self):
88        return self._sock.getsockname()
89
90    def getsockbyname(self):
91        return self._sock.getsockbyname()
92
93    def accept(self):
94        self._na('accept() method')
95        return self._sock.accept()
96
97    def connect(self, *args, **kwargs):
98        self._na('connect() method')
99        return self._sock.connect(*args, **kwargs)
100
101    def connect_ex(self, *args, **kwargs):
102        self._na('connect_ex() method')
103        return self._sock.connect_ex(*args, **kwargs)
104
105    def bind(self, *args, **kwargs):
106        self._na('bind() method')
107        return self._sock.bind(*args, **kwargs)
108
109    def ioctl(self, *args, **kwargs):
110        self._na('ioctl() method')
111        return self._sock.ioctl(*args, **kwargs)
112
113    def listen(self, *args, **kwargs):
114        self._na('listen() method')
115        return self._sock.listen(*args, **kwargs)
116
117    def makefile(self):
118        self._na('makefile() method')
119        return self._sock.makefile()
120
121    def sendfile(self, *args, **kwargs):
122        self._na('sendfile() method')
123        return self._sock.sendfile(*args, **kwargs)
124
125    def close(self):
126        self._na('close() method')
127        return self._sock.close()
128
129    def detach(self):
130        self._na('detach() method')
131        return self._sock.detach()
132
133    def sendmsg_afalg(self, *args, **kwargs):
134        self._na('sendmsg_afalg() method')
135        return self._sock.sendmsg_afalg(*args, **kwargs)
136
137    def sendmsg(self, *args, **kwargs):
138        self._na('sendmsg() method')
139        return self._sock.sendmsg(*args, **kwargs)
140
141    def sendto(self, *args, **kwargs):
142        self._na('sendto() method')
143        return self._sock.sendto(*args, **kwargs)
144
145    def send(self, *args, **kwargs):
146        self._na('send() method')
147        return self._sock.send(*args, **kwargs)
148
149    def sendall(self, *args, **kwargs):
150        self._na('sendall() method')
151        return self._sock.sendall(*args, **kwargs)
152
153    def set_inheritable(self, *args, **kwargs):
154        self._na('set_inheritable() method')
155        return self._sock.set_inheritable(*args, **kwargs)
156
157    def share(self, process_id):
158        self._na('share() method')
159        return self._sock.share(process_id)
160
161    def recv_into(self, *args, **kwargs):
162        self._na('recv_into() method')
163        return self._sock.recv_into(*args, **kwargs)
164
165    def recvfrom_into(self, *args, **kwargs):
166        self._na('recvfrom_into() method')
167        return self._sock.recvfrom_into(*args, **kwargs)
168
169    def recvmsg_into(self, *args, **kwargs):
170        self._na('recvmsg_into() method')
171        return self._sock.recvmsg_into(*args, **kwargs)
172
173    def recvmsg(self, *args, **kwargs):
174        self._na('recvmsg() method')
175        return self._sock.recvmsg(*args, **kwargs)
176
177    def recvfrom(self, *args, **kwargs):
178        self._na('recvfrom() method')
179        return self._sock.recvfrom(*args, **kwargs)
180
181    def recv(self, *args, **kwargs):
182        self._na('recv() method')
183        return self._sock.recv(*args, **kwargs)
184
185    def settimeout(self, value):
186        if value == 0:
187            return
188        raise ValueError(
189            'settimeout(): only 0 timeout is allowed on transport sockets')
190
191    def gettimeout(self):
192        return 0
193
194    def setblocking(self, flag):
195        if not flag:
196            return
197        raise ValueError(
198            'setblocking(): transport sockets cannot be blocking')
199
200    def __enter__(self):
201        self._na('context manager protocol')
202        return self._sock.__enter__()
203
204    def __exit__(self, *err):
205        self._na('context manager protocol')
206        return self._sock.__exit__(*err)
207