int main(int argc, char **argv) { Sdr sdr; Object txExtent; Object txBundleZco; Object txNewBundle; BpDelivery rxDlv; int rxContentLength; ZcoReader rxReader; int rxLen; char rxContent[sizeof(testLine)]; /* Start ION */ ionstart_default_config("loopback-ltp/loopback.ionrc", NULL, "loopback-ltp/loopback.ltprc", "loopback-ltp/loopback.bprc", "loopback-ltp/loopback.ipnrc", NULL); /* Attach to ION */ fail_unless(bp_attach() >= 0); sdr = bp_get_sdr(); /* Send the loopback bundle */ sdr_begin_xn(sdr); txExtent = sdr_malloc(sdr, sizeof(testLine) - 1); fail_unless(txExtent != 0); sdr_write(sdr, txExtent, testLine, sizeof(testLine) - 1); txBundleZco = zco_create(sdr, ZcoSdrSource, txExtent, 0, sizeof(testLine) - 1); fail_unless(sdr_end_xn(sdr) >= 0 && txBundleZco != 0); fail_unless(bp_send(NULL, testEid, NULL, 300, BP_STD_PRIORITY, NoCustodyRequested, 0, 0, NULL, txBundleZco, &txNewBundle) > 0); /* Receive the loopback bundle */ fail_unless(bp_open(testEid, &rxSap) >= 0); fail_unless(bp_receive(rxSap, &rxDlv, IONTEST_DEFAULT_RECEIVE_WAIT) >= 0); fail_unless(rxDlv.result == BpPayloadPresent); sdr_begin_xn(sdr); rxContentLength = zco_source_data_length(sdr, rxDlv.adu); fail_unless(rxContentLength == sizeof(testLine) - 1); zco_start_receiving(rxDlv.adu, &rxReader); rxLen = zco_receive_source(sdr, &rxReader, rxContentLength, rxContent); fail_unless(rxLen == rxContentLength); fail_unless(sdr_end_xn(sdr) >= 0); bp_release_delivery(&rxDlv, 1); bp_close(rxSap); /* Detach from ION */ writeErrmsgMemos(); bp_detach(); /* Compare the received data */ rxContent[sizeof(rxContent) - 1] = '\0'; fail_unless(strncmp(rxContent, testLine, sizeof(testLine)) == 0); /* Stop ION */ ionstop(); CHECK_FINISH; }
static int handleGreenSegment(AcqWorkArea *work, LtpSessionId *sessionId, unsigned char endOfBlock, unsigned int offset, unsigned int length, Object zco, unsigned int *buflen, char **buffer) { Sdr sdr = getIonsdr(); static LtpSessionId currentSessionId = { 0, 0 }; static unsigned int currentOffset = 0; unsigned int fillLength; ZcoReader reader; int result; if (zco == 0) /* Import session canceled. */ { bpCancelAcq(work); currentSessionId.sourceEngineId = 0; currentSessionId.sessionNbr = 0; currentOffset = 0; return 0; } if (zco_source_data_length(sdr, zco) != length) { return 0; /* Just discard the segment. */ } if (sessionId->sourceEngineId != currentSessionId.sourceEngineId || sessionId->sessionNbr != currentSessionId.sessionNbr) { /* Did not receive end-of-block segment for the * block that was being received. Discard the * partially received bundle in the work area, * if any. */ bpCancelAcq(work); currentSessionId.sourceEngineId = 0; currentSessionId.sessionNbr = 0; currentOffset = 0; } if (currentOffset == 0) { /* Start new green bundle acquisition. */ if (bpBeginAcq(work, 0, NULL) < 0) { putErrmsg("Can't begin acquisition of bundle.", NULL); return -1; } currentSessionId.sourceEngineId = sessionId->sourceEngineId; currentSessionId.sessionNbr = sessionId->sessionNbr; } if (offset < currentOffset) /* Out of order. */ { return 0; /* Just discard the segment. */ } if (offset > currentOffset) { /* Convergence layer must not deliver incomplete * bundles to BP. Practically speaking, this * gap in segment sequence must be treated as * malformation of the bundle. */ work->malformed = 1; /* But continue bundle acquisition anyway, in * case the incomplete bundle is useful for some * diagnostic purpose. */ fillLength = offset - currentOffset; if (fillLength > *buflen) { /* Make buffer big enough for the fill * data. */ if (*buffer) { MRELEASE(*buffer); *buflen = 0; } *buffer = MTAKE(fillLength); if (*buffer == NULL) { /* Gap is too large to fill. * Might be a DOS attack; cancel * acquisition. */ bpCancelAcq(work); currentSessionId.sourceEngineId = 0; currentSessionId.sessionNbr = 0; currentOffset = 0; return 0; } *buflen = fillLength; } memset(*buffer, 0, fillLength); if (bpContinueAcq(work, *buffer, (int) fillLength, 0) < 0) { putErrmsg("Can't insert bundle fill data.", NULL); return -1; } currentOffset += fillLength; } if (length > *buflen) { /* Make buffer big enough for the green data. */ if (*buffer) { MRELEASE(*buffer); *buflen = 0; } *buffer = MTAKE(length); if (*buffer == NULL) { /* Segment is too large. Might be a * DOS attack; cancel acquisition. */ bpCancelAcq(work); currentSessionId.sourceEngineId = 0; currentSessionId.sessionNbr = 0; currentOffset = 0; return 0; } *buflen = length; } /* Extract data from segment ZCO so that it can be * appended to the bundle acquisition ZCO. Note * that we're breaking the "zero-copy" model here; * it would be better to have an alternate version * of bpContinueAcq that uses zco_clone_source_data * to append the segment ZCO's source data to the * acquisition ZCO in the work area. (TODO) */ zco_start_receiving(zco, &reader); CHKERR(sdr_begin_xn(sdr)); result = zco_receive_source(sdr, &reader, length, *buffer); if (sdr_end_xn(sdr) < 0 || result < 0) { putErrmsg("Failed reading green segment data.", NULL); return -1; } if (bpContinueAcq(work, *buffer, (int) length, 0) < 0) { putErrmsg("Can't continue bundle acquisition.", NULL); return -1; } currentOffset += length; if (endOfBlock) { if (bpEndAcq(work) < 0) { putErrmsg("Can't end acquisition of bundle.", NULL); return -1; } currentSessionId.sourceEngineId = 0; currentSessionId.sessionNbr = 0; currentOffset = 0; } return 0; }
static void *getBundles(void *parm) { RxThreadParms *parms = (RxThreadParms *) parm; char ownEid[64]; Sdr sdr = getIonsdr(); BpDelivery dlv; uvast profNum; Scalar seqNum; char type; unsigned int aduLength; int bytesRemaining; ZcoReader reader; unsigned char *buffer; int bytesToRead; int sdnvLength; unsigned char *cursor; isprintf(ownEid, sizeof ownEid, "ipn:" UVAST_FIELDSPEC ".%d", getOwnNodeNbr(), DTPC_RECV_SVC_NBR); if (bp_open(ownEid, &(parms->rxSap)) < 0) { putErrmsg("DTPC can't open own 'recv' endpoint.", ownEid); parms->running = 0; return NULL; } writeMemo("[i] dtpcd receiver thread has started."); while (parms->running) { if (bp_receive(parms->rxSap, &dlv, BP_BLOCKING) < 0) { putErrmsg("dtpcd bundle reception failed.", NULL); parms->running = 0; continue; } switch (dlv.result) { case BpEndpointStopped: parms->running = 0; break; case BpPayloadPresent: CHKNULL(sdr_begin_xn(sdr)); /* Since the max length of a Sdnv is 10 bytes, * read 21 bytes to be sure that the Profile * and Sequence number Sdnvs plus the type * were read. */ aduLength = zco_source_data_length(sdr, dlv.adu); bytesRemaining = aduLength; if (aduLength < 21) /* Just in case we receive * a very small adu. */ { bytesToRead = aduLength; } else { bytesToRead = 21; } buffer = MTAKE(bytesToRead); if (buffer == NULL) { putErrmsg("Out of memory.",NULL); return NULL; } cursor = buffer; zco_start_receiving(dlv.adu, &reader); if (zco_receive_headers(sdr, &reader, bytesToRead, (char *) buffer) < 0) { putErrmsg("dtpcd can't receive ADU header.", itoa(bytesToRead)); sdr_cancel_xn(sdr); MRELEASE(buffer); parms->running = 0; continue; } type = *cursor; /* Get the type byte. */ cursor++; bytesRemaining--; sdnvLength = decodeSdnv(&profNum, cursor); cursor += sdnvLength; bytesRemaining -= sdnvLength; sdnvLength = sdnvToScalar(&seqNum, cursor); cursor += sdnvLength; bytesRemaining -= sdnvLength; /* Mark remaining bytes as source data. */ zco_delimit_source(sdr, dlv.adu, cursor - buffer, bytesRemaining); zco_strip(sdr, dlv.adu); MRELEASE(buffer); if (sdr_end_xn(sdr) < 0) { putErrmsg("dtpcd can't handle bundle delivery.", NULL); parms->running = 0; continue; } switch (type) { case 0x00: /* Received an adu. */ switch (handleInAdu(sdr, &dlv, profNum, seqNum)) { case -1: putErrmsg("dtpcd can't handle inbound \ adu.", NULL); parms->running = 0; continue; case 1: if (parseInAdus(sdr) < 0) { putErrmsg("dtpcd can't parse \ inbound adus.", NULL); parms->running = 0; continue; } case 0: /* Intentional fall-through to * next case. */ default: if (dlv.ackRequested) { if (sendAck(parms->txSap, profNum, seqNum, &dlv) < 0) { putErrmsg("dtpcd can't \ send ack.", NULL); parms->running = 0; continue; } } break; } break; case 0x01: /* Received an ACK. */ if (handleAck(sdr, &dlv, profNum, seqNum) < 0) { putErrmsg("dtpcd can't handle ACK.", NULL); parms->running = 0; continue; } break; default: writeMemo("[?] Invalid item type. Corrupted \ item?"); break; } default: break; }
static void *receivePdus(void *parm) { RxThreadParms *parms = (RxThreadParms *) parm; char ownEid[64]; Sdr sdr; BpDelivery dlv; int contentLength; ZcoReader reader; unsigned char *buffer; buffer = MTAKE(CFDP_MAX_PDU_SIZE); if (buffer == NULL) { putErrmsg("bputa receiver thread can't get buffer.", NULL); parms->running = 0; return NULL; } isprintf(ownEid, sizeof ownEid, "ipn:" UVAST_FIELDSPEC ".%u", getOwnNodeNbr(), CFDP_RECV_SVC_NBR); if (bp_open(ownEid, &(parms->rxSap)) < 0) { MRELEASE(buffer); putErrmsg("CFDP can't open own 'recv' endpoint.", ownEid); parms->running = 0; return NULL; } sdr = bp_get_sdr(); writeMemo("[i] bputa input has started."); while (parms->running) { if (bp_receive(parms->rxSap, &dlv, BP_BLOCKING) < 0) { putErrmsg("bputa bundle reception failed.", NULL); parms->running = 0; continue; } switch (dlv.result) { case BpEndpointStopped: parms->running = 0; break; case BpPayloadPresent: contentLength = zco_source_data_length(sdr, dlv.adu); CHKNULL(sdr_begin_xn(sdr)); zco_start_receiving(dlv.adu, &reader); if (zco_receive_source(sdr, &reader, contentLength, (char *) buffer) < 0) { sdr_cancel_xn(sdr); putErrmsg("bputa can't receive bundle ADU.", itoa(contentLength)); parms->running = 0; continue; } if (sdr_end_xn(sdr) < 0) { putErrmsg("bputa can't handle bundle delivery.", NULL); parms->running = 0; continue; } if (cfdpHandleInboundPdu(buffer, contentLength) < 0) { putErrmsg("bputa can't handle inbound PDU.", NULL); parms->running = 0; } break; default: break; } bp_release_delivery(&dlv, 1); /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } bp_close(parms->rxSap); MRELEASE(buffer); writeMemo("[i] bputa input has stopped."); return NULL; }
static int processCmdFile(Sdr sdr, BpDelivery *dlv) { int contentLength; ZcoReader reader; int len; char *content; char *endOfContent; char *line; char *delimiter; char *nextLine; int lineLength; char *fileName = NULL; int opsFile = -1; contentLength = zco_source_data_length(sdr, dlv->adu); if (contentLength > 64000) { putErrmsg("lgagent: bundle content length > 64000, ignored.", itoa(contentLength)); return 0; } content = MTAKE(contentLength + 1); if (content == NULL) { putErrmsg("lgagent: no space for bundle content.", NULL); return -1; } zco_start_receiving(dlv->adu, &reader); CHKERR(sdr_begin_xn(sdr)); len = zco_receive_source(sdr, &reader, contentLength, content); if (sdr_end_xn(sdr) < 0) { return -1; } if (len < 0) { MRELEASE(content); putErrmsg("lgagent: can't receive bundle content.", NULL); return -1; } endOfContent = content + contentLength; *endOfContent = 0; line = content; while (line < endOfContent) { delimiter = strchr(line, '\n'); /* LF (newline) */ if (delimiter == NULL) /* No LF or CRLF */ { writeMemoNote("[?] lgagent: non-terminated line, \ discarding bundle content", content); closeOpsFile(&opsFile); fileName = NULL; break; /* Out of loop. */ } nextLine = delimiter + 1; lineLength = nextLine - line; *delimiter = 0; /* Strip off the LF. */ if (lineLength == 1) /* Empty line. */ { line = nextLine; continue; } /* Case 1: line is start of an operations file. */ if (*line == '[') /* Start loading file. */ { if (fileName) { putErrmsg("lgagent: '[' line before end of \ load, no further activity.", itoa(line - content)); closeOpsFile(&opsFile); fileName = NULL; break; /* Out of loop. */ } /* Remainder of line is file name. */ fileName = line + 1; opsFile = iopen(fileName, O_RDWR | O_CREAT, 0777); if (opsFile < 0) { putSysErrmsg("lgagent: can't open operations \ file name, no further activity", fileName); fileName = NULL; break; /* Out of loop. */ } #ifdef TargetFFS closeOpsFile(&opsFile); #endif line = nextLine; continue; }