import sys
import struct
+if sys.platform == "win32":
+ header_len = 2
#
# Message classes
else:
raise TypeError
if sys.platform == "win32":
- size = _pack_int16(len(r) + 2) # size specifier adds to size
+ size = _pack_int16(len(r) + header_len)
r = size + r
return bytes(r)
self.socket.bind(self.sockaddr)
self.socket.listen(1)
+ self.ipc_rxbuffer = bytearray()
+
def _cleanup_file(self):
try:
os.remove(self.sockaddr)
def recv(self):
maxlen = 2048
if sys.platform == "win32":
- packet = self.conn.recv(maxlen)
- if len(packet) < 1:
- return None
- if len(packet) >= maxlen:
- raise PacketTooLarge
- expected_size = struct.unpack("<H", packet[:2])[0]
-
- # If full packet wasn't received, keep waiting!
- if len(packet) < expected_size:
- packet_frag = self.conn.recv(maxlen)
- packet += packet_frag
- if len(packet_frag) < 1:
- return None
- if len(packet) >= maxlen:
- raise PacketTooLarge
-
- # Discard the length from the packet - it's not needed anymore.
- packet = packet[2:]
+ def recv_packet():
+ while len(self.ipc_rxbuffer) < header_len:
+ self.ipc_rxbuffer += self.conn.recv(maxlen)
+ packet_len = struct.unpack("<H", self.ipc_rxbuffer[:header_len])[0]
+ while len(self.ipc_rxbuffer) < packet_len:
+ self.ipc_rxbuffer += self.conn.recv(maxlen)
+ packet = self.ipc_rxbuffer[header_len:packet_len]
+ self.ipc_rxbuffer = self.ipc_rxbuffer[packet_len:]
+ return packet
+ packet = recv_packet()
else:
packet = self.conn.recv(maxlen)
- if len(packet) < 1:
- return None
- if len(packet) >= maxlen:
- raise PacketTooLarge
+ if len(packet) < 1:
+ return None
+ if len(packet) >= maxlen:
+ raise PacketTooLarge
return _unpack(packet)
def close(self):
self.conn.close()
if hasattr(self, "socket"):
if sys.platform == "win32":
- # self.socket.shutdown(socket.SHUT_RDWR)
- # Fails with WinError 10057:
- # A request to send or receive data was disallowed because the
- # socket is not connected and (when sending on a datagram
- # socket using a sendto call) no address was supplied
- # This error will cascade into WinError 10038, where
- # Simulator.__exit__ didn't finish cleaning up and left an
- # invalid socket.
+ # don't shutdown our socket since closing connection
+ # seems to already have done it. (trigger an error
+ # otherwise)
self.socket.close()
else:
self.socket.shutdown(socket.SHUT_RDWR)
* License: GPLv3 with additional permissions (see README).
*/
+#ifdef _WIN32
+#define WINVER 0x501
+#endif
+
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
-#define WIN_SOCKET_PORT "50007"
#else
#include <sys/socket.h>
#include <sys/un.h>
void *user;
};
+#define MAX_LEN 2048
+
+#ifdef _WIN32
+#define WIN32_HEADER_LEN 2
+#define WIN32_SOCKET_PORT "50007"
+
+unsigned char ipc_rxbuffer[2*MAX_LEN];
+int ipc_rxlen;
+#endif
+
struct ipc_softc *ipc_connect(const char *sockaddr,
go_handler h_go, write_handler h_write, read_handler h_read, void *user)
{
#ifdef _WIN32
struct addrinfo hints, *my_addrinfo;
WSADATA wsaData;
+ ipc_rxlen = 0;
#else
struct sockaddr_un addr;
#endif
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
- if(getaddrinfo(sockaddr, WIN_SOCKET_PORT, NULL, &my_addrinfo) != 0) {
+ if(getaddrinfo(sockaddr, WIN32_SOCKET_PORT, NULL, &my_addrinfo) != 0) {
free(sc);
return NULL;
}
MESSAGE_READ_REPLY
};
-#define MAX_LEN 2048
+static int ipc_receive_packet(struct ipc_softc *sc, unsigned char *buffer) {
+#ifdef _WIN32
+ int len;
+ int packet_len;
+ /* ensure we have packet header */
+ while (ipc_rxlen < WIN32_HEADER_LEN) {
+ len = recv(sc->socket, (char *)&ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
+ if (len)
+ ipc_rxlen += len;
+ }
+
+ /* compute packet length and ensure we have the payload */
+ packet_len = ((ipc_rxbuffer[1] << 8) | (ipc_rxbuffer[0]));
+ while (ipc_rxlen < packet_len) {
+ len = recv(sc->socket, (char *) &ipc_rxbuffer[ipc_rxlen], MAX_LEN, 0);
+ if (len)
+ ipc_rxlen += len;
+ }
+
+ /* copy packet to buffer */
+ memcpy(buffer, ipc_rxbuffer + WIN32_HEADER_LEN, packet_len - WIN32_HEADER_LEN);
+
+ /* prepare ipc_rxbuffer for next packet */
+ ipc_rxlen = ipc_rxlen - packet_len;
+ memcpy(ipc_rxbuffer, ipc_rxbuffer + packet_len, ipc_rxlen);
+
+ return packet_len - WIN32_HEADER_LEN;
+#else
+ return recv(sc->socket, buffer, MAX_LEN, 0);
+#endif
+}
/*
* 0 -> error
unsigned char buffer[MAX_LEN];
ssize_t l = 0;
int i;
-#ifdef _WIN32
- int expected_num;
- int received_num = 0;
-#endif
-#ifdef _WIN32
- /* Initial recv. Includes a length identifier so that we wait
- * until a full message is received. The length of the message
- * includes the length identifier. */
- while(received_num < 2) {
- /* Ensure we wait to get the packet length,
- * which requires two bytes, before continuing. */
- received_num = recv(sc->socket, (char *)&buffer[l], \
- (MAX_LEN - received_num), 0);
- l += received_num;
-
- if(received_num == 0)
- return 2;
- if((received_num < 0) || (received_num >= MAX_LEN) || \
- (l >= MAX_LEN))
- return 0;
- }
-
- expected_num = ((buffer[1] << 8) | (buffer[0]));
- while(l < expected_num) {
- /* received_num will never exceed MAX_LEN, unless
- * recv is broken. */
- received_num = recv(sc->socket, (char *)&buffer[l], \
- (MAX_LEN - received_num), 0);
- l += received_num;
-
- if(received_num == 0)
- return 2;
- if((received_num < 0) || (received_num >= MAX_LEN) || \
- (l >= MAX_LEN))
- return 0;
- } /* l is assumed to have the message length
- * in the message unpacking code. */
- i = 2; /* Skip the length identifier. */
-#else
- /* On Unix, SOCK_SEQPACKET will take care of ensuring message
- * boundaries are satisfied. */
- l = recv(sc->socket, buffer, MAX_LEN, 0);
+ l = ipc_receive_packet(sc, (unsigned char *)&buffer);
if(l == 0)
return 2;
if((l < 0) || (l >= MAX_LEN))
return 0;
- i = 0; /* No length identifier, so we care about the entire buffer */
-#endif
+ i = 0;
switch(buffer[i++]) {
case MESSAGE_GO: