Source code for nclib.server

from typing import Tuple
import socket
import select

from . import Netcat

[docs]class TCPServer: """ A simple TCP server model. Iterating over it will yield client sockets as Netcat objects. :param bindto: The address to bind to, a tuple (host, port) :param kernel_backlog: The argument to listen() Any additional keyword arguments will be passed to the constructor of the Netcat object that is constructed for each client. Here is a simple echo server example: >>> from nclib import TCPServer >>> server = TCPServer(('0.0.0.0', 1337)) >>> for client in server: ... client.send(client.recv()) # or submit to a thread pool for async handling... """
[docs] def __init__(self, bindto: Tuple[str, int], kernel_backlog: int=5, **kwargs): self.addr = bindto self.kwargs = kwargs self.sock = socket.socket(type=socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(bindto) self.sock.listen(kernel_backlog) self._oob_rsock, self._oob_wsock = socket.socketpair() self.closed = False
def __iter__(self): while True: rl, _, _ = select.select([self.sock, self._oob_rsock], [], []) if self._oob_rsock in rl: self._oob_rsock.close() self._oob_wsock.close() break client, addr = self.sock.accept() yield Netcat(sock=client, server=addr, **self.kwargs)
[docs] def close(self): """ Tear down this server and release its resources """ if not self.closed: self.closed = True self._oob_wsock.send(b'.') self.sock.close()
[docs]class UDPServer: """ A simple UDP server model. Iterating over it will yield of tuples of datagrams and peer addresses. To respond, use the respond method, which takes the response and the peer address. :param bindto: The address to bind to, a tuple (host, port) :param dgram_size: The size of the datagram to receive. This is important! If you send a message longer than the receiver's receiving size, the rest of the message will be silently lost! Default is 4096. Here is a simple echo server example: >>> from nclib import UDPServer >>> server = UDPServer(('0.0.0.0', 1337)) >>> for message, peer in server: ... server.respond(message, peer) # or submit to a thread pool for async handling... """
[docs] def __init__(self, bindto, dgram_size=4096): self.addr = bindto self.dgram_size = dgram_size self.sock = socket.socket(type=socket.SOCK_DGRAM) self.sock.bind(bindto)
def __iter__(self): while True: packet, peer = self.sock.recvfrom(self.dgram_size) yield packet, peer
[docs] def respond(self, packet, peer, flags=0): """ Send a message back to a peer. :param packet: The data to send :param peer: The address to send to, as a tuple (host, port) :param flags: Any sending flags you want to use for some reason """ self.sock.sendto(packet, flags, peer)
[docs] def close(self): """ Tear down this server and release its resources """ return self.sock.close()