Created
October 5, 2011 14:45
-
-
Save szastupov/1264593 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This function ensures that there is required amount of data in the | |
* ndr stream. When there isn't, it tries to read as much data as | |
* possible in order to reduce the number of recv() calls. It grows | |
* the stream if necessary. It relies on pdu_size so be careful. | |
*/ | |
static int | |
nds_fetch(int sock, ndr_stream_t *nds, size_t need) | |
{ | |
ssize_t rc; | |
size_t size = nds->pdu_size; | |
size_t avail = size - nds->pdu_scan_offset; | |
if (need > avail) { | |
NDS_GROW_PDU(nds, size + need, NULL); | |
rc = recv_min(sock, | |
(uint8_t *)nds->pdu_base_offset + size, | |
nds->pdu_max_size - size, | |
need - avail); | |
if (rc == -1) | |
return (errno); | |
nds->pdu_size = size + rc; | |
} | |
return (0); | |
} | |
/* | |
* Read the incoming fragments and defragment the message on the go. | |
*/ | |
static int | |
ndr_session_read_fragments(ndr_session_t *session) | |
{ | |
ndr_xa_t *mxa = &session->mxa; | |
ndr_stream_t *nds = &mxa->recv_nds; | |
ndr_common_header_t frag_hdr; | |
int rc; | |
int nfrags = 0; | |
int frag_size; | |
/* | |
* TODO: in some cases we should generate a proper error reply in | |
* RPC form, not just -1 and broken pipe on the other side. | |
*/ | |
do { | |
rc = nds_fetch(session->sock, nds, | |
sizeof (ndr_common_header_t)); | |
if (rc != 0) | |
return (rc); | |
ndr_decode_frag_hdr(nds, &frag_hdr); | |
ndr_show_hdr(&frag_hdr); | |
if ((frag_hdr.rpc_vers != 5) || (frag_hdr.rpc_vers_minor != 0)) | |
return (-1); | |
frag_size = frag_hdr.frag_length; | |
rc = nds_fetch(session->sock, nds, frag_size); | |
if (rc != 0) | |
return (rc); | |
if (NDR_IS_FIRST_FRAG(frag_hdr.pfc_flags)) { | |
if (nfrags > 0) | |
return (-1); | |
nds->pdu_scan_offset = frag_size; | |
} else { | |
ndr_remove_frag_hdr(nds); | |
nds->pdu_scan_offset += frag_size - NDR_RSP_HDR_SIZE; | |
} | |
nfrags++; | |
} while (!NDR_IS_LAST_FRAG(frag_hdr.pfc_flags)); | |
nds->pdu_scan_offset = 0; | |
return (0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment