def test_listen(self, llc, ldl, dlc, bind):
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.listen(object(), 0)
assert excinfo.value.errno == errno.ENOTSOCK
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.listen(ldl, 0)
assert excinfo.value.errno == errno.EOPNOTSUPP
with pytest.raises(TypeError) as excinfo:
llc.listen(dlc, 0.1)
assert str(excinfo.value) == "backlog must be int type"
with pytest.raises(ValueError) as excinfo:
llc.listen(dlc, -1)
assert str(excinfo.value) == "backlog can not be negative"
if bind:
llc.bind(dlc)
llc.listen(dlc, 0)
assert dlc.state.LISTEN is True
python类ENOTSOCK的实例源码
def test_accept_connect(self, llc, ldl, dlc, peer_miu, send_miu):
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.accept(object())
assert excinfo.value.errno == errno.ENOTSOCK
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.accept(ldl)
assert excinfo.value.errno == errno.EOPNOTSUPP
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.accept(dlc)
assert excinfo.value.errno == errno.EINVAL
connect_pdu = nfc.llcp.pdu.Connect(4, 32, peer_miu)
threading.Timer(0.01, llc.dispatch, (connect_pdu,)).start()
llc.bind(dlc, b'urn:nfc:sn:snep')
llc.listen(dlc, 0)
sock = llc.accept(dlc)
assert isinstance(sock, nfc.llcp.tco.DataLinkConnection)
assert llc.getsockopt(sock, nfc.llcp.SO_SNDMIU) == send_miu
assert llc.getpeername(sock) == 32
assert llc.getsockname(sock) == 4
def sendto(self, socket, message, dest, flags):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if isinstance(socket, tco.RawAccessPoint):
if not isinstance(message, pdu.ProtocolDataUnit):
raise TypeError("on a raw access point message must be a pdu")
if not socket.is_bound:
self.bind(socket)
# FIXME: set socket send miu when activated
socket.send_miu = self.cfg['send-miu']
return socket.send(message, flags)
if not isinstance(message, bytes):
raise TypeError("the message argument must be a byte string")
if isinstance(socket, tco.LogicalDataLink):
if dest is None:
raise err.Error(errno.EDESTADDRREQ)
if not socket.is_bound:
self.bind(socket)
# FIXME: set socket send miu when activated
socket.send_miu = self.cfg['send-miu']
return socket.sendto(message, dest, flags)
if isinstance(socket, tco.DataLinkConnection):
return socket.send(message, flags)
def nl_sendmsg(sock,msg,override=False):
"""
sends msg to kernel
:param sock: netlink socket
:param msg: nlmsg stream
:param override: if True will keep the message's pid and seq. This can
be used for testing
"""
try:
# change the msg's pid & seq to that of the sockets prior to sending &
# set the ack flag - I can't figure how to tell in recv if an ack was
# requested or not so I force an ACK here
if not override:
msg.pid = sock.pid
msg.seq = sock.seq
msg.flags = msg.flags | nlh.NLM_F_ACK
sent = sock.send(msg.tostream())
if sent != msg.len: raise error(errno.EBADMSG,"Message sent incomplete")
except socket.error as e:
raise error(errno.ECOMM, e)
except AttributeError:
raise error(errno.ENOTSOCK,"Invalid netlink socket")
def io_transfer(iosock,flag,ifreq):
"""
send & recieve an ifreq struct
:param iosock: io socket
:param flag: sockios control call
:param ifreq: ifreq to send
:returns: an the ifreq struct recieved
"""
try:
return ioctl(iosock.fileno(),flag,ifreq)
except (AttributeError,struct.error) as e:
# either sock is not valid or a bad value passed to ifreq
if e.message.find('fileno'): raise error(errno.ENOTSOCK,"Bad socket")
else: raise error(errno.EINVAL,e)
except IOError as e:
# generally device cannot be found sort but can also be
# permissions etc, catch and reraise as our own
if e.errno is not None: # just in case we have a none 2-tuple error
raise error(e.errno,e.strerror)
else:
raise error(-1,e)
except Exception as e:
# blanket catchall
raise error(-1,e.args[0])
def send(self, sendbuf=None):
'''Flush the send buffer.'''
self.acquire_lock()
try:
if not self.sock:
e = socket.error(
'[errno %d] Socket operation on non-socket' % errno.ENOTSOCK)
e.errno = errno.ENOTSOCK
raise e
try:
if sendbuf is None:
if self.sendbuf:
self.sock.sendall(self.sendbuf)
self.sendbuf = b''
elif sendbuf:
self.sock.sendall(sendbuf)
except socket.error as e:
try:
self.sock.close()
finally:
self.sock = None
raise
self.quit('Network error.', wait=False)
finally:
self.lock.release()
def handle(ws):
if ws.path == '/echo':
while True:
m = ws.wait()
if m is None:
break
ws.send(m)
elif ws.path == '/range':
for i in range(10):
ws.send("msg %d" % i)
eventlet.sleep(0.01)
elif ws.path == '/error':
# some random socket error that we shouldn't normally get
raise socket.error(errno.ENOTSOCK)
else:
ws.close()
def handle(ws):
if ws.path == '/echo':
while True:
m = ws.wait()
if m is None:
break
ws.send(m)
elif ws.path == '/range':
for i in range(10):
ws.send("msg %d" % i)
eventlet.sleep(0.01)
elif ws.path == '/error':
# some random socket error that we shouldn't normally get
raise socket.error(errno.ENOTSOCK)
else:
ws.close()
def shutdown_safe(sock):
""" Shuts down the socket. This is a convenience method for
code that wants to gracefully handle regular sockets, SSL.Connection
sockets from PyOpenSSL and ssl.SSLSocket objects from Python 2.6
interchangeably. Both types of ssl socket require a shutdown() before
close, but they have different arity on their shutdown method.
Regular sockets don't need a shutdown before close, but it doesn't hurt.
"""
try:
try:
# socket, ssl.SSLSocket
return sock.shutdown(socket.SHUT_RDWR)
except TypeError:
# SSL.Connection
return sock.shutdown()
except socket.error as e:
# we don't care if the socket is already closed;
# this will often be the case in an http server context
if get_errno(e) not in (errno.ENOTCONN, errno.EBADF, errno.ENOTSOCK):
raise
def read(self, size):
"""
Reads (receives) a whole block of size bytes from the connected peer.
:param size: the size of the block to be read.
:return: the read data with len(data) == size.
"""
if self._socket is None:
raise ConnectionResetError()
# TODO Remove the timeout from this method, always use previous one
with BufferedWriter(BytesIO(), buffer_size=size) as buffer:
bytes_left = size
while bytes_left != 0:
try:
partial = self._socket.recv(bytes_left)
except socket.timeout as e:
raise TimeoutError() from e
except OSError as e:
if e.errno == errno.EBADF or e.errno == errno.ENOTSOCK:
self._raise_connection_reset()
else:
raise
if len(partial) == 0:
self._raise_connection_reset()
buffer.write(partial)
bytes_left -= len(partial)
# If everything went fine, return the read bytes
buffer.flush()
return buffer.raw.getvalue()
def test_poll(self, llc, ldl):
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.poll(object(), 'recv')
assert excinfo.value.errno == errno.ENOTSOCK
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.poll(ldl, 'recv')
assert excinfo.value.errno == errno.EBADF
llc.bind(ldl)
pdu = nfc.llcp.pdu.UnnumberedInformation(32, 17, b'123')
threading.Timer(0.01, llc.dispatch, (pdu,)).start()
assert llc.poll(ldl, 'recv') is True
def test_close(self, llc, ldl, dlc):
with pytest.raises(nfc.llcp.Error) as excinfo:
llc.close(object())
assert excinfo.value.errno == errno.ENOTSOCK
llc.bind(ldl)
llc.close(ldl)
assert ldl.state.SHUTDOWN is True
llc.close(dlc)
assert dlc.state.SHUTDOWN is True
def setsockopt(self, socket, option, value):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if option == nfc.llcp.SO_RCVMIU:
value = min(value, self.cfg['recv-miu'])
socket.setsockopt(option, value)
return socket.getsockopt(option)
def bind(self, socket, addr_or_name=None):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if socket.addr is not None:
raise err.Error(errno.EINVAL)
if addr_or_name is None:
self._bind_by_none(socket)
elif isinstance(addr_or_name, int):
self._bind_by_addr(socket, addr_or_name)
elif isinstance(addr_or_name, bytes):
self._bind_by_name(socket, addr_or_name)
else:
raise err.Error(errno.EFAULT)
def connect(self, socket, dest):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if not socket.is_bound:
self.bind(socket)
socket.connect(dest)
log.debug("connected ({0} ===> {1})".format(socket.addr, socket.peer))
if socket.send_miu > self.cfg['send-miu']:
log.warn("reducing outbound miu to not exceed the link miu")
socket.send_miu = self.cfg['send-miu']
def listen(self, socket, backlog):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if not isinstance(socket, tco.DataLinkConnection):
raise err.Error(errno.EOPNOTSUPP)
if not isinstance(backlog, int):
raise TypeError("backlog must be int type")
if backlog < 0:
raise ValueError("backlog can not be negative")
backlog = min(backlog, 16)
if not socket.is_bound:
self.bind(socket)
socket.listen(backlog)
def accept(self, socket):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if not isinstance(socket, tco.DataLinkConnection):
raise err.Error(errno.EOPNOTSUPP)
while True:
client = socket.accept()
self.sap[client.addr].insert_socket(client)
log.debug("new data link connection ({0} <=== {1})"
.format(client.addr, client.peer))
if client.send_miu > self.cfg['send-miu']:
log.warn("reducing outbound miu to comply with link miu")
client.send_miu = self.cfg['send-miu']
return client
def poll(self, socket, event, timeout=None):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if not (socket.addr and self.sap[socket.addr]):
raise err.Error(errno.EBADF)
return socket.poll(event, timeout)
def close(self, socket):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
if socket.is_bound:
self.sap[socket.addr].remove_socket(socket)
else:
socket.close()
def getsockname(self, socket):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
return socket.addr
def getpeername(self, socket):
if not isinstance(socket, tco.TransmissionControlObject):
raise err.Error(errno.ENOTSOCK)
return socket.peer
def is_fatal_error(self, ex):
return isinstance(ex, socket.error) and ex[0] in (errno.EBADF, errno.EINVAL, errno.ENOTSOCK)
def is_socket(fd):
""" Determine whether the file descriptor is a socket.
:param fd: The file descriptor to interrogate.
:return: ``True`` iff the file descriptor is a socket; otherwise
``False``.
Query the socket type of `fd`. If there is no error, the file is a
socket.
"""
result = False
file_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_RAW)
try:
socket_type = file_socket.getsockopt(
socket.SOL_SOCKET, socket.SO_TYPE)
except socket.error as exc:
exc_errno = exc.args[0]
if exc_errno == errno.ENOTSOCK:
# Socket operation on non-socket.
pass
else:
# Some other socket error.
result = True
else:
# No error getting socket type.
result = True
return result
def is_fatal_error(self, ex):
return isinstance(ex, socket.error) and ex[0] in (errno.EBADF, errno.EINVAL, errno.ENOTSOCK)
def nl_recvmsg(sock):
"""
:param sock: netlink socket
:returns: a GENLMsg received from the socket
"""
try:
# we can expect two types of messages 1) an instant success message
# or 2) a data message. If it's a data message, we need to catch
# the ack
msg = nlmsg_fromstream(sock.recv())
try:
# catch the follow on ack
_ = nlmsg_fromstream(sock.recv())
except error as e:
# on success, just return the orginal message
if e.errno == nlh.NLE_SUCCESS: pass
else: raise
if sock.seq != msg.seq: raise error(errno.EBADMSG,"Seq. # out of order")
return msg
except socket.timeout:
raise error(-1,"Socket timed out")
#except socket.error as e: # this became in issue in python 3
# raise error(errno.ENOTSOCK,e)
except error as e:
if e.errno == nlh.NLE_SUCCESS: return nlh.NLE_SUCCESS
raise # rethrow
finally:
# always increment the sequence #
sock.incr()
def _getselectable(selectable_object):
try:
channel = selectable_object.getchannel()
except:
try:
channel = selectable_object.fileno().getChannel()
except:
raise TypeError("Object '%s' is not watchable" % selectable_object,
errno.ENOTSOCK)
if channel and not isinstance(channel, java.nio.channels.SelectableChannel):
raise TypeError("Object '%s' is not watchable" % selectable_object,
errno.ENOTSOCK)
return channel
def is_fatal_error(self, ex):
return isinstance(ex, socket.error) and ex[0] in (errno.EBADF, errno.EINVAL, errno.ENOTSOCK)
def _is_sockfd(self, sockfd):
try:
fd = self.files[sockfd]
if not isinstance(fd, SocketDesc):
return -errno.ENOTSOCK
return 0
except IndexError:
return -errno.EBADF
def sys_recv(self, sockfd, buf, count, flags):
try:
sock = self.files[sockfd]
except IndexError:
return -errno.EINVAL
if not isinstance(sock, Socket):
return -errno.ENOTSOCK
data = sock.read(count)
self.current.write_bytes(buf, data)
self.syscall_trace.append(("_recv", sockfd, data))
return len(data)
def sys_send(self, sockfd, buf, count, flags):
try:
sock = self.files[sockfd]
except IndexError:
return -errno.EINVAL
if not isinstance(sock, Socket):
return -errno.ENOTSOCK
data = self.current.read_bytes(buf, count)
#XXX(yan): send(2) is currently a nop; we don't communicate yet
self.syscall_trace.append(("_send", sockfd, data))
return count