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]))
|
assert(isinstance(value, parameter[0]))
|
||||||
setattr(self, parameter[1], value)
|
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):
|
class MessageTick(Message):
|
||||||
code = 0
|
code = 0
|
||||||
parameters = []
|
parameters = []
|
||||||
|
@ -21,11 +29,11 @@ class MessageGo(Message):
|
||||||
|
|
||||||
class MessageWrite(Message):
|
class MessageWrite(Message):
|
||||||
code = 2
|
code = 2
|
||||||
parameters = [(str, "signal"), (int, "value")]
|
parameters = [(str, "name"), (int, "value")]
|
||||||
|
|
||||||
class MessageRead(Message):
|
class MessageRead(Message):
|
||||||
code = 3
|
code = 3
|
||||||
parameters = [(str, "signal")]
|
parameters = [(str, "name")]
|
||||||
|
|
||||||
class MessageReadReply(Message):
|
class MessageReadReply(Message):
|
||||||
code = 4
|
code = 4
|
||||||
|
@ -38,16 +46,21 @@ message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageRea
|
||||||
#
|
#
|
||||||
|
|
||||||
def _pack_int(v):
|
def _pack_int(v):
|
||||||
# TODO
|
p = []
|
||||||
return []
|
while v != 0:
|
||||||
|
p.append(v & 0xff)
|
||||||
|
v >>= 8
|
||||||
|
p.insert(0, len(p))
|
||||||
|
return p
|
||||||
|
|
||||||
def _pack_str(v):
|
def _pack_str(v):
|
||||||
# TODO
|
p = [ord(c) for c in v]
|
||||||
return []
|
p.append(0)
|
||||||
|
return p
|
||||||
|
|
||||||
def _pack(message):
|
def _pack(message):
|
||||||
r = [message.code]
|
r = [message.code]
|
||||||
for p, t in message.parameters:
|
for t, p in message.parameters:
|
||||||
value = getattr(message, p)
|
value = getattr(message, p)
|
||||||
assert(isinstance(value, t))
|
assert(isinstance(value, t))
|
||||||
if t == int:
|
if t == int:
|
||||||
|
@ -63,19 +76,28 @@ def _pack(message):
|
||||||
#
|
#
|
||||||
|
|
||||||
def _unpack_int(i):
|
def _unpack_int(i):
|
||||||
# TODO
|
v = 0
|
||||||
return 0
|
power = 1
|
||||||
|
nchunks = next(i)
|
||||||
|
for j in range(nchunks):
|
||||||
|
v += power*next(i)
|
||||||
|
power *= 256
|
||||||
|
return v
|
||||||
|
|
||||||
def _unpack_str(i):
|
def _unpack_str(i):
|
||||||
# TODO
|
v = ""
|
||||||
return ""
|
c = next(i)
|
||||||
|
while c:
|
||||||
|
v += chr(c)
|
||||||
|
c = next(i)
|
||||||
|
return v
|
||||||
|
|
||||||
def _unpack(message):
|
def _unpack(message):
|
||||||
i = iter(message)
|
i = iter(message)
|
||||||
code = next(i)
|
code = next(i)
|
||||||
msgclass = next(filter(lambda x: x.code == code, message_classes))
|
msgclass = next(filter(lambda x: x.code == code, message_classes))
|
||||||
pvalues = []
|
pvalues = []
|
||||||
for p, t in msgclass.parameters:
|
for t, p in msgclass.parameters:
|
||||||
if t == int:
|
if t == int:
|
||||||
v = _unpack_int(i)
|
v = _unpack_int(i)
|
||||||
elif t == str:
|
elif t == str:
|
||||||
|
@ -113,8 +135,10 @@ class Initiator:
|
||||||
self.conn.send(_pack(message))
|
self.conn.send(_pack(message))
|
||||||
|
|
||||||
def recv(self):
|
def recv(self):
|
||||||
maxlen = 4096
|
maxlen = 2048
|
||||||
packet = self.conn.recv(maxlen)
|
packet = self.conn.recv(maxlen)
|
||||||
|
if len(packet) < 1:
|
||||||
|
return None
|
||||||
if len(packet) >= maxlen:
|
if len(packet) >= maxlen:
|
||||||
raise PacketTooLarge
|
raise PacketTooLarge
|
||||||
return _unpack(packet)
|
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