3
3
* License: GPLv3 with additional permissions (see README).
4
4
*/
5
5
6
+ #ifdef _WIN32
7
+ #define WINVER 0x501
8
+ #endif
9
+
6
10
#include <assert.h>
7
11
#include <sys/types.h>
8
12
#include <unistd.h>
13
17
#ifdef _WIN32
14
18
#include <winsock2.h>
15
19
#include <ws2tcpip.h>
16
- #define WIN_SOCKET_PORT "50007"
17
20
#else
18
21
#include <sys/socket.h>
19
22
#include <sys/un.h>
@@ -30,13 +33,24 @@ struct ipc_softc {
30
33
void * user ;
31
34
};
32
35
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
+
33
46
struct ipc_softc * ipc_connect (const char * sockaddr ,
34
47
go_handler h_go , write_handler h_write , read_handler h_read , void * user )
35
48
{
36
49
struct ipc_softc * sc ;
37
50
#ifdef _WIN32
38
51
struct addrinfo hints , * my_addrinfo ;
39
52
WSADATA wsaData ;
53
+ ipc_rxlen = 0 ;
40
54
#else
41
55
struct sockaddr_un addr ;
42
56
#endif
@@ -61,7 +75,7 @@ struct ipc_softc *ipc_connect(const char *sockaddr,
61
75
hints .ai_socktype = SOCK_STREAM ;
62
76
hints .ai_protocol = IPPROTO_TCP ;
63
77
64
- if (getaddrinfo (sockaddr , WIN_SOCKET_PORT , NULL , & my_addrinfo ) != 0 ) {
78
+ if (getaddrinfo (sockaddr , WIN32_SOCKET_PORT , NULL , & my_addrinfo ) != 0 ) {
65
79
free (sc );
66
80
return NULL ;
67
81
}
@@ -113,7 +127,37 @@ enum {
113
127
MESSAGE_READ_REPLY
114
128
};
115
129
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
+ }
117
161
118
162
/*
119
163
* 0 -> error
@@ -125,55 +169,13 @@ int ipc_receive(struct ipc_softc *sc)
125
169
unsigned char buffer [MAX_LEN ];
126
170
ssize_t l = 0 ;
127
171
int i ;
128
- #ifdef _WIN32
129
- int expected_num ;
130
- int received_num = 0 ;
131
- #endif
132
172
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 );
171
174
if (l == 0 )
172
175
return 2 ;
173
176
if ((l < 0 ) || (l >= MAX_LEN ))
174
177
return 0 ;
175
- i = 0 ; /* No length identifier, so we care about the entire buffer */
176
- #endif
178
+ i = 0 ;
177
179
178
180
switch (buffer [i ++ ]) {
179
181
case MESSAGE_GO :