Skip to content

Commit 98cf103

Browse files
committedMay 13, 2015
vpi: fix and simplify windows simulation (ends of msg were ignored)
1 parent b0f1594 commit 98cf103

File tree

2 files changed

+71
-78
lines changed

2 files changed

+71
-78
lines changed
 

‎migen/sim/ipc.py

+22-31
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import sys
77
import struct
88

9+
if sys.platform == "win32":
10+
header_len = 2
911

1012
#
1113
# Message classes
@@ -108,7 +110,7 @@ def _pack(message):
108110
else:
109111
raise TypeError
110112
if sys.platform == "win32":
111-
size = _pack_int16(len(r) + 2) # size specifier adds to size
113+
size = _pack_int16(len(r) + header_len)
112114
r = size + r
113115
return bytes(r)
114116

@@ -174,6 +176,8 @@ def __init__(self, sockaddr):
174176
self.socket.bind(self.sockaddr)
175177
self.socket.listen(1)
176178

179+
self.ipc_rxbuffer = bytearray()
180+
177181
def _cleanup_file(self):
178182
try:
179183
os.remove(self.sockaddr)
@@ -189,30 +193,22 @@ def send(self, message):
189193
def recv(self):
190194
maxlen = 2048
191195
if sys.platform == "win32":
192-
packet = self.conn.recv(maxlen)
193-
if len(packet) < 1:
194-
return None
195-
if len(packet) >= maxlen:
196-
raise PacketTooLarge
197-
expected_size = struct.unpack("<H", packet[:2])[0]
198-
199-
# If full packet wasn't received, keep waiting!
200-
if len(packet) < expected_size:
201-
packet_frag = self.conn.recv(maxlen)
202-
packet += packet_frag
203-
if len(packet_frag) < 1:
204-
return None
205-
if len(packet) >= maxlen:
206-
raise PacketTooLarge
207-
208-
# Discard the length from the packet - it's not needed anymore.
209-
packet = packet[2:]
196+
def recv_packet():
Has conversations. Original line has conversations.
197+
while len(self.ipc_rxbuffer) < header_len:
198+
self.ipc_rxbuffer += self.conn.recv(maxlen)
199+
packet_len = struct.unpack("<H", self.ipc_rxbuffer[:header_len])[0]
200+
while len(self.ipc_rxbuffer) < packet_len:
201+
self.ipc_rxbuffer += self.conn.recv(maxlen)
202+
packet = self.ipc_rxbuffer[header_len:packet_len]
203+
self.ipc_rxbuffer = self.ipc_rxbuffer[packet_len:]
204+
return packet
205+
packet = recv_packet()
210206
else:
211207
packet = self.conn.recv(maxlen)
212-
if len(packet) < 1:
213-
return None
214-
if len(packet) >= maxlen:
215-
raise PacketTooLarge
208+
if len(packet) < 1:
209+
return None
210+
if len(packet) >= maxlen:
211+
raise PacketTooLarge
216212
return _unpack(packet)
217213

218214
def close(self):
@@ -221,14 +217,9 @@ def close(self):
221217
self.conn.close()
222218
if hasattr(self, "socket"):
223219
if sys.platform == "win32":
224-
# self.socket.shutdown(socket.SHUT_RDWR)
225-
# Fails with WinError 10057:
226-
# A request to send or receive data was disallowed because the
227-
# socket is not connected and (when sending on a datagram
228-
# socket using a sendto call) no address was supplied
229-
# This error will cascade into WinError 10038, where
230-
# Simulator.__exit__ didn't finish cleaning up and left an
231-
# invalid socket.
220+
# don't shutdown our socket since closing connection
221+
# seems to already have done it. (trigger an error
222+
# otherwise)
232223
self.socket.close()
233224
else:
234225
self.socket.shutdown(socket.SHUT_RDWR)

‎vpi/ipc.c

+49-47
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
* License: GPLv3 with additional permissions (see README).
44
*/
55

6+
#ifdef _WIN32
7+
#define WINVER 0x501
8+
#endif
9+
610
#include <assert.h>
711
#include <sys/types.h>
812
#include <unistd.h>
@@ -13,7 +17,6 @@
1317
#ifdef _WIN32
1418
#include <winsock2.h>
1519
#include <ws2tcpip.h>
16-
#define WIN_SOCKET_PORT "50007"
1720
#else
1821
#include <sys/socket.h>
1922
#include <sys/un.h>
@@ -30,13 +33,24 @@ struct ipc_softc {
3033
void *user;
3134
};
3235

36+
#define MAX_LEN 2048
37+
38+
#ifdef _WIN32
39+
#define WIN32_HEADER_LEN 2
40+
#define WIN32_SOCKET_PORT "50007"
41+
42+
unsigned char ipc_rxbuffer[2*MAX_LEN];
43+
int ipc_rxlen;
44+
#endif
45+
3346
struct ipc_softc *ipc_connect(const char *sockaddr,
3447
go_handler h_go, write_handler h_write, read_handler h_read, void *user)
3548
{
3649
struct ipc_softc *sc;
3750
#ifdef _WIN32
3851
struct addrinfo hints, *my_addrinfo;
3952
WSADATA wsaData;
53+
ipc_rxlen = 0;
4054
#else
4155
struct sockaddr_un addr;
4256
#endif
@@ -61,7 +75,7 @@ struct ipc_softc *ipc_connect(const char *sockaddr,
6175
hints.ai_socktype = SOCK_STREAM;
6276
hints.ai_protocol = IPPROTO_TCP;
6377

64-
if(getaddrinfo(sockaddr, WIN_SOCKET_PORT, NULL, &my_addrinfo) != 0) {
78+
if(getaddrinfo(sockaddr, WIN32_SOCKET_PORT, NULL, &my_addrinfo) != 0) {
6579
free(sc);
6680
return NULL;
6781
}
@@ -113,7 +127,37 @@ enum {
113127
MESSAGE_READ_REPLY
114128
};
115129

116-
#define MAX_LEN 2048
130+
static int ipc_receive_packet(struct ipc_softc *sc, unsigned char *buffer) {
131+
#ifdef _WIN32
132+
int len;
133+
int packet_len;
134+
/* ensure we have packet header */
135+
while (ipc_rxlen < WIN32_HEADER_LEN) {
Has conversations. Original line has conversations.
136+
len = recv(sc->socket, (char *)&ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
137+
if (len)
138+
ipc_rxlen += len;
139+
}
140+
141+
/* compute packet length and ensure we have the payload */
142+
packet_len = ((ipc_rxbuffer[1] << 8) | (ipc_rxbuffer[0]));
Has conversations. Original line has conversations.
143+
while (ipc_rxlen < packet_len) {
144+
len = recv(sc->socket, (char *) &ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
145+
if (len)
146+
ipc_rxlen += len;
147+
}
148+
149+
/* copy packet to buffer */
150+
memcpy(buffer, ipc_rxbuffer + WIN32_HEADER_LEN, packet_len - WIN32_HEADER_LEN);
151+
152+
/* prepare ipc_rxbuffer for next packet */
153+
ipc_rxlen = ipc_rxlen - packet_len;
154+
memcpy(ipc_rxbuffer, ipc_rxbuffer + packet_len, ipc_rxlen);
155+
156+
return packet_len - WIN32_HEADER_LEN;
157+
#else
158+
return recv(sc->socket, buffer, MAX_LEN, 0);
159+
#endif
160+
}
117161

118162
/*
119163
* 0 -> error
@@ -125,55 +169,13 @@ int ipc_receive(struct ipc_softc *sc)
125169
unsigned char buffer[MAX_LEN];
126170
ssize_t l = 0;
127171
int i;
128-
#ifdef _WIN32
129-
int expected_num;
130-
int received_num = 0;
131-
#endif
132172

133-
#ifdef _WIN32
134-
/* Initial recv. Includes a length identifier so that we wait
135-
* until a full message is received. The length of the message
136-
* includes the length identifier. */
137-
while(received_num < 2) {
138-
/* Ensure we wait to get the packet length,
139-
* which requires two bytes, before continuing. */
140-
received_num = recv(sc->socket, (char *)&buffer[l], \
141-
(MAX_LEN - received_num), 0);
142-
l += received_num;
143-
144-
if(received_num == 0)
145-
return 2;
146-
if((received_num < 0) || (received_num >= MAX_LEN) || \
147-
(l >= MAX_LEN))
148-
return 0;
149-
}
150-
151-
expected_num = ((buffer[1] << 8) | (buffer[0]));
152-
while(l < expected_num) {
153-
/* received_num will never exceed MAX_LEN, unless
154-
* recv is broken. */
155-
received_num = recv(sc->socket, (char *)&buffer[l], \
156-
(MAX_LEN - received_num), 0);
157-
l += received_num;
158-
159-
if(received_num == 0)
160-
return 2;
161-
if((received_num < 0) || (received_num >= MAX_LEN) || \
162-
(l >= MAX_LEN))
163-
return 0;
164-
} /* l is assumed to have the message length
165-
* in the message unpacking code. */
166-
i = 2; /* Skip the length identifier. */
167-
#else
168-
/* On Unix, SOCK_SEQPACKET will take care of ensuring message
169-
* boundaries are satisfied. */
170-
l = recv(sc->socket, buffer, MAX_LEN, 0);
173+
l = ipc_receive_packet(sc, (unsigned char *)&buffer);
171174
if(l == 0)
172175
return 2;
173176
if((l < 0) || (l >= MAX_LEN))
174177
return 0;
175-
i = 0; /* No length identifier, so we care about the entire buffer */
176-
#endif
178+
i = 0;
177179

178180
switch(buffer[i++]) {
179181
case MESSAGE_GO:

0 commit comments

Comments
 (0)
Please sign in to comment.