Skip to content

Instantly share code, notes, and snippets.

@szastupov
Created October 5, 2011 14:45
Show Gist options
  • Save szastupov/1264593 to your computer and use it in GitHub Desktop.
Save szastupov/1264593 to your computer and use it in GitHub Desktop.
/*
* 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