crossroads / crossroads / lowest.py

# -*- coding: utf-8 -*-
'''Lowest-level bindings to Crossroads.I/O.'''

from functools import partial
from ctypes.util import find_library
from ctypes import (
    Structure, CDLL, POINTER, memmove, get_errno, c_void_p, c_int, c_char_p,
    c_ubyte, c_size_t, c_short, c_ulong)

################################################################################
## UTILITIES ###################################################################
################################################################################
array = lambda ctype, length: (ctype * length)()


def _check_nonzero(result, func, arguments):
    if result == -1:
        raise XSError(get_errno())
    return result


def _check_not_null(result, func, arguments):
    if result is None:
        raise XSError(get_errno())
    return result


def _check_errno(result, func, arguments):
    errno = get_errno()
    if errno != 0:
        raise XSError(errno)
    return result

################################################################################
## CTYPES BINDING ##############################################################
################################################################################

def _factory(lib, prefix, restype, func, *args):
    newfunc = getattr(lib, '_'.join([prefix, func]))
    newfunc.argtypes = list(args)
    newfunc.restype = restype
    if newfunc.restype is c_int:
        newfunc.errcheck = _check_nonzero
    elif newfunc.restype is c_void_p:
        newfunc.errcheck = _check_not_null
    return newfunc

XS = CDLL(find_library('xs'), use_errno=True)
factory = partial(_factory, XS, 'xs')
intfactory = partial(_factory, XS, 'xs', c_int)
voidfactory = partial(_factory, XS, 'xs', c_void_p)
# memory mover
memmove.restype = c_void_p

################################################################################
## CROSSROADS VERSIONING SUPPORT ###############################################
################################################################################

version = voidfactory('version', POINTER(c_int), POINTER(c_int), POINTER(c_int))

################################################################################
## CROSSROADS ERRORS ###########################################################
################################################################################

# int xs_errno (void)
errno = intfactory('errno')

# const char *xs_strerror (int errnum)
strerror = factory(c_char_p, 'strerror', c_int)

################################################################################
## CROSSROADS MESSAGE DEFINITION ###############################################
################################################################################


class msg_t(Structure):

    # typedef struct {unsigned char _ [32];} xs_msg_t;
    _fields_ = [('_', c_ubyte * 32)]

# int xs_msg_init (xs_msg_t *msg);
msg_init = intfactory('msg_init', POINTER(msg_t))

# int xs_msg_init_size (xs_msg_t *msg, size_t size);
msg_init_size = intfactory('msg_init_size', POINTER(msg_t), c_size_t)

# int xs_msg_init_data (
#  xs_msg_t *msg, void *data, size_t size, xs_free_fn *ffn, void *hint
# );
# requires a free function for fourth argument e.g.
# typedef void (xs_free_fn) (void *data, void *hint);
msg_init_data = intfactory(
    'msg_init_data', POINTER(msg_t), c_void_p, c_size_t, c_void_p, c_void_p,
)

# int xs_msg_close (xs_msg_t *msg);
msg_close = intfactory('msg_close', POINTER(msg_t))

# int xs_msg_move (xs_msg_t *dest, xs_msg_t *src);
msg_move = intfactory('msg_move', POINTER(msg_t), POINTER(msg_t))

# int xs_msg_copy (xs_msg_t *dest, xs_msg_t *src);
msg_copy = intfactory('msg_copy', POINTER(msg_t), POINTER(msg_t))

# void *xs_msg_data (xs_msg_t *msg);
msg_data = voidfactory('msg_data', POINTER(msg_t))

# size_t xs_msg_size (xs_msg_t *msg);
msg_size = factory(c_size_t, 'msg_size', POINTER(msg_t))

# int xs_getmsgopt (xs_msg_t *msg, int option, void *optval, size_t *optvallen)
getmsgopt = intfactory(
    'getmsgopt', POINTER(msg_t), c_int, POINTER(c_int), POINTER(c_size_t)
)

################################################################################
## CROSSROADS CONTEXT DEFINITION ###############################################
################################################################################

# void *xs_init (void);
init = voidfactory('init')

# int xs_term (void *context);
term = intfactory('term', c_void_p)

# int xs_setctxopt (
#  void *context, int option, const void *optval, size_t optvallen
# );
setctxopt = intfactory('setctxopt', c_void_p, c_int, POINTER(c_int), c_size_t)

################################################################################
## CROSSROADS SOCKET DEFINITION ################################################
################################################################################

#void *xs_socket (void *context, int type);
socket = voidfactory('socket', c_void_p, c_int)

# int xs_close (void *s);
close = intfactory('close', c_void_p)

# int xs_setsockopt (void *s, int option, const void *optval, size_t optvallen)
setsockopt = intfactory('setsockopt', c_void_p, c_int, c_void_p, c_size_t)

# int xs_getsockopt (void *s, int option, void *optval, size_t *optvallen);
getsockopt = intfactory(
    'getsockopt', c_void_p, c_int, POINTER(c_int), POINTER(c_size_t)
)

# int xs_bind (void *s, const char *addr);
bind = intfactory('bind', c_void_p, c_char_p)

# int xs_connect (void *s, const char *addr);
connect = intfactory('connect', c_void_p, c_char_p)

# int xs_shutdown (void *s, int how);
shutdown = intfactory('shutdown', c_void_p, c_int)

# int xs_send (void *s, const void *buf, size_t len, int flags);
send = intfactory('send', c_void_p, c_void_p, c_size_t, c_int)

# int xs_recv (void *s, void *buf, size_t len, int flags);
recv = intfactory('recv', c_void_p, c_void_p, c_size_t, c_int)

# int xs_sendmsg (void *s, xs_msg_t *msg, int flags);
sendmsg = intfactory('sendmsg', c_void_p, POINTER(msg_t), c_int)

# int xs_recvmsg (void *s, xs_msg_t *msg, int flags);
recvmsg = intfactory('recvmsg', c_void_p, POINTER(msg_t), c_int)

################################################################################
## I/O MULTIPLEXING ############################################################
################################################################################


class pollitem_t(Structure):

    # typedef struct {
    #   void *socket; int fd; short events; short revents;
    # } xs_pollitem_t;

    _fields_ = [
        ('socket', c_void_p), ('fd', c_int),  ('events', c_short),
        ('revents', c_short),
    ]

# int xs_poll (xs_pollitem_t *items, int nitems, int timeout);
poll = intfactory('poll', POINTER(pollitem_t), c_int, c_int)

# Starts the stopwatch. Returns the handle to the watch.
# void *xs_stopwatch_start (void);
stopwatch_start = voidfactory('stopwatch_start')

# Stops the stopwatch. Returns the number of microseconds elapsed since the
# stopwatch was started.
# unsigned long xs_stopwatch_stop (void *watch);
stopwatch_stop = factory(c_ulong, 'stopwatch_stop', c_void_p)

################################################################################
## EXCEPTIONS ##################################################################
################################################################################


class XSBaseError(Exception):
    '''Base exception.'''


class XSOperationError(XSBaseError):
    '''Operational Error.'''


class XSError(XSBaseError):

    def __init__(self, errno=None):
        if errno is None:
            errno = get_errno()
        self.strerror = strerror(errno)
        self.errno = errno

    def __str__(self):
        return '{self.errno}: {self.strerror}'.format(self=self)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.