void adm_destroy() { LystElt elt = 0; for (elt = lyst_first(gAdmData); elt; elt = lyst_next(elt)) { adm_datadef_t *cur = (adm_datadef_t *) lyst_data(elt); mid_release(cur->mid); MRELEASE(cur); } lyst_destroy(gAdmData); gAdmData = NULL; for (elt = lyst_first(gAdmCtrls); elt; elt = lyst_next(elt)) { adm_ctrl_t *cur = (adm_ctrl_t *) lyst_data(elt); mid_release(cur->mid); MRELEASE(cur); } lyst_destroy(gAdmCtrls); gAdmCtrls = NULL; lyst_destroy(gAdmLiterals); gAdmLiterals = NULL; lyst_destroy(gAdmOps); gAdmOps = NULL; }
void rpt_release_data_entry(rpt_data_entry_t *entry) { if(entry != NULL) { MRELEASE(entry->contents); mid_release(entry->id); MRELEASE(entry); } }
int ltpei_parse_extension(char **cursor, int *bytesRemaining, Lyst exts, unsigned int *extensionOffset) { char *initialCursor; LtpExtensionInbound *extField; unsigned int valueLength; CHKERR(cursor); CHKERR(*cursor); CHKERR(bytesRemaining); CHKERR(exts); if ((*bytesRemaining) < 1) { return 0; /* Corrupt. */ } extField = MTAKE(sizeof(LtpExtensionInbound)); if (extField == NULL) { return -1; /* Give up. */ } initialCursor = *cursor; extField->offset = *extensionOffset; extField->tag = **cursor; (*cursor)++; (*bytesRemaining)--; extractSmallSdnv(&valueLength, cursor, bytesRemaining); if (valueLength == 0 || *bytesRemaining < valueLength) { return 0; /* Corrupt. */ } extField->length = valueLength; extField->value = MTAKE(valueLength); if (extField->value == 0) { MRELEASE(extField); return -1; /* Give up. */ } memcpy(extField->value, *cursor, valueLength); (*cursor) += valueLength; (*bytesRemaining) -= valueLength; if (lyst_insert_last(exts, extField) == NULL) { MRELEASE(extField->value); MRELEASE(extField); return -1; /* Give up. */ } *extensionOffset += ((*cursor) - initialCursor); return 1; }
void adm_build_mid_str(uint8_t flag, char *nn, int nn_len, int offset, uint8_t *mid_str) { uint8_t *cursor = NULL; Sdnv len; Sdnv off; uint32_t nn_size; uint8_t *tmp = NULL; int size = 0; DTNMP_DEBUG_ENTRY("adm_build_mid_str", "(%d, %s, %d, %d)", flag, nn, nn_len, offset); encodeSdnv(&len, nn_len + 1); encodeSdnv(&off, offset); tmp = utils_string_to_hex((unsigned char*)nn, &nn_size); size = 1 + nn_size + len.length + off.length + 1; if(size > ADM_MID_ALLOC) { DTNMP_DEBUG_ERR("adm_build_mid_str", "Size %d bigger than max MID size of %d.", size, ADM_MID_ALLOC); DTNMP_DEBUG_EXIT("adm_build_mid_str","->.", NULL); MRELEASE(tmp); return; } cursor = mid_str; memcpy(cursor, &flag, 1); cursor += 1; memcpy(cursor, len.text, len.length); cursor += len.length; memcpy(cursor, tmp, nn_size); cursor += nn_size; memcpy(cursor, off.text, off.length); cursor += off.length; memset(cursor, 0, 1); // NULL terminator. DTNMP_DEBUG_EXIT("adm_build_mid_str","->%s", mid_str); MRELEASE(tmp); return; }
static void udpClearAmsEndpoint(AmsEndpoint *dp) { if (dp->tsep) { MRELEASE(dp->tsep); } }
/****************************************************************************** * * \par Function Name: mid_clear * * \par Resets the values associated with a MID. Basically, a structure-aware * bzero. * * \retval void * * \param[in,out] mid The MID being cleared. * * \par Notes: * 1. Clearing a MID is different than destroying a MID. This just clears * allocated members. The MID itself may be re-used. * * Modification History: * MM/DD/YY AUTHOR DESCRIPTION * -------- ------------ --------------------------------------------- * 10/22/12 E. Birrane Initial implementation, *****************************************************************************/ void mid_clear(mid_t *mid) { DTNMP_DEBUG_ENTRY("mid_clear","(%#llx)", (unsigned long) mid); if(mid == NULL) { DTNMP_DEBUG_ERR("mid_clear","Clearing NULL MID.", NULL); DTNMP_DEBUG_EXIT("mid_clear","->NULL.",NULL); return; } if(mid->raw != NULL) { MRELEASE(mid->raw); mid->raw = NULL; } if(mid->oid != NULL) { oid_release(mid->oid); mid->oid = NULL; } memset(mid, 0, sizeof(mid_t)); DTNMP_DEBUG_EXIT("mid_clear","", NULL); }
/** * \brief serializes a register agent message into a buffer. * * \author Ed Birrane * * \note The returned message must be de-allocated from the memory pool. * * \return NULL - Failure * !NULL - The serialized message. * * \param[in] msg The message to serialize. * \param[out] len The length of the serialized message. */ uint8_t *msg_serialize_reg_agent(adm_reg_agent_t *msg, uint32_t *len) { Sdnv id; uint8_t *result = NULL; uint8_t *cursor = NULL; DTNMP_DEBUG_ENTRY("msg_serialize_reg_agent","(0x%x, 0x%x)", (unsigned long)msg, (unsigned long) len); /* Step 0: Sanity Checks. */ if((msg == NULL) || (len == NULL)) { DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Bad Args",NULL); DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL); return NULL; } /* * STEP 1: Figure out the size of the entire message. That includes the * length of the header, acl list, SDNV holding length, and data. */ int id_len = strlen(msg->agent_id.name); encodeSdnv(&id,id_len); *len = id.length + id_len; /* STEP 4: Allocate the serialized message. */ if((result = (uint8_t*)MTAKE(*len)) == NULL) { DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Can't alloc %d bytes", *len); *len = 0; DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL); return NULL; } /* Step 5: Populate the serialized message. */ cursor = result; memcpy(cursor, id.text, id.length); cursor += id.length; memcpy(cursor, msg->agent_id.name, id_len); cursor += id_len; /* Step 6: Last sanity check. */ if((cursor - result) != *len) { DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Wrote %d bytes but allcated %d", (unsigned long) (cursor - result), *len); *len = 0; MRELEASE(result); DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL); return NULL; } DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->0x%x",(unsigned long)result); return result; }
void bp_release_delivery(BpDelivery *dlvBuffer, int releasePayload) { Sdr sdr = getIonsdr(); CHKVOID(dlvBuffer); if (dlvBuffer->result == BpPayloadPresent) { if (dlvBuffer->bundleSourceEid) { MRELEASE(dlvBuffer->bundleSourceEid); dlvBuffer->bundleSourceEid = NULL; } if (releasePayload) { if (dlvBuffer->adu) { sdr_begin_xn(sdr); zco_destroy_reference(sdr, dlvBuffer->adu); if (sdr_end_xn(sdr) < 0) { putErrmsg("Failed releasing delivery.", NULL); } dlvBuffer->adu = 0; } } } }
static void udpClearMamsEndpoint(MamsEndpoint *ep) { if (ep->tsep) { MRELEASE(ep->tsep); } }
void rpt_release_prod(rpt_prod_t *msg) { DTNMP_DEBUG_ENTRY("rpt_release_prod","(0x%x)", (unsigned long) msg); if(msg != NULL) { LystElt elt; rule_time_prod_t *item; for(elt = lyst_first(msg->defs); elt; elt = lyst_next(elt)) { item = (rule_time_prod_t *) lyst_data(elt); rule_release_time_prod_entry(item); /* \todo Double check we don't need to kill the ELT here versus as * part of lyst_destroy. */ } lyst_destroy(msg->defs); MRELEASE(msg); } DTNMP_DEBUG_EXIT("rpt_release_prod","->.",NULL); }
static void terminateReceiverThread(ReceiverThreadParms *parms) { int senderSocket; writeErrmsgMemos(); writeMemo("[i] brsscla receiver thread stopping."); pthread_mutex_lock(parms->mutex); if (parms->bundleSocket != -1) { closesocket(parms->bundleSocket); if (parms->ductNbr != (unsigned int) -1) { senderSocket = parms->ductNbr - parms->baseDuctNbr; if (parms->brsSockets[senderSocket] == parms->bundleSocket) { /* Stop sender thread transmission * over this socket. Note: does * not halt the sender thread. */ parms->brsSockets[senderSocket] = -1; } } parms->bundleSocket = -1; } lyst_delete(parms->elt); pthread_mutex_unlock(parms->mutex); MRELEASE(parms); }
mid_t *mid_copy(mid_t *src_mid) { mid_t *result = 0; DTNMP_DEBUG_ENTRY("mid_copy","(%#llx)", (unsigned long) src_mid); /* Step 0: Sanity Check */ if(src_mid == NULL) { DTNMP_DEBUG_ERR("mid_copy","Cannot copy from NULL source MID.", NULL); DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL); return NULL; } /* Step 1: Allocate the new MID. */ if((result = (mid_t *)MTAKE(sizeof(mid_t))) == NULL) { DTNMP_DEBUG_ERR("mid_copy","Can't allocate %d bytes", sizeof(mid_t)); DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL); return NULL; } /* Step 2: Start with a shallow copy. */ memcpy(result, src_mid, sizeof(mid_t)); /* Step 3: Now, deep copy the pointers. */ result->oid = oid_copy(src_mid->oid); if((result->raw = (uint8_t *)MTAKE(src_mid->raw_size)) == NULL) { DTNMP_DEBUG_ERR("mid_copy","Can't allocate %d bytes", src_mid->raw_size); MRELEASE(result->oid); MRELEASE(result); DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL); return NULL; } memcpy(result->raw, src_mid->raw, src_mid->raw_size); DTNMP_DEBUG_EXIT("mid_copy","->%d", result); return result; }
void bp_close(BpSAP sap) { VEndpoint *vpoint; if (sap == NULL) { return; } vpoint = sap->vpoint; if (vpoint->appPid == sm_TaskIdSelf()) { vpoint->appPid = -1; } MRELEASE(sap->endpointMetaEid.nss); MRELEASE(sap->endpointMetaEid.schemeName); MRELEASE(sap); }
uint8_t *msg_serialize_rpt_policy(adm_rpt_policy_t *msg, uint32_t *len) { uint8_t *result = NULL; uint8_t *cursor = NULL; DTNMP_DEBUG_ENTRY("msg_serialize_rpt_policy","(0x%x, 0x%x)", (unsigned long)msg, (unsigned long) len); /* Step 0: Sanity Checks. */ if((msg == NULL) || (len == NULL)) { DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Bad Args",NULL); DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL); return NULL; } /* * STEP 1: Figure out the size of the entire message. That includes the * length of the header, acl list, and 1 byte for the mask. */ *len = 1; /* STEP 4: Allocate the serialized message. */ if((result = (uint8_t*)MTAKE(*len)) == NULL) { DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Can't alloc %d bytes", *len); *len = 0; DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL); return NULL; } /* Step 5: Populate the serialized message. */ cursor = result; memcpy(cursor, &(msg->mask),1); cursor += 1; /* Step 6: Last sanity check. */ if((cursor - result) != *len) { DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Wrote %d bytes but allcated %d", (unsigned long) (cursor - result), *len); *len = 0; MRELEASE(result); DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL); return NULL; } DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->0x%x",(unsigned long)result); return result; }
void ltpei_discard_extensions(Lyst extensions) { LystElt elt; LtpExtensionInbound *ext; CHKVOID(extensions); while ((elt = lyst_first(extensions)) != NULL) { ext = (LtpExtensionInbound *) lyst_data(elt); if (ext->value) { MRELEASE(ext->value); } MRELEASE(ext); lyst_delete(elt); } lyst_destroy(extensions); }
static void *udpAmsReceiver(void *parm) { AmsInterface *tsif = (AmsInterface *) parm; int fd; AmsSAP *amsSap; char *buffer; sigset_t signals; int length; struct sockaddr_in fromAddr; unsigned int fromSize; fd = (long) (tsif->sap); amsSap = tsif->amsSap; buffer = MTAKE(UDPTS_MAX_MSG_LEN); if (buffer == NULL) { putSysErrmsg(NoMemoryMemo, NULL); return NULL; } sigfillset(&signals); pthread_sigmask(SIG_BLOCK, &signals, NULL); while (1) { fromSize = sizeof fromAddr; length = recvfrom(fd, buffer, UDPTS_MAX_MSG_LEN, 0, (struct sockaddr *) &fromAddr, &fromSize); if (length < 2) /* length == 1 is "shutdown" */ { if (length < 0) { if (errno == EINTR) { continue; } putSysErrmsg("udpts failed receiving AMS \ message", NULL); } close(fd); MRELEASE(buffer); tsif->sap = NULL; return NULL; } /* Got an AMS message. */ if (enqueueAmsMsg(amsSap, (unsigned char *) buffer, length) < 0) { putErrmsg("udpts discarded AMS message.", NULL); } } }
/****************************************************************************** * * \par Function Name: adm_add_datadef_collect * * \par Registers a collection function to a data definition. * * \param[in] mid_str serialized MID value * \param[in] collect The data collection function. * * \par Notes: * 1. When working with parameterized OIDs, the given MID should * be all information excluding the parameterized portion of the OID. * 2. ADM names will be truncated after ADM_MAX_NAME bytes. * * Modification History: * MM/DD/YY AUTHOR DESCRIPTION * -------- ------------ --------------------------------------------- * 11/25/12 E. Birrane Initial implementation. * 07/27/13 E. BIrrane Updated ADM to use Lysts. *****************************************************************************/ void adm_add_datadef_collect(uint8_t *mid_str, adm_data_collect_fn collect) { uint32_t used = 0; mid_t *mid = NULL; adm_datadef_t *entry = NULL; DTNMP_DEBUG_ENTRY("adm_add_datadef_collect","(%lld, %lld)", mid_str, collect); if((mid_str == NULL) || (collect == NULL)) { DTNMP_DEBUG_ERR("adm_add_datadef_collect","Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL); return; } if((mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used)) == NULL) { char *tmp = utils_hex_to_string(mid_str, ADM_MID_ALLOC); DTNMP_DEBUG_ERR("adm_add_datadef_collect","Can't deserialize MID str %s.",tmp); MRELEASE(tmp); DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL); return; } if((entry = adm_find_datadef(mid)) == NULL) { char *tmp = mid_to_string(mid); DTNMP_DEBUG_ERR("adm_add_datadef_collect","Can't find data for MID %s.", tmp); MRELEASE(tmp); } else { entry->collect = collect; } mid_release(mid); DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL); }
void mid_release(mid_t *mid) { DTNMP_DEBUG_ENTRY("mid_release", "(%#llx)", (unsigned long) mid); if(mid != NULL) { mid_clear(mid); MRELEASE(mid); mid = NULL; } DTNMP_DEBUG_EXIT("mid_release", "-> NULL", NULL); }
void adm_add_ctrl_run(uint8_t *mid_str, adm_ctrl_fn run) { uint32_t used = 0; mid_t *mid = NULL; adm_ctrl_t *entry = NULL; DTNMP_DEBUG_ENTRY("adm_add_ctrl_run","(%lld, %lld)", mid_str, run); if((mid_str == NULL) || (run == NULL)) { DTNMP_DEBUG_ERR("adm_add_ctrl_run","Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL); return; } if((mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used)) == NULL) { char *tmp = utils_hex_to_string(mid_str, ADM_MID_ALLOC); DTNMP_DEBUG_ERR("adm_add_ctrl_run","Can't deserialized MID %s", tmp); MRELEASE(tmp); DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL); return; } if((entry = adm_find_ctrl(mid)) == NULL) { char *tmp = mid_to_string(mid); DTNMP_DEBUG_ERR("adm_add_ctrl_run","Can't find control for MID %s", tmp); MRELEASE(tmp); } else { entry->run = run; } mid_release(mid); DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL); }
int mgr_agent_remove(eid_t* in_eid) { agent_t *agent = NULL; Object *entry = NULL; LystElt elt; DTNMP_DEBUG_ENTRY("mgr_agent_remove","(0x%#llx)", (unsigned long) in_eid); /* Step 0: Sanity Checks. */ if(in_eid == NULL) { DTNMP_DEBUG_ERR("remove_agent","Specified EID was null.", NULL); DTNMP_DEBUG_EXIT("remove_agent","", NULL); return -1; } lockResource(&agents_mutex); elt = lyst_first(known_agents); while(elt != NULL) { if(strcmp(in_eid->name, ((agent_t *) lyst_data(elt))->agent_eid.name) == 0) { agent = (agent_t *) lyst_data(elt); lyst_delete(elt); break; } else { elt = lyst_next(elt); } } unlockResource(&agents_mutex); if(agent == NULL) { DTNMP_DEBUG_ERR("remove_agent", "No agent %s found in hashtable", in_eid->name); DTNMP_DEBUG_EXIT("remove_agent", "->0", NULL); return 0; } rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1); def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1); killResourceLock(&(agent->mutex)); MRELEASE(agent); DTNMP_DEBUG_EXIT("remove_agent", "->1", NULL); return 1; }
void rpt_print_data_entry(rpt_data_entry_t *entry) { char *id_str = NULL; if(entry == NULL) { fprintf(stderr,"NULL ENTRY.\n"); } id_str = mid_pretty_print(entry->id); fprintf(stderr,"DATA ENTRY:\n%s\n", id_str); MRELEASE(id_str); fprintf(stderr,"SIZE: %d\n", (uint32_t)entry->size); utils_print_hex(entry->contents, entry->size); }
/* Release functions.*/ void rpt_release_lst(rpt_items_t *msg) { DTNMP_DEBUG_ENTRY("rpt_release_lst","(0x%x)", (unsigned long) msg); if(msg != NULL) { if(msg->contents != NULL) { midcol_destroy(&(msg->contents)); } MRELEASE(msg); } DTNMP_DEBUG_EXIT("rpt_release_lst","->.",NULL); }
void rpt_release_defs(rpt_defs_t *msg) { DTNMP_DEBUG_ENTRY("rpt_release_defs","(0x%x)", (unsigned long) msg); if(msg != NULL) { if(msg->defs != NULL) { midcol_destroy(&(msg->defs)); } MRELEASE(msg); } DTNMP_DEBUG_EXIT("rpt_release_defs","->.",NULL); }
void mgr_agent_remove_cb(LystElt elt, void *nil) { eid_t *agent_eid = NULL; agent_t *agent = NULL; Object *entry = NULL; if(elt == NULL) { DTNMP_DEBUG_ERR("mgr_agent_remove_cb", "Specified Lyst element was null.", NULL); DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL); return; } lockResource(&agents_mutex); if((agent = (agent_t *) lyst_data(elt)) == NULL) { DTNMP_DEBUG_ERR("mgr_agent_remove_cb", "Specified Lyst data was null.", NULL); } else { rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1); def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1); killResourceLock(&(agent->mutex)); MRELEASE(agent); } unlockResource(&agents_mutex); DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL); return; }
int bp_receive(BpSAP sap, BpDelivery *dlvBuffer, int timeoutSeconds) { Sdr sdr = getIonsdr(); VEndpoint *vpoint; OBJ_POINTER(Endpoint, endpoint); Object dlvElt; Object bundleAddr; Bundle bundle; TimerParms timerParms; pthread_t timerThread; int result; char *dictionary; CHKERR(sap && dlvBuffer); if (timeoutSeconds < BP_BLOCKING) { putErrmsg("Illegal timeout interval.", itoa(timeoutSeconds)); return -1; } vpoint = sap->vpoint; sdr_begin_xn(sdr); if (vpoint->appPid != sm_TaskIdSelf()) { sdr_exit_xn(sdr); putErrmsg("Can't receive: not owner of endpoint.", itoa(vpoint->appPid)); return -1; } if (sm_SemEnded(vpoint->semaphore)) { sdr_exit_xn(sdr); writeMemo("[?] Endpoint has been stopped."); /* End task, but without error. */ return -1; } /* Get oldest bundle in delivery queue, if any; wait * for one if necessary. */ GET_OBJ_POINTER(sdr, Endpoint, endpoint, sdr_list_data(sdr, vpoint->endpointElt)); dlvElt = sdr_list_first(sdr, endpoint->deliveryQueue); if (dlvElt == 0) { sdr_exit_xn(sdr); if (timeoutSeconds == BP_POLL) { dlvBuffer->result = BpReceptionTimedOut; return 0; } /* Wait for semaphore to be given, either by the * deliverBundle() function or by timer thread. */ if (timeoutSeconds == BP_BLOCKING) { timerParms.interval = -1; } else /* This is a receive() with a deadline. */ { timerParms.interval = timeoutSeconds; timerParms.semaphore = vpoint->semaphore; if (pthread_create(&timerThread, NULL, timerMain, &timerParms) < 0) { putSysErrmsg("Can't enable interval timer", NULL); return -1; } } /* Take endpoint semaphore. */ if (sm_SemTake(vpoint->semaphore) < 0) { putErrmsg("Can't take endpoint semaphore.", NULL); return -1; } if (sm_SemEnded(vpoint->semaphore)) { writeMemo("[i] Endpoint has been stopped."); /* End task, but without error. */ return -1; } /* Have taken the semaphore, one way or another. */ sdr_begin_xn(sdr); dlvElt = sdr_list_first(sdr, endpoint->deliveryQueue); if (dlvElt == 0) /* Still nothing. */ { /* Either sm_SemTake() was interrupted * or else timer thread gave semaphore. */ sdr_exit_xn(sdr); if (timerParms.interval == 0) { /* Timer expired. */ dlvBuffer->result = BpReceptionTimedOut; pthread_join(timerThread, NULL); } else /* Interrupted. */ { dlvBuffer->result = BpReceptionInterrupted; if (timerParms.interval != -1) { pthread_cancel(timerThread); pthread_join(timerThread, NULL); } } return 0; } else /* Bundle was delivered. */ { if (timerParms.interval != -1) { pthread_cancel(timerThread); pthread_join(timerThread, NULL); } } } /* At this point, we have got a dlvElt and are in an SDR * transaction. */ bundleAddr = sdr_list_data(sdr, dlvElt); sdr_stage(sdr, (char *) &bundle, bundleAddr, sizeof(Bundle)); dictionary = retrieveDictionary(&bundle); if (dictionary == (char *) &bundle) { sdr_cancel_xn(sdr); putErrmsg("Can't retrieve dictionary.", NULL); return -1; } /* Now fill in the data indication structure. */ dlvBuffer->result = BpPayloadPresent; if (printEid(&bundle.id.source, dictionary, &dlvBuffer->bundleSourceEid) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't print source EID.", NULL); return -1; } dlvBuffer->bundleCreationTime.seconds = bundle.id.creationTime.seconds; dlvBuffer->bundleCreationTime.count = bundle.id.creationTime.count; dlvBuffer->adminRecord = bundle.bundleProcFlags & BDL_IS_ADMIN; dlvBuffer->adu = zco_add_reference(sdr, bundle.payload.content); dlvBuffer->ackRequested = bundle.bundleProcFlags & BDL_APP_ACK_REQUEST; /* Now before returning we send delivery status report * if it is requested. */ if (SRR_FLAGS(bundle.bundleProcFlags) & BP_DELIVERED_RPT) { bundle.statusRpt.flags |= BP_DELIVERED_RPT; getCurrentDtnTime(&bundle.statusRpt.deliveryTime); } if (bundle.statusRpt.flags) { result = sendStatusRpt(&bundle, dictionary); if (result < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't send status report.", NULL); return -1; } } /* Finally delete the delivery list element and, if * possible, destroy the bundle itself. */ if (dictionary) { MRELEASE(dictionary); } sdr_list_delete(sdr, dlvElt, (SdrListDeleteFn) NULL, NULL); bundle.dlvQueueElt = 0; sdr_write(sdr, bundleAddr, (char *) &bundle, sizeof(Bundle)); if (bpDestroyBundle(bundleAddr, 0) < 0) { sdr_cancel_xn(sdr); putErrmsg("Can't destroy bundle.", NULL); return -1; } if (sdr_end_xn(sdr) < 0) { putErrmsg("Failure in bundle reception.", NULL); return -1; } return 0; }
static void *sendKeepalives(void *parm) { KeepaliveThreadParms *parms = (KeepaliveThreadParms *) parm; int keepaliveTimer = 0; int bytesSent; int backoffTimer = BACKOFF_TIMER_START; int backoffTimerCount = 0; unsigned char *buffer; buffer = MTAKE(TCPCLA_BUFSZ); //To send keepalive bundle if (buffer == NULL) { putErrmsg("No memory for TCP buffer in tcpclo.", NULL); return NULL; } iblock(SIGTERM); while (*(parms->cloRunning)) { snooze(1); keepaliveTimer++; if (keepaliveTimer < *(parms->keepalivePeriod)) { continue; } // If the negotiated keep alive interval is 0, then // keep alives will not be sent. if(*(parms->keepalivePeriod) == 0) { continue; } /* Time to send a keepalive. Note that the * interval between keepalive attempts will be * KEEPALIVE_PERIOD plus (if the remote induct * is not reachable) the length of time taken * by TCP to determine that the connection * attempt will not succeed (e.g., 3 seconds). */ keepaliveTimer = 0; pthread_mutex_lock(parms->mutex); bytesSent = sendBundleByTCPCL(parms->socketName, parms->ductSocket, 0, 0, buffer, parms->keepalivePeriod); pthread_mutex_unlock(parms->mutex); /* if the node is unable to establish a TCP connection, * the connection should be tried only after some delay. * */ if(bytesSent == 0) { while((backoffTimerCount < backoffTimer) && (*(parms->ductSocket) < 0)) { snooze(1); backoffTimerCount++; if(!(*(parms->cloRunning))) { break; } } backoffTimerCount = 0; /* keepaliveTimer keeps track of when the keepalive needs * to be sent. This value is set to keepalive period. * That way at the end of backoff period a * keepalive is sent * */ keepaliveTimer = *(parms->keepalivePeriod); if(backoffTimer < BACKOFF_TIMER_LIMIT) { backoffTimer *= 2; } continue; } backoffTimer = BACKOFF_TIMER_START; if (bytesSent < 0) { shutDownClo(); break; } } MRELEASE(buffer); return NULL; }
int tcpclo(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) { char *ductName = (char *) a1; #else int main(int argc, char *argv[]) { char *ductName = (argc > 1 ? argv[1] : NULL); #endif unsigned char *buffer; VOutduct *vduct; PsmAddress vductElt; Sdr sdr; Outduct duct; ClProtocol protocol; Outflow outflows[3]; int i; char *hostName; unsigned short portNbr; unsigned int hostNbr; struct sockaddr socketName; struct sockaddr_in *inetName; int running = 1; pthread_mutex_t mutex; KeepaliveThreadParms parms; ReceiveThreadParms rparms; pthread_t keepaliveThread; pthread_t receiverThread; Object bundleZco; BpExtendedCOS extendedCOS; char destDuctName[MAX_CL_DUCT_NAME_LEN + 1]; unsigned int bundleLength; int ductSocket = -1; int bytesSent; int keepalivePeriod = 0; VInduct *viduct; if (ductName == NULL) { PUTS("Usage: tcpclo <remote host name>[:<port number>]"); return 0; } if (bpAttach() < 0) { putErrmsg("tcpclo can't attach to BP", NULL); return 1; } buffer = MTAKE(TCPCLA_BUFSZ); if (buffer == NULL) { putErrmsg("No memory for TCP buffer in tcpclo.", NULL); return 1; } findOutduct("tcp", ductName, &vduct, &vductElt); if (vductElt == 0) { putErrmsg("No such tcp duct.", ductName); MRELEASE(buffer); return 1; } if (vduct->cloPid != ERROR && vduct->cloPid != sm_TaskIdSelf()) { putErrmsg("CLO task is already started for this duct.", itoa(vduct->cloPid)); MRELEASE(buffer); return 1; } /* All command-line arguments are now validated. */ sdr = getIonsdr(); CHKERR(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &duct, sdr_list_data(sdr, vduct->outductElt), sizeof(Outduct)); sdr_read(sdr, (char *) &protocol, duct.protocol, sizeof(ClProtocol)); sdr_exit_xn(sdr); if (protocol.nominalRate == 0) { vduct->xmitThrottle.nominalRate = DEFAULT_TCP_RATE; } else { vduct->xmitThrottle.nominalRate = protocol.nominalRate; } memset((char *) outflows, 0, sizeof outflows); outflows[0].outboundBundles = duct.bulkQueue; outflows[1].outboundBundles = duct.stdQueue; outflows[2].outboundBundles = duct.urgentQueue; for (i = 0; i < 3; i++) { outflows[i].svcFactor = 1 << i; } hostName = ductName; parseSocketSpec(ductName, &portNbr, &hostNbr); if (portNbr == 0) { portNbr = BpTcpDefaultPortNbr; } portNbr = htons(portNbr); if (hostNbr == 0) { putErrmsg("Can't get IP address for host.", hostName); MRELEASE(buffer); return 1; } hostNbr = htonl(hostNbr); memset((char *) &socketName, 0, sizeof socketName); inetName = (struct sockaddr_in *) &socketName; inetName->sin_family = AF_INET; inetName->sin_port = portNbr; memcpy((char *) &(inetName->sin_addr.s_addr), (char *) &hostNbr, 4); if (_tcpOutductId(&socketName, "tcp", ductName) < 0) { putErrmsg("Can't record TCP Outduct ID for connection.", NULL); MRELEASE(buffer); return -1; } /* Set up signal handling. SIGTERM is shutdown signal. */ oK(tcpcloSemaphore(&(vduct->semaphore))); isignal(SIGTERM, shutDownClo); #ifndef mingw isignal(SIGPIPE, handleConnectionLoss); #endif /* Start the keepalive thread for the eventual connection. */ tcpDesiredKeepAlivePeriod = KEEPALIVE_PERIOD; parms.cloRunning = &running; pthread_mutex_init(&mutex, NULL); parms.mutex = &mutex; parms.socketName = &socketName; parms.ductSocket = &ductSocket; parms.keepalivePeriod = &keepalivePeriod; if (pthread_begin(&keepaliveThread, NULL, sendKeepalives, &parms)) { putSysErrmsg("tcpclo can't create keepalive thread", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } // Returns the VInduct Object of first induct with same protocol // as the outduct. The VInduct is required to create an acq area. // The Acq Area inturn uses the throttle information from VInduct // object while receiving bundles. The throttle information // of all inducts of the same induct will be the same, so choosing // any induct will serve the purpose. findVInduct(&viduct,protocol.name); if(viduct == NULL) { putErrmsg("tcpclo can't get VInduct", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } rparms.vduct = viduct; rparms.bundleSocket = &ductSocket; rparms.mutex = &mutex; rparms.cloRunning = &running; if (pthread_begin(&receiverThread, NULL, receiveBundles, &rparms)) { putSysErrmsg("tcpclo can't create receive thread", NULL); MRELEASE(buffer); pthread_mutex_destroy(&mutex); return 1; } /* Can now begin transmitting to remote duct. */ { char txt[500]; isprintf(txt, sizeof(txt), "[i] tcpclo is running, spec=[%s:%d].", inet_ntoa(inetName->sin_addr), ntohs(inetName->sin_port)); writeMemo(txt); } while (running && !(sm_SemEnded(tcpcloSemaphore(NULL)))) { if (bpDequeue(vduct, outflows, &bundleZco, &extendedCOS, destDuctName, 0, -1) < 0) { running = 0; /* Terminate CLO. */ continue; } if (bundleZco == 0) /* Interrupted. */ { continue; } CHKZERO(sdr_begin_xn(sdr)); bundleLength = zco_length(sdr, bundleZco); sdr_exit_xn(sdr); pthread_mutex_lock(&mutex); bytesSent = sendBundleByTCPCL(&socketName, &ductSocket, bundleLength, bundleZco, buffer, &keepalivePeriod); pthread_mutex_unlock(&mutex); if(bytesSent < 0) { running = 0; /* Terminate CLO. */ } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } writeMemo("[i] tcpclo done sending"); if (sendShutDownMessage(&ductSocket, SHUT_DN_NO, -1, &socketName) < 0) { putErrmsg("Sending Shutdown message failed!!",NULL); } if (ductSocket != -1) { closesocket(ductSocket); ductSocket=-1; } running = 0; pthread_join(keepaliveThread, NULL); writeMemo("[i] tcpclo keepalive thread killed"); pthread_join(receiverThread, NULL); writeMemo("[i] tcpclo receiver thread killed"); writeErrmsgMemos(); writeMemo("[i] tcpclo duct has ended."); oK(_tcpOutductId(&socketName, NULL, NULL)); MRELEASE(buffer); pthread_mutex_destroy(&mutex); bp_detach(); return 0; }
static void *receiveBundles(void *parm) { /* Main loop for bundle reception thread */ ReceiveThreadParms *parms = (ReceiveThreadParms *) parm; int threadRunning = 1; AcqWorkArea *work; char *buffer; buffer = MTAKE(TCPCLA_BUFSZ); if (buffer == NULL) { putErrmsg("tcpclo receiver can't get TCP buffer", NULL); return NULL; } work = bpGetAcqArea(parms->vduct); if (work == NULL) { putErrmsg("tcpclo receiver can't get acquisition work area", NULL); MRELEASE(buffer); return NULL; } iblock(SIGTERM); while (threadRunning && *(parms->cloRunning)) { if(*(parms->bundleSocket) < 0) { snooze(1); /*Retry later*/ continue; } if (bpBeginAcq(work, 0, NULL) < 0) { putErrmsg("Can't begin acquisition of bundle.", NULL); threadRunning = 0; continue; } switch (receiveBundleByTcpCL(*(parms->bundleSocket), work, buffer)) { case -1: putErrmsg("Can't acquire bundle.", NULL); pthread_mutex_lock(parms->mutex); closesocket(*(parms->bundleSocket)); *(parms->bundleSocket) = -1; pthread_mutex_unlock(parms->mutex); continue; case 0: /* Shutdown message */ /* Go back to the start of the while loop */ pthread_mutex_lock(parms->mutex); closesocket(*(parms->bundleSocket)); *(parms->bundleSocket) = -1; pthread_mutex_unlock(parms->mutex); continue; default: break; /* Out of switch. */ } if (bpEndAcq(work) < 0) { putErrmsg("Can't end acquisition of bundle.", NULL); threadRunning = 0; } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } /* End of receiver thread; release resources. */ bpReleaseAcqArea(work); MRELEASE(buffer); return NULL; }
int bp_open(char *eidString, BpSAP *bpsapPtr) { Sdr sdr; MetaEid metaEid; VScheme *vscheme; PsmAddress vschemeElt; Sap sap; VEndpoint *vpoint; PsmAddress vpointElt; CHKERR(eidString && *eidString && bpsapPtr); *bpsapPtr = NULL; /* Default, in case of failure. */ sdr = getIonsdr(); sdr_begin_xn(sdr); /* Just to lock memory. */ /* First validate the endpoint ID. */ if (parseEidString(eidString, &metaEid, &vscheme, &vschemeElt) == 0) { sdr_exit_xn(sdr); putErrmsg("Malformed EID.", eidString); return -1; } if (vschemeElt == 0) { sdr_exit_xn(sdr); putErrmsg("Scheme not known.", metaEid.schemeName); restoreEidString(&metaEid); return -1; } findEndpoint(NULL, metaEid.nss, vscheme, &vpoint, &vpointElt); if (vpointElt == 0) { sdr_exit_xn(sdr); putErrmsg("Endpoint not known.", metaEid.nss); restoreEidString(&metaEid); return -1; } /* Endpoint exists; make sure it's not already opened * by some application. */ if (vpoint->appPid > 0) /* Endpoint not closed. */ { if (sm_TaskExists(vpoint->appPid)) { sdr_exit_xn(sdr); if (vpoint->appPid == sm_TaskIdSelf()) { return 0; } restoreEidString(&metaEid); putErrmsg("Endpoint is already open.", itoa(vpoint->appPid)); return -1; } /* Application terminated without closing the * endpoint, so simply close it now. */ vpoint->appPid = -1; } /* Construct the service access point. */ sap.vpoint = vpoint; memcpy(&sap.endpointMetaEid, &metaEid, sizeof(MetaEid)); sap.endpointMetaEid.colon = NULL; sap.endpointMetaEid.schemeName = MTAKE(metaEid.schemeNameLength + 1); if (sap.endpointMetaEid.schemeName == NULL) { sdr_exit_xn(sdr); putErrmsg("Can't create BpSAP.", NULL); restoreEidString(&metaEid); return -1; } sap.endpointMetaEid.nss = MTAKE(metaEid.nssLength + 1); if (sap.endpointMetaEid.nss == NULL) { sdr_exit_xn(sdr); MRELEASE(sap.endpointMetaEid.schemeName); putErrmsg("Can't create BpSAP.", NULL); restoreEidString(&metaEid); return -1; } *bpsapPtr = MTAKE(sizeof(Sap)); if (*bpsapPtr == NULL) { sdr_exit_xn(sdr); MRELEASE(sap.endpointMetaEid.nss); MRELEASE(sap.endpointMetaEid.schemeName); putErrmsg("Can't create BpSAP.", NULL); restoreEidString(&metaEid); return -1; } istrcpy(sap.endpointMetaEid.schemeName, metaEid.schemeName, sizeof sap.endpointMetaEid.schemeName); istrcpy(sap.endpointMetaEid.nss, metaEid.nss, sizeof sap.endpointMetaEid.nss); restoreEidString(&metaEid); sap.recvSemaphore = vpoint->semaphore; memcpy((char *) *bpsapPtr, (char *) &sap, sizeof(Sap)); /* Having created the SAP, give its owner exclusive * access to the endpoint. */ vpoint->appPid = sm_TaskIdSelf(); sdr_exit_xn(sdr); /* Unlock memory. */ return 0; }
static void *handleDatagrams(void *parm) { /* Main loop for UDP datagram reception and handling. */ ReceiverThreadParms *rtp = (ReceiverThreadParms *) parm; char *procName = "udplsi"; char *buffer; int segmentLength; struct sockaddr_in fromAddr; socklen_t fromSize; snooze(1); /* Let main thread become interruptable. */ buffer = MTAKE(UDPLSA_BUFSZ); if (buffer == NULL) { putErrmsg("udplsi can't get UDP buffer.", NULL); ionKillMainThread(procName); return NULL; } /* Can now start receiving bundles. On failure, take * down the LSI. */ while (rtp->running) { fromSize = sizeof fromAddr; segmentLength = irecvfrom(rtp->linkSocket, buffer, UDPLSA_BUFSZ, 0, (struct sockaddr *) &fromAddr, &fromSize); switch (segmentLength) { case -1: putSysErrmsg("Can't acquire segment", NULL); ionKillMainThread(procName); /* Intentional fall-through to next case. */ case 1: /* Normal stop. */ rtp->running = 0; continue; } if (ltpHandleInboundSegment(buffer, segmentLength) < 0) { putErrmsg("Can't handle inbound segment.", NULL); ionKillMainThread(procName); rtp->running = 0; continue; } /* Make sure other tasks have a chance to run. */ sm_TaskYield(); } writeErrmsgMemos(); writeMemo("[i] udplsi receiver thread has ended."); /* Free resources. */ MRELEASE(buffer); return NULL; }