Skip to content

Commit 73a0ce0

Browse files
author
giraffedata
committed
Change packet socket protocol to have <PKT> and <END> instead of <PKT>
git-svn-id: file:///var/tmp/xmlrpc/svn/trunk/xmlrpc-c@1016 adbb7d4b-a73a-0410-a071-c5f57c452bd4
1 parent 607a36a commit 73a0ce0

File tree

2 files changed

+88
-56
lines changed

2 files changed

+88
-56
lines changed

include/xmlrpc-c/packetsocket.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class packetSocket {
7272
This is an Internet communication vehicle that transmits individual
7373
variable-length packets of text.
7474
75-
It is based on a TCP socket.
75+
It is based on a stream socket.
7676
7777
It would be much better to use a kernel SOCK_SEQPACKET socket, but
7878
Linux 2.4 does not have them.
@@ -105,12 +105,18 @@ class packetSocket {
105105
packetPtr packetAccumP;
106106
// The packet we're currently accumulating; it will join
107107
// 'readBuffer' when we've received the whole packet (and we've
108-
// seen the PKT escape sequence so we know we've received it all).
108+
// seen the END escape sequence so we know we've received it all).
109+
// If we're not currently accumulating a packet (haven't seen a
110+
// PKT escape sequence), this points to nothing.
109111
bool inEscapeSeq;
110112
// In our trek through the data read from the underlying stream
111113
// socket, we are after an ESC character and before the end of the
112114
// escape sequence. 'escAccum' shows what of the escape sequence
113115
// we've seen so far.
116+
bool inPacket;
117+
// We're now receiving packet data from the underlying stream
118+
// socket. We've seen a complete PKT escape sequence, but have not
119+
// seen a complete END escape sequence since.
114120
struct {
115121
unsigned char bytes[3];
116122
size_t len;
@@ -126,12 +132,16 @@ class packetSocket {
126132

127133
void
128134
takeSomePacket(const unsigned char * const buffer,
129-
size_t const length,
130-
size_t * const bytesTakenP);
135+
size_t const length,
136+
size_t * const bytesTakenP);
131137

132138
void
133139
verifyNothingAccumulated();
134140

141+
void
142+
processBytesRead(const unsigned char * const buffer,
143+
size_t const bytesRead);
144+
135145
void
136146
readFromFile();
137147

src/cpp/packetsocket.cpp

Lines changed: 74 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,34 @@
1717
/*============================================================================
1818
The protocol for carrying packets on a character stream:
1919
20-
The protocol consists of the XML text to be transported with a bare
20+
The protocol consists of the actual bytes to be transported with a bare
2121
minimum of framing information added:
2222
2323
An ASCII Escape (<ESC> == 0x1B) character marks the start of a
2424
4-ASCII-character control word. These are defined:
2525
26-
<ESC>PKT : marks the end of a packet.
26+
<ESC>PKT : marks the beginning of a packet.
27+
<ESC>END : marks the end of a packet.
2728
<ESC>ESC : represents an <ESC> character in the packet
2829
<ESC>NOP : no meaning
2930
30-
Any other bytes after <ESC> is a protocol error. End of
31-
stream anywhere but after <ESC>PKT or beginning of stream is
32-
a protocol error.
31+
Any other bytes after <ESC> is a protocol error.
32+
33+
A stream is all the data transmitted during a single socket
34+
connection.
35+
36+
End of stream in the middle of a packet is a protocol error.
3337
3438
All bytes not part of a control word are literal bytes of a packet.
3539
36-
You can create a pstream transport from any file descriptor from which
40+
You can create a packet socket from any file descriptor from which
3741
you can read and write a bidirectional character stream. Typically,
3842
it's a TCP socket.
3943
4044
One use of the NOP control word is to validate that the connection
4145
is still working. You might send one periodically to detect, for
42-
example, an unplugged TCP/IP network cable.
46+
example, an unplugged TCP/IP network cable. It's probably better
47+
to use the TCP keepalive facility for that.
4348
============================================================================*/
4449

4550
#define _BSD_SOURCE // gets uint defined
@@ -174,11 +179,10 @@ packetSocket::packetSocket(int const sockFd) {
174179
this->sockFd = dupRc;
175180

176181
this->inEscapeSeq = false;
182+
this->inPacket = false;
177183

178184
this->escAccum.len = 0;
179185

180-
this->packetAccumP = packetPtr(new packet);
181-
182186
fcntl(this->sockFd, F_SETFL, O_NONBLOCK);
183187

184188
this->eof = false;
@@ -225,12 +229,16 @@ writeFd(int const fd,
225229
void
226230
packetSocket::writeWait(packetPtr const& packetP) const {
227231

228-
const unsigned char * const packetMarker(
232+
const unsigned char * const packetStart(
229233
reinterpret_cast<const unsigned char *>(ESC_STR "PKT"));
234+
const unsigned char * const packetEnd(
235+
reinterpret_cast<const unsigned char *>(ESC_STR "END"));
236+
237+
writeFd(this->sockFd, packetStart, 4);
230238

231239
writeFd(this->sockFd, packetP->getBytes(), packetP->getLength());
232240

233-
writeFd(this->sockFd, packetMarker, 4);
241+
writeFd(this->sockFd, packetEnd, 4);
234242
}
235243

236244

@@ -245,24 +253,15 @@ libc_read(int const fd,
245253

246254

247255

248-
void
249-
packetSocket::bufferFinishedPacket() {
250-
/*----------------------------------------------------------------------------
251-
Assume the packet currently being accumulated (in *this->packetAccumP)
252-
is complete and move it to the packet buffer (this->readBuffer).
253-
-----------------------------------------------------------------------------*/
254-
this->readBuffer.push(this->packetAccumP);
255-
256-
this->packetAccumP = packetPtr(new packet);
257-
}
258-
259-
260-
261256
void
262257
packetSocket::takeSomeEscapeSeq(const unsigned char * const buffer,
263258
size_t const length,
264259
size_t * const bytesTakenP) {
265-
260+
/*----------------------------------------------------------------------------
261+
Take and process some bytes from the incoming stream 'buffer',
262+
which contains 'length' bytes, assuming they are within an escape
263+
sequence.
264+
-----------------------------------------------------------------------------*/
266265
size_t bytesTaken;
267266

268267
bytesTaken = 0;
@@ -277,9 +276,20 @@ packetSocket::takeSomeEscapeSeq(const unsigned char * const buffer,
277276
} else if (xmlrpc_memeq(this->escAccum.bytes, "NOP", 3)) {
278277
// Nothing to do
279278
} else if (xmlrpc_memeq(this->escAccum.bytes, "PKT", 3)) {
280-
bufferFinishedPacket();
279+
this->packetAccumP = packetPtr(new packet);
280+
this->inPacket = true;
281+
} else if (xmlrpc_memeq(this->escAccum.bytes, "END", 3)) {
282+
if (this->inPacket) {
283+
this->readBuffer.push(this->packetAccumP);
284+
this->inPacket = false;
285+
this->packetAccumP = packetPtr();
286+
} else
287+
throwf("END control word received without preceding PKT");
281288
} else if (xmlrpc_memeq(this->escAccum.bytes, "ESC", 3)) {
282-
this->packetAccumP->addData((const unsigned char *)ESC_STR, 1);
289+
if (this->inPacket)
290+
this->packetAccumP->addData((const unsigned char *)ESC_STR, 1);
291+
else
292+
throwf("ESC control work received outside of a packet");
283293
} else
284294
throwf("Invalid escape sequence 0x%02x%02x%02x read from "
285295
"stream socket under packet socket",
@@ -311,14 +321,10 @@ packetSocket::takeSomePacket(const unsigned char * const buffer,
311321
// packet accumulator.
312322
this->packetAccumP->addData(buffer, escOffset);
313323

314-
this->inEscapeSeq = true;
315-
316324
// Caller can pick up from here; we don't know nothin' 'bout
317325
// no escape sequences.
318326

319-
// +1 below reflects the fact that we're taking the ESC character
320-
// too.
321-
*bytesTakenP = escOffset + 1;
327+
*bytesTakenP = escOffset;
322328
} else {
323329
// No complete packet yet and no substitution to do;
324330
// just throw the whole thing into the accumulator.
@@ -338,14 +344,45 @@ packetSocket::verifyNothingAccumulated() {
338344
throwf("Streams socket closed in the middle of an "
339345
"escape sequence");
340346

341-
if (this->packetAccumP->getLength() > 0)
347+
if (this->inPacket)
342348
throwf("Stream socket closed in the middle of a packet "
343-
"(%u bytes of packet received; no PKT marker to mark "
349+
"(%u bytes of packet received; no END marker to mark "
344350
"end of packet)", this->packetAccumP->getLength());
345351
}
346352

347353

348354

355+
void
356+
packetSocket::processBytesRead(const unsigned char * const buffer,
357+
size_t const bytesRead) {
358+
359+
uint cursor; // Cursor into buffer[]
360+
cursor = 0;
361+
while (cursor < bytesRead) {
362+
size_t bytesTaken;
363+
364+
if (this->inEscapeSeq)
365+
this->takeSomeEscapeSeq(&buffer[cursor],
366+
bytesRead - cursor,
367+
&bytesTaken);
368+
else if (buffer[cursor] == ESC) {
369+
this->inEscapeSeq = true;
370+
bytesTaken = 1;
371+
} else if (this->inPacket)
372+
this->takeSomePacket(&buffer[cursor],
373+
bytesRead - cursor,
374+
&bytesTaken);
375+
else
376+
throwf("Byte 0x%02x is not in a packet or escape sequence. "
377+
"Sender is probably not using packet socket protocol",
378+
buffer[cursor]);
379+
380+
cursor += bytesTaken;
381+
}
382+
}
383+
384+
385+
349386
void
350387
packetSocket::readFromFile() {
351388
/*----------------------------------------------------------------------------
@@ -379,24 +416,9 @@ packetSocket::readFromFile() {
379416

380417
if (bytesRead == 0) {
381418
this->eof = true;
382-
verifyNothingAccumulated();
383-
} else {
384-
uint cursor; // Cursor into buffer[]
385-
cursor = 0;
386-
while (cursor < bytesRead) {
387-
size_t bytesTaken;
388-
389-
if (this->inEscapeSeq)
390-
this->takeSomeEscapeSeq(&buffer[cursor],
391-
bytesRead - cursor,
392-
&bytesTaken);
393-
else
394-
this->takeSomePacket(&buffer[cursor],
395-
bytesRead - cursor,
396-
&bytesTaken);
397-
cursor += bytesTaken;
398-
}
399-
}
419+
this->verifyNothingAccumulated();
420+
} else
421+
this->processBytesRead(buffer, bytesRead);
400422
}
401423
}
402424
}

0 commit comments

Comments
 (0)