peng3dnet.net - Core Networking Classes

peng3dnet.net.STRUCT_HEADER = <Struct object>

struct.Struct instance used for rapid encoding and decoding of header data.

See also

See peng3dnet.constants.STRUCT_FORMAT_HEADER for more information.

peng3dnet.net.STRUCT_LENGTH32 = <Struct object>

struct.Struct instance used for rapid encoding and decoding of the length prefix.

See also

See peng3dnet.constants.STRUCT_FORMAT_LENGTH32 for more information.

class peng3dnet.net.Server(peng=None, addr=None, clientcls=None, cfg=None)[source]

Server class representing the server side of the client-server relationship.

Usually, a server will be able to serve many clients simultaneously without problems. This is achieved using the selectors standard library module, which internally uses select or similiar techniques.

If given, peng should be an instance of peng3d.peng.Peng and will be used for sending events and the configuration system. Note that without a valid peng parameter, the event system will not work and a custom config stack will be created. If a peng parameter is given, its config stack will be adapted and the event system enabled.

See also

See net.events.enable and Events used by peng3dnet for more information on the event system.

addr, if given, should be a value parseable by peng3dnet.util.normalize_addr_socketstyle(). If addr is not given, first net.server.addr is tried, then net.server.addr.host and net.server.addr.port. If any given address is missing an explicitly specified port, net.server.addr.port is supplemented.

clientcls may be used to override the class used for creating new client-on-server objects. Defaults to ClientOnServer.

cfg may be used to override initial configuration values and should be a dictionary.

addConnType(t, obj)[source]

Adds a connection type to the internal registry.

t should be the string name of the connection type.

obj should be an instance of a subclass of peng3dnet.conntypes.ConnectionType().

Trying to register a name multiple times will cause an AlreadyRegisteredError.

bind()[source]

Creates and binds the socket used for listening for new connections.

Repeated calls of this method will be ignored.

If SSL is enabled, an SSL context will be created and the socket wrapped according to the SSL settings.

See also

See net.ssl.enabled for more information about the SSL configuration.

Currently, the socket will be configured to listen for up to 100 connection requests in parallel.

After binding of the socket, the event peng3dnet:server.bind will be sent.

close_connection(cid, reason=None)[source]

Closes the connection to the given peer due to the optional reason.

cid should be the Client ID number.

reason may be a string describing the reason.

genCID()[source]

Generates a client ID number.

These IDs are guaranteed to be unique to the instance that generated them.

Usually, these will be integers that simply count up and are not meant to be cryptographically secure.

initialize()[source]

Initializes internal registries used during runtime.

Calling this method repeatedly will be ignored.

Currently, this registers packets and connection types. Additionally, the peng3dnet:server.initialize event is sent.

Subclasses and Mix-ins may hook into this method via definition of methods named _reg_packets_* or _reg_conntypes_* with the star being an arbitrary string. The method may not take any arguments.

interrupt()[source]

Wakes up the main loop by sending a special message to an internal socket.

This forces the main loop to iterate once and check that the system is still running.

Also sends the peng3dnet:server.interrupt event.

join(timeout=None)[source]

Waits for all spawned threads to finish.

If timeout is given, it indicates the total amount of time spent waiting.

If a thread has not been started yet, it will be skipped and not waited for.

process(wait=False, timeout=None)[source]

Processes all packets awaiting processing.

If wait is true, this function will wait up to timeout seconds for new data to arrive.

It will then process all packets in the queue, decoding them and then calling the appropriate event handlers. This method assumes all messages are packed with msgpack.

If the connection type allows it, event handlers will be called and the peng3dnet:server.connection.recv event is sent.

This method returns the number of packets processed.

process_async()[source]

Processes packets asynchronously.

Internally calls process_forever() in a separate daemon thread named peng3dnet process Thread.

process_forever()[source]

Processes packets in a blocking manner.

Note that this method is currently not interruptable and thus uses short timeouts of about 10ms, causing a slight delay in stopping this loop.

process_single_packet(client)[source]

Called when there should be enough data to process a single packet.

client is an instance of ClientOnServer representing the client.

Currently parses a single packet including length prefix and calls receive_packet() with the packet data.

receive_data(data, cid)[source]

Called when new raw data has been read from a socket.

Note that the given data may contain only parts of a packet or even multiple packets.

cid is the integer ID number of the client the data was received from.

By default, the received data is stored in a buffer until enough data is available to process a packet, then process_single_packet() is called.

receive_packet(data, cid)[source]

Called when a full packet has been received.

data is the raw packet data without length prefix.

cid is the integer ID number of the client.

Currently, this puts the data in a queue to be processed further by process().

register_packet(name, obj, n=None)[source]

Registers a new packet with the internal registry.

name should be a string of format namespace:category.subcategory.name where category may be repeated.

obj should be an instance of a subclass of peng3dnet.packet.Packet().

n may be optionally used to force a packet to use a specific packet ID, otherwise one will be generated.

