"""
TIPC python wrapper
Alberto Bertogli (albertito@gmail.com)
Addresses are expressed as (addr_type, v1, v2, v3 [, scope]);
where addr_type can be one of:
TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, and TIPC_ADDR_ID;
and scope can be one of:
TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and TIPC_NODE_SCOPE.
The meaning of v1, v2 and v3 depend on the value of addr_type:
if addr_type is TIPC_ADDR_NAME:
v1 is the server type
v2 is the port identifier
v3 is ignored
if addr_type is TIPC_ADDR_NAMESEQ:
v1 is the server type
v2 is the lower port number
v3 is the upper port number
if addr_type is TIPC_ADDR_ID:
v1 is the node
v2 is the ref
v3 is ignored
Even when ignored, v3 must be present and be an integer.
"""
import os
import socket as socketmodule
import tipc_ll
# Exported constants
from tipc_ll import AF_TIPC, SOL_TIPC, \
TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, TIPC_ADDR_ID, \
TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, TIPC_NODE_SCOPE, \
TIPC_IMPORTANCE, \
TIPC_SRC_DROPPABLE, TIPC_DEST_DROPPABLE, \
TIPC_CONN_TIMEOUT, \
TIPC_LOW_IMPORTANCE, TIPC_MEDIUM_IMPORTANCE, \
TIPC_HIGH_IMPORTANCE, TIPC_CRITICAL_IMPORTANCE, \
TIPC_SUB_PORTS, TIPC_SUB_SERVICE, TIPC_SUB_CANCEL, \
TIPC_WAIT_FOREVER, \
TIPC_PUBLISHED, TIPC_WITHDRAWN, TIPC_SUBSCR_TIMEOUT, \
TIPC_CFG_SRV, TIPC_TOP_SRV
class TIPCSocket:
def __init__(self, stype, fd = None):
if not fd:
self.fd = tipc_ll.socket(stype)
else:
self.fd = fd
self.closed = 0
self.psock = socketmodule.fromfd(self.fd, AF_TIPC, stype)
self.family = AF_TIPC
self.type = stype
self.proto = 0
def __del__(self):
self.close()
# Friendly functions for the ones implemented in tipc_ll
def connect(self, addr):
"Connects to the given server."
return tipc_ll.connect(self.fd, addr)
def bind(self, addr):
"Binds to the given address."
return tipc_ll.bind(self.fd, addr)
def accept(self):
"Accepts a new connection, returns (conn, addr)."
newfd, addr = tipc_ll.accept(self.fd)
return (TIPCSocket(self.type, fd = newfd), addr)
def sendto(self, buf, addr):
"Sends a message/buffer to the given address."
return tipc_ll.sendto(self.fd, buf, addr)
def recvfrom(self, maxlen = 64 * 1024):
"Receives a message/buffer, returns (buffer, address)."
return tipc_ll.recvfrom(self.fd, maxlen)
def close(self):
"Closes the socket."
if not self.closed:
self.closed = 1
return os.close(self.fd)
def getsockname(self):
return tipc_ll.getsockname(self.fd)
# Other useful functions, some of them based on socketmodule
def fileno(self):
"Returns the file descriptor number."
return self.fd
def send(self, buf):
"Sends a message/buffer."
return self.psock.send(buf)
def recv(self, bufsize):
"Receives a message/buffer."
b, a = self.recvfrom(bufsize)
return b
def listen(self, backlog):
"Listen for connections made to the socket."
return self.psock.listen(backlog)
def setblocking(self, flag):
"Set blocking or non-blocking mode for the socket."
return self.psock.setblocking(flag)
def getsockopt(self, level, optname, buflen = None):
"""Return the value of the given socket option (see the Unix
man page getsockopt(2))."""
if not buflen:
return self.psock.getsockopt(level, optname)
return self.psock.getsockopt(level, optname, buflen)
def setsockopt(self, level, optname, value):
"""Set the value of the given socket option (see the Unix
manual page setsockopt(2))"""
return self.psock.setsockopt(level, optname, value)
def shutdown(self, how):
"Shut down one or both halves of the connection."
return self.psock.shutdown(how)
# Subscription handling
def send_subscr(self, addr, timeout = None, filter = TIPC_SUB_SERVICE):
"""
Sends a subscription message to the server (the socket must
be connected to TIPC_ADDR_NAME, TIPC_TOP_SRV, TIPC_TOP_SRV, 0)
for this to work).
- addr: specifies the address to wait for (can be a name or a
nameseq).
- timeout: timeout in milliseconds (use None to wait
forever), defaults to None.
- filter: Either TIPC_SUB_SERVICE or TIPC_SUB_PORTS, see TIPC
documentation for details. Defaults to TIPC_SUB_SERVICE.
"""
if not timeout:
timeout = TIPC_WAIT_FOREVER
atype, stype, lower, upper = addr[:4]
if atype == TIPC_ADDR_NAME:
upper = lower
subs = tipc_ll.build_subscr(stype, lower, upper,
timeout, filter)
self.send(subs)
def recv_subscr_event(self):
"""
Receives a subscription event from the socket.
It returns None if there was an error receiving the
subscription, or the tuple:
( event, found_lower, found_upper,
(srv_type, lower, upper, timeout, filter) )
- event: one of TIPC_SUBSCR_TIMEOUT, TIPC_PUBLISHED or
TIPC_WITHDRAWN.
- found_lower, found_upper: the lower and upper ports found.
- (srv_type, lower, upper, timeout, filter): information on
the subscription that generated the event (see send_subscr()
for details).
"""
buf = self.recv(4092)
return tipc_ll.parse_event(buf)
def socket(stype):
"""
Creates and returns a socket object of the given type.
The type can be one of SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM and
SOCK_DGRAM, see TIPC documentation for more information.
"""
return TIPCSocket(stype)
def wait_for(addr, timeout = None, filter = None):
"""
Waits for a server to appear on the given address.
If a timeout is specified and no server came up after that number of
milliseconds, returns None.
The optional filter parameter can be either TIPC_SUB_SERVICE or
TIPC_SUB_PORTS, see TIPC documentation for more details; it defaults
to TIPC_SUB_SERVICE.
If there are any errors, return None; otherwise return an event tuple
composed of:
( event, found_lower, found_upper,
(srv_type, lower, upper, timeout, filter) )
- event: one of TIPC_SUBSCR_TIMEOUT, TIPC_PUBLISHED or
TIPC_WITHDRAWN.
- found_lower, found_upper: the lower and upper ports found.
- (srv_type, lower, upper, timeout, filter): information on
the subscription that generated the event (see send_subscr()
for details).
"""
fd = socket(socketmodule.SOCK_SEQPACKET)
if not timeout:
timeout = TIPC_WAIT_FOREVER
if not filter:
filter = TIPC_SUB_SERVICE
topsrv_addr = (TIPC_ADDR_NAME, TIPC_TOP_SRV,
TIPC_TOP_SRV, TIPC_TOP_SRV)
fd.connect(topsrv_addr)
fd.send_subscr(addr, timeout, filter)
return fd.recv_subscr_event()