sim: two way IPC working
This commit is contained in:
parent
8586daf2dd
commit
29859acc34
|
@ -11,6 +11,14 @@ class Message:
|
|||
assert(isinstance(value, parameter[0]))
|
||||
setattr(self, parameter[1], value)
|
||||
|
||||
def __str__(self):
|
||||
p = ""
|
||||
for parameter in self.parameters:
|
||||
p += parameter[1] + "=" + str(getattr(self, parameter[1]))
|
||||
if p:
|
||||
p = " " + p
|
||||
return "<" + self.__class__.__name__ + p + ">"
|
||||
|
||||
class MessageTick(Message):
|
||||
code = 0
|
||||
parameters = []
|
||||
|
@ -21,11 +29,11 @@ class MessageGo(Message):
|
|||
|
||||
class MessageWrite(Message):
|
||||
code = 2
|
||||
parameters = [(str, "signal"), (int, "value")]
|
||||
parameters = [(str, "name"), (int, "value")]
|
||||
|
||||
class MessageRead(Message):
|
||||
code = 3
|
||||
parameters = [(str, "signal")]
|
||||
parameters = [(str, "name")]
|
||||
|
||||
class MessageReadReply(Message):
|
||||
code = 4
|
||||
|
@ -38,16 +46,21 @@ message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageRea
|
|||
#
|
||||
|
||||
def _pack_int(v):
|
||||
# TODO
|
||||
return []
|
||||
p = []
|
||||
while v != 0:
|
||||
p.append(v & 0xff)
|
||||
v >>= 8
|
||||
p.insert(0, len(p))
|
||||
return p
|
||||
|
||||
def _pack_str(v):
|
||||
# TODO
|
||||
return []
|
||||
p = [ord(c) for c in v]
|
||||
p.append(0)
|
||||
return p
|
||||
|
||||
def _pack(message):
|
||||
r = [message.code]
|
||||
for p, t in message.parameters:
|
||||
for t, p in message.parameters:
|
||||
value = getattr(message, p)
|
||||
assert(isinstance(value, t))
|
||||
if t == int:
|
||||
|
@ -63,19 +76,28 @@ def _pack(message):
|
|||
#
|
||||
|
||||
def _unpack_int(i):
|
||||
# TODO
|
||||
return 0
|
||||
v = 0
|
||||
power = 1
|
||||
nchunks = next(i)
|
||||
for j in range(nchunks):
|
||||
v += power*next(i)
|
||||
power *= 256
|
||||
return v
|
||||
|
||||
def _unpack_str(i):
|
||||
# TODO
|
||||
return ""
|
||||
v = ""
|
||||
c = next(i)
|
||||
while c:
|
||||
v += chr(c)
|
||||
c = next(i)
|
||||
return v
|
||||
|
||||
def _unpack(message):
|
||||
i = iter(message)
|
||||
code = next(i)
|
||||
msgclass = next(filter(lambda x: x.code == code, message_classes))
|
||||
pvalues = []
|
||||
for p, t in msgclass.parameters:
|
||||
for t, p in msgclass.parameters:
|
||||
if t == int:
|
||||
v = _unpack_int(i)
|
||||
elif t == str:
|
||||
|
@ -113,8 +135,10 @@ class Initiator:
|
|||
self.conn.send(_pack(message))
|
||||
|
||||
def recv(self):
|
||||
maxlen = 4096
|
||||
maxlen = 2048
|
||||
packet = self.conn.recv(maxlen)
|
||||
if len(packet) < 1:
|
||||
return None
|
||||
if len(packet) >= maxlen:
|
||||
raise PacketTooLarge
|
||||
return _unpack(packet)
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ipc.h"
|
||||
|
||||
struct ipc_softc {
|
||||
int socket;
|
||||
go_handler h_go;
|
||||
write_handler h_write;
|
||||
read_handler h_read;
|
||||
void *user;
|
||||
};
|
||||
|
||||
struct ipc_softc *ipc_connect(const char *sockaddr,
|
||||
go_handler h_go, write_handler h_write, read_handler h_read, void *user)
|
||||
{
|
||||
struct ipc_softc *sc;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
sc = malloc(sizeof(struct ipc_softc));
|
||||
if(!sc) return NULL;
|
||||
|
||||
sc->h_go = h_go;
|
||||
sc->h_write = h_write;
|
||||
sc->h_read = h_read;
|
||||
sc->user = user;
|
||||
|
||||
sc->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if(sc->socket < 0) {
|
||||
free(sc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, sockaddr);
|
||||
if(connect(sc->socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
|
||||
close(sc->socket);
|
||||
free(sc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
void ipc_destroy(struct ipc_softc *sc)
|
||||
{
|
||||
close(sc->socket);
|
||||
free(sc);
|
||||
}
|
||||
|
||||
enum {
|
||||
MESSAGE_TICK = 0,
|
||||
MESSAGE_GO,
|
||||
MESSAGE_WRITE,
|
||||
MESSAGE_READ,
|
||||
MESSAGE_READ_REPLY
|
||||
};
|
||||
|
||||
#define MAX_LEN 2048
|
||||
|
||||
int ipc_receive(struct ipc_softc *sc)
|
||||
{
|
||||
char buffer[MAX_LEN];
|
||||
ssize_t l;
|
||||
int i;
|
||||
|
||||
l = recv(sc->socket, buffer, MAX_LEN, 0);
|
||||
if((l <= 0) || (l >= MAX_LEN))
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
switch(buffer[i++]) {
|
||||
case MESSAGE_GO:
|
||||
assert(l == 1);
|
||||
return sc->h_go(sc->user);
|
||||
case MESSAGE_WRITE: {
|
||||
char *name;
|
||||
int nchunks;
|
||||
unsigned char *chunks;
|
||||
|
||||
name = &buffer[i];
|
||||
i += strlen(name) + 1;
|
||||
assert(i < l);
|
||||
nchunks = buffer[i++];
|
||||
assert(i + nchunks == l);
|
||||
chunks = (unsigned char *)&buffer[i];
|
||||
|
||||
return sc->h_write(name, nchunks, chunks, sc->user);
|
||||
}
|
||||
case MESSAGE_READ: {
|
||||
char *name;
|
||||
|
||||
name = &buffer[i];
|
||||
i += strlen(name) + 1;
|
||||
assert(i == l);
|
||||
|
||||
return sc->h_read(name, sc->user);
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ipc_tick(struct ipc_softc *sc)
|
||||
{
|
||||
char c;
|
||||
ssize_t l;
|
||||
|
||||
c = MESSAGE_TICK;
|
||||
l = send(sc->socket, &c, 1, 0);
|
||||
if(l != 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *chunks)
|
||||
{
|
||||
int len;
|
||||
char buffer[MAX_LEN];
|
||||
ssize_t l;
|
||||
|
||||
len = nchunks + 2;
|
||||
assert(len < MAX_LEN);
|
||||
assert(nchunks < 256);
|
||||
|
||||
buffer[0] = MESSAGE_READ_REPLY;
|
||||
buffer[1] = nchunks;
|
||||
memcpy(&buffer[2], chunks, nchunks);
|
||||
|
||||
l = send(sc->socket, buffer, len, 0);
|
||||
if(l != len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __IPC_H
|
||||
#define __IPC_H
|
||||
|
||||
struct ipc_softc;
|
||||
|
||||
typedef int(*go_handler)(void *);
|
||||
typedef int(*write_handler)(char *, int, const unsigned char *, void *);
|
||||
typedef int(*read_handler)(char *, void *);
|
||||
|
||||
struct ipc_softc *ipc_connect(const char *sockaddr,
|
||||
go_handler h_go, write_handler h_write, read_handler h_read, void *user);
|
||||
void ipc_destroy(struct ipc_softc *sc);
|
||||
|
||||
int ipc_receive(struct ipc_softc *sc);
|
||||
|
||||
int ipc_tick(struct ipc_softc *sc);
|
||||
int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *value);
|
||||
|
||||
#endif /* __IPC_H */
|
Loading…
Reference in New Issue