runAsync(selector=<class 'selectors.EpollSelector'>)[source]

Runs the server main loop in a seperate thread.

selector may be changed to override the selector used for smart waiting.

This method does not block and should return immediately.

The newly created thread will be named peng3dnet Server Thread and is a daemon thread, i.e. it will not keep the program alive.

runBlocking(selector=<class 'selectors.EpollSelector'>)[source]

Runs the server main loop in a blocking manner.

selector may be changed to override the selector used for smart waiting.

This method blocks until stop() is called.

sendEvent(event, data=None)[source]

Helper method used to send events.

Checks if the event system is enabled, adds the peng and server data attributes and then sends it.

send_message(ptype, data, cid)[source]

Sends a message to the specified peer.

ptype should be a valid packet type, e.g. either an ID, name or object.

data should be the data to send to the peer.

cid should be the Client ID number to send the message to.

Note that all data encoding will be done synchronously and may cause this method to not return immediately. The packet may also be encrypted and compressed, if applicable.

Additionally, the peng3dnet:server.connection.send event is sent if the connection type allows it.

shutdown(join=True, timeout=0, reason='servershutdown')[source]

Shuts down the server, disconnecting all clients.

If join is true, this method will block until all clients are disconnected or timeout seconds have passed. If timeout is 0, it will be ignored.

reason will be used as the closing reason and transmitted to all clients.

After these messages have been sent, stop() is called and the peng3dnet:server.shutdown event is sent.

stop()[source]

Stops the running server main loop.

Will set an internal flag, then sends the event peng3dnet:server.stop and calls interrupt() to force the close.

Note that this will not close open connections properly, use shutdown() instead.

class peng3dnet.net.ClientOnServer(server, conn, addr, cid)[source]

Class representing a client on the server.

This serves mainly as a data structure for storing the state of a specific connection.

This class is not intended to be created manually.

server is the instance of Server that created this object.

conn is the socket that should be used for communication with this client.

addr is the address of this client.

cid is the unique Client ID assigned to this client.

close(reason=None)[source]

Called to close the connection to this client.

This method is not an event handler, use on_close() instead.

on_close(reason=None)[source]

Called when the connection has been closed.

reason is the reason sent either by the peer or passed by the caller of Server.close_connection().

on_connect()[source]

Sent once a connection has been established.

Note that at the time this method is called the handshake may not be finished, see on_handshake_complete() instead.

on_handshake_complete()[source]

Called when the handshake has been completed.

The default implementation sends the peng3dnet:server.connection.handshakecomplete event and changes the connection state to STATE_ACTIVE.

May be overridden by subclasses.

on_receive(ptype, msg)[source]

Called when a packet has been received.

ptype will be an integer or string representing the packet type.

msg will be a Python object decoded from the raw message via messagepack.

on_send(ptype, msg)[source]

Called when a packet has been sent.

ptype will be the packet type in either string, integer or object form.

msg will be the Python object that has been encoded and sent via messagepack.

class peng3dnet.net.Client(peng=None, addr=None, cfg=None, conntype='classic')[source]

Client class representing the client side of the client-server relationship.

A client can only be connected to a single server during its lifetime, recycling of client instances is not supported.

If given, peng should be an instance of peng3d.peng.Peng and will be used for sending events and the configuration system. Note that without a valid peng parameter, the event system will not work and a custom config stack will be created. If a peng parameter is given, its config stack will be adapted and the event system enabled.

See also

See net.events.enable and Events used by peng3dnet for more information on the event system.

addr, if given, should be a value parseable by peng3dnet.util.normalize_addr_socketstyle(). If addr is not given, first net.client.addr is tried, then net.client.addr.host and net.client.addr.port. If any given address is missing an explicitly specified port, net.client.addr.port is supplemented.

cfg may be used to override initial configuration values and should be a dictionary.

Optionally, the connection type may be specified via conntype, which may be set to a string identifying the type of the connection. This should usually be CONNTYPE_CLASSIC or one of the other CONNTYPE_* constants. Note that the connection type specified must also be registered via addConnType(), except for the built-in connection types.

addConnType(t, obj)[source]

Adds a connection type to the internal registry.

t should be the string name of the connection type.

obj should be an instance of a subclass of peng3dnet.conntypes.ConnectionType().

Trying to register a name multiple times will cause an AlreadyRegisteredError.

close(reason=None)[source]

Called to close the connection to the server.

This method is not an event handler, use on_close() instead.

Also sends the event peng3dnet:client.close.

close_connection(cid=None, reason=None)[source]

Closes the connection to the server due to the optional reason.

cid is a dummy value used for compatibility with server applications.

reason may be a string describing the reason.

connect()[source]

Connects the client with a server.

Note that the server must have been specified before calling this method via either the addr argument to the initializer or any of the net.client.addr config values.

Repeated calls of this method will be ignored.

If SSL is enabled, this method will also initialize the SSL Context and load the certificates.

After the connection has been made, the peng3dnet.client.connect event is sent.

