From 84616652ed8622f987ada764613d84bdf4e42c7b Mon Sep 17 00:00:00 2001
From: Mattias Andrée <maandree@kth.se>
Date: Mon, 8 Aug 2016 23:23:55 +0200
Subject: ...
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Mattias Andrée <maandree@kth.se>
---
 src/libcoopgamma.py             | 29 ++++++++++---
 src/libcoopgamma_native.pyx.gpp | 92 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/src/libcoopgamma.py b/src/libcoopgamma.py
index 31f5aaa..9aae31b 100644
--- a/src/libcoopgamma.py
+++ b/src/libcoopgamma.py
@@ -596,7 +596,14 @@ class Context:
         @param  method:int|str?  The adjustment method, `None` for automatic
         @param  site:str?        The site, `None` for automatic
         '''
-        pass
+        if method is not None and isinstance(method, int):
+            method = str(method)
+        error = libcoopgamma_native_connect(method, site, self.address)
+        if error is not None:
+            if errno == 0:
+                pass # TODO server failed to initialise
+            else:
+                pass # TODO
     
     def detach(self):
         '''
@@ -625,7 +632,9 @@ class Context:
         
         @param  nonblocking:bool  Nonblocking mode?
         '''
-        pass
+        error = libcoopgamma_native.libcoopgamma_native_set_nonblocking(self.address, nonbreaking)
+        if error != 0:
+            pass # TODO
     
     def flush(self):
         '''
@@ -635,7 +644,9 @@ class Context:
         with EINTR, call this function to complete the transfer. The `async` parameter
         will always be in a properly configured state if a function fails with EINTR.
         '''
-        pass
+        error = libcoopgamma_native.libcoopgamma_native_flush(self.address)
+        if error != 0:
+            pass # TODO
     
     def synchronise(self, pending : list) -> int:
         '''
@@ -651,13 +662,21 @@ class Context:
                                              `None` if the message is ignored, which happens if
                                              corresponding AsyncContext is not listed.
         '''
-        pass
+        pending = [p.address for p in pending]
+        (successful, value) = libcoopgamma_native.libcoopgamma_native_flush(self.address, pending)
+        if not successful:
+            if error == 0:
+                return None
+            else:
+                pass # TODO
+        else:
+            return value
     
     def skip_message(self):
         '''
         Tell the library that you will not be parsing a receive message
         '''
-        pass
+        libcoopgamma_native.libcoopgamma_native_skip_message(self.address)
     
     def get_crtcs_send(self) -> AsyncContext:
         '''
diff --git a/src/libcoopgamma_native.pyx.gpp b/src/libcoopgamma_native.pyx.gpp
index 73d8353..b28c57b 100644
--- a/src/libcoopgamma_native.pyx.gpp
+++ b/src/libcoopgamma_native.pyx.gpp
@@ -1043,3 +1043,95 @@ def libcoopgamma_native_async_context_unmarshal(buf : bytes):
     ret0 = <int>libcoopgamma_async_context_unmarshal(this, <bytes>buf, &ret1)
     return (ret0, <int>ret1)
 
+
+def libcoopgamma_native_connect(method : str, site : str, address : int):
+    '''
+    Connect to a coopgamma server, and start it if necessary
+    
+    Use `libcoopgamma_context_destroy` to disconnect
+    
+    SIGCHLD must not be ignored or blocked
+    
+    @param   method:str?  The adjustment method, `NULL` for automatic
+    @param   site:str?    The site, `NULL` for automatic
+    @param   address:int  The address of the state of the library, must be initialised
+    @return  :int?        `None`, 0 if the server on could not be initialised,
+                          the value `errno` on other errors
+    '''
+    cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address
+    if libcoopgamma_connect(method, site, ctx) < 0:
+        return int(errno)
+    return None
+
+
+def libcoopgamma_native_set_nonblocking(address : int, nonblocking : bool):
+    '''
+    By default communication is blocking, this function
+    can be used to switch between blocking and nonblocking
+    
+    After setting the communication to nonblocking,
+    `libcoopgamma_flush`, `libcoopgamma_synchronise` and
+    and request-sending functions can fail with EAGAIN and
+    EWOULDBLOCK. It is safe to continue with `libcoopgamma_flush`
+    (for `libcoopgamma_flush` it selfand equest-sending functions)
+    or `libcoopgamma_synchronise` just like EINTR failure.
+    
+    @param   address:int       The address of the state of the library, must be connected
+    @param   nonblocking:bool  Nonblocking mode?
+    @return  :int              Zero on success, the value of `errno` on error
+    '''
+    cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address
+    if libcoopgamma_set_nonblocking(ctx, <int>(1 if nonblocking else 0)) < 0:
+        return int(errno)
+    return 0
+
+
+def libcoopgamma_native_flush(address : int):
+    '''
+    Send all pending outbound data
+    
+    If this function or another function that sends a request
+    to the server fails with EINTR, call this function to
+    complete the transfer. The `async` parameter will always
+    be in a properly configured state if a function fails
+    with EINTR.
+    
+    @param   address:int  The address of the state of the library, must be connected
+    @return  :int         Zero on success, the value of `errno` on error
+    '''
+    cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address
+    if libcoopgamma_flush(ctx) < 0:
+        return int(errno)
+    return 0
+
+
+def libcoopgamma_native_synchronise(address : int, pending : list):
+    '''
+    Wait for the next message to be received
+    
+    @param   address:int        The address of the state of the library, must be connected
+    @param   pending:list<int>  Addresses of the information for each pending request
+    @return  :(:bool, :int)     If [0] = 0: [1] is the value of `errno`
+                                   [0] = 1: [1] is the selected request
+    '''
+    cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address
+    cdef libcoopgamma_async_context_t* pends
+    cdef size_t selected = 0
+    pends = <libcoopgamma_async_context_t*>malloc(n * sizeof(*pends))
+    if pends is None:
+        pass
+    for i in range(len(pending)):
+        pends[i] = *<libcoopgamma_async_context_t*><void*><intptr_t>pendings[i]
+    if libcoopgamma_synchronise(ctx, pends, <size_t>len(pending), &selected) < 0:
+        return (False, int(errno))
+    return (True, <int>selected)
+
+
+def libcoopgamma_native_skip_message(address : int):
+    '''
+    Tell the library that you will not be parsing a receive message
+    
+    @param  address:int  The address of the state of the library, must be connected
+    '''
+    libcoopgamma_skip_message(<libcoopgamma_context_t*><void*><intptr_t>address)
+
-- 
cgit v1.2.3-70-g09d2