initialize()[source]

Initializes internal registries used during runtime.

Calling this method repeatedly will be ignored.

Currently, this registers packets and connection types. Additionally, the peng3dnet:client.initialize event is sent.

Subclasses and Mix-ins may hook into this method via definition of methods named _reg_packets_* or _reg_conntypes_* with the star being an arbitrary string. The methods may not take any arguments.

interrupt()[source]

Wakes up the main loop by sending a special message to an internal socket.

This forces the main loop to iterate once and check that the system is still running.

Also sends the peng3dnet:client.interrupt event.

join(timeout=None)[source]

Waits for all spawned threads to finish.

If timeout is given, it indicates the total amount of time spent waiting.

If a thread has not been started yet, it will be skipped and not waited for.

on_close(reason=None)[source]

Event handler called during connection shutdown.

It may or may not be possible to send data over the connection within this method, depending on various factors.

on_connect()[source]

Event handler called once a connection has been established.

Note that usually the handshake will still be in progress while this method is called.

See also

See the on_handshake_complete() event handler for a better indicator when data can be sent.

on_handshake_complete()[source]

Callback called once the handshake has been completed.

The default implementation sends the peng3dnet:client.handshakecomplete event and sets the connection state to STATE_ACTIVE.

on_receive(ptype, msg)[source]

Event handler called if data is received from the peer.

on_send(ptype, msg)[source]

Event handler called if data is sent to the peer.

process(wait=False, timeout=None)[source]

Processes all packets awaiting processing.

If wait is true, this function will wait up to timeout seconds for new data to arrive.

It will then process all packets in the queue, decoding them and then calling the appropriate event handlers. This method assumes all messages are packed with msgpack.

If the connection type allows it, event handlers will be called and the peng3dnet:client.recv event is sent.

This method returns the number of packets processed.

process_async()[source]

Processes packets asynchronously.

Internally calls process_forever() in a separate daemon thread named peng3dnet process Thread.

process_forever()[source]

Processes packets in a blocking manner.

Note that this method is currently not interruptable and thus uses short timeouts of about 10ms, causing a slight delay in stopping this loop.

process_single_packet(client=None)[source]

Called when there should be enough data to process a single packet.

client is a dummy value used for compatibilizy with server applications.

Currently parses a single packet including length prefix and calls receive_packet() with the packet data.

pump_write_buffer()[source]

Tries to send as much of the data in the internal buffer as possible.

Note that depending on various factors, not all data may be sent at once. It is possible that sent data will be fragmented at arbitrary points.

If an exception occurs while sending the data, it will be ignored and the error printed to the console.

receive_data(data, cid=None)[source]

Called when new raw data has been read from the socket.

Note that the given data may contain only parts of a packet or even multiple packets.

cid is a dummy value used for compatibility with server applications.

By default, the received data is stored in a buffer until enough data is available to process a packet, then process_single_packet() is called.

receive_packet(data, cid=None)[source]

Called when a full packet has been received.

data is the raw packet data without length prefix.

cid is a dummy value used for compatibility with server applications.

Currently, this puts the data in a queue to be processed further by process().

register_packet(name, obj, n=None)[source]

Registers a new packet with the internal registry.

name should be a string of format namespace:category.subcategory.name where category may be repeated.

obj should be an instance of a subclass of peng3dnet.packet.Packet().

n may be optionally used to force a packet to use a specific packet ID, otherwise one will be generated.

runAsync(selector=<class 'selectors.EpollSelector'>)[source]

Runs the client main loop in a seperate thread.

selector may be changed to override the selector used for smart waiting.

This method does not block and should return immediately.

The newly created thread will be named peng3dnet Client Thread and is a daemon thread, i.e. it will not keep the program alive.

runBlocking(selector=<class 'selectors.EpollSelector'>)[source]

Runs the client main loop in a blocking manner.

selector may be changed to override the selector used for smart waiting.

This method blocks until stop() is called.

sendEvent(event, data)[source]

Helper method used to send events.

Checks if the event system is enabled, adds the peng and client data attributes and then sends it.

send_message(ptype, data, cid=None)[source]

Sends a message to the server.

ptype should be a valid packet type, e.g. either an ID, name or object.

data should be the data to send to the server.

cid will be ignored, available for compatibility with server applications.

Note that all data encoding will be done synchronously and may cause this method to not return immediately. The packet may also be encrypted and compressed, if applicable.

Additionally, the peng3dnet:client.send event is sent if the connection type allows it.

stop()[source]

Stops the running client main loop.

Will set an internal flag, then sends the event peng3dnet:client.stop and calls interrupt() to force the close.

Note that this will not close open connections properly, call close_connection() before calling this method.

wait_for_close(timeout=None)[source]

Waits up to timeout seconds for the connection to close.

Returns immediately if the connection is already closed.

wait_for_connection(timeout=None)[source]

Waits up to timeout seconds for the connection to be established.

Returns immediately if there is an active connection.