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; }
static int udpParseMamsEndpoint(MamsEndpoint *ep) { char *colon; char hostName[MAXHOSTNAMELEN + 1]; UdpTsep tsep; if (ep == NULL || ep->ept == NULL) { errno = EINVAL; putErrmsg("udpts can't parse MAMS endpoint name.", NULL); return -1; } colon = strchr(ep->ept, ':'); *colon = '\0'; istrcpy(hostName, ep->ept, sizeof hostName); *colon = ':'; tsep.portNbr = atoi(colon + 1); tsep.ipAddress = getInternetAddress(hostName); ep->tsep = MTAKE(sizeof(UdpTsep)); if (ep->tsep == NULL) { putSysErrmsg("udpts can't record parsed MAMS endpoint name.", NULL); return -1; } memcpy((char *) (ep->tsep), (char *) &tsep, sizeof(UdpTsep)); //printf("parsed '%s' to port %d address %d.\n", ep->ept, tsep.portNbr, //tsep.ipAddress); return 0; }
/** * \brief Convenience function to build a data report. * * \author Ed Birrane * * \note * - We shallow copy information into the message. So, don't release anything * provided as an argument to this function. * * \return NULL - Failure * !NULL - Created message. * * \param[in] time The time when the report was created. * \param[in[ reports The data reports. */ rpt_data_t *rpt_create_data(time_t time, Lyst reports, eid_t recipient) { rpt_data_t *result = NULL; DTNMP_DEBUG_ENTRY("rpt_create_data","(%d,0x%x,%s)", time, (unsigned long) reports, recipient.name); /* Step 0: Sanity Check. */ if(reports == NULL) { DTNMP_DEBUG_ERR("rpt_create_data","Bad Args.",NULL); DTNMP_DEBUG_EXIT("rpt_create_data","->NULL",NULL); return NULL; } /* Step 1: Allocate the message. */ if((result = (rpt_data_t*) MTAKE(sizeof(rpt_data_t))) == NULL) { DTNMP_DEBUG_ERR("rpt_create_data","Can't alloc %d bytes.", sizeof(rpt_data_t)); DTNMP_DEBUG_EXIT("rpt_create_data","->NULL",NULL); return NULL; } /* Step 2: Populate the message. */ result->time = time; result->reports = reports; result->recipient = recipient; result->size = 0; DTNMP_DEBUG_EXIT("rpt_create_data","->0x%x",result); return result; }
/** * \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; }
expr_result_t ltp_get_eng_all(Lyst params) { datacol_entry_t *entry = (datacol_entry_t*)lyst_data(lyst_first(params)); unsigned long val = 0; unsigned int engineId = 0; expr_result_t result; result.type = EXPR_TYPE_UINT32; /* \todo: Check for NULL entry here. */ NmltpSpan span; int success = 0; memcpy(&val, entry->value, sizeof(val)); engineId = val; result.length = 0; result.value = NULL; ltpnm_span_get(engineId, &span, &success); if(success != 0) { result.value = (uint8_t*) MTAKE(sizeof(span)); memcpy(result.value, &span, sizeof(span)); result.length = sizeof(span); } return result; }
static int udpParseAmsEndpoint(AmsEndpoint *dp) { char *colon; char hostName[MAXHOSTNAMELEN + 1]; UdpTsep tsep; if (dp == NULL || dp->ept == NULL) { errno = EINVAL; putErrmsg("udpts can't parse AMS endpoint.", NULL); return -1; } colon = strchr(dp->ept, ':'); *colon = '\0'; istrcpy(hostName, dp->ept, sizeof hostName); *colon = ':'; tsep.portNbr = atoi(colon + 1); tsep.ipAddress = getInternetAddress(hostName); dp->tsep = MTAKE(sizeof(UdpTsep)); if (dp->tsep == NULL) { putSysErrmsg("udpts can't record parsed AMS endpoint name.", NULL); return -1; } memcpy((char *) (dp->tsep), (char *) &tsep, sizeof(UdpTsep)); /* Also parse out the QOS of this endpoint. */ dp->diligence = AmsBestEffort; dp->sequence = AmsArrivalOrder; return 0; }
uint8_t* adm_copy_string(char *value, uint64_t *length) { uint8_t *result = NULL; uint32_t size = 0; DTNMP_DEBUG_ENTRY("adm_copy_string","(%#llx, %d, %#llx)", value, size, length); /* Step 0 - Sanity Check. */ if((value == NULL) || (length == NULL)) { DTNMP_DEBUG_ERR("adm_copy_string","Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_copy_string","->NULL.", NULL); return NULL; } size = strlen(value) + 1; /* Step 1 - Alloc new space. */ if((result = (uint8_t *) MTAKE(size)) == NULL) { DTNMP_DEBUG_ERR("adm_copy_string","Can't alloc %d bytes.", size); DTNMP_DEBUG_EXIT("adm_copy_string","->NULL.", NULL); return NULL; } /* Step 2 - Copy data in. */ *length = size; memcpy(result, value, size); /* Step 3 - Return. */ DTNMP_DEBUG_EXIT("adm_copy_string","->%s", (char *)result); return (uint8_t*)result; }
/** * \brief Convenience function to build data report message. * * \author Ed Birrane * * \note * - We shallow copy information into the message. So, don't release anything * provided as an argument to this function. * * \return NULL - Failure * !NULL - Created message. * * \param[in[ contents The data IDs available. */ rpt_items_t *rpt_create_lst(Lyst contents) { rpt_items_t *result = NULL; DTNMP_DEBUG_ENTRY("rpt_create_lst","(0x%x)", (unsigned long) contents); /* Step 0: Sanity Check. */ if(contents == NULL) { DTNMP_DEBUG_ERR("rpt_create_lst","Bad Args.",NULL); DTNMP_DEBUG_EXIT("rpt_create_lst","->NULL",NULL); return NULL; } /* Step 1: Allocate the message. */ if((result = (rpt_items_t*)MTAKE(sizeof(rpt_items_t))) == NULL) { DTNMP_DEBUG_ERR("rpt_create_lst","Can't alloc %d bytes.", sizeof(rpt_items_t)); DTNMP_DEBUG_EXIT("rpt_create_lst","->NULL",NULL); return NULL; } /* Step 2: Populate the message. */ result->contents = contents; DTNMP_DEBUG_EXIT("rpt_create_lst","->0x%x",result); return result; }
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 adm_add_datadef(char *name, uint8_t *mid_str, int num_parms, adm_string_fn to_string, adm_size_fn get_size) { uint32_t size = 0; uint32_t used = 0; adm_datadef_t *new_entry = NULL; DTNMP_DEBUG_ENTRY("adm_add_datadef","(%llx, %llx, %d, %llx, %llx)", name, mid_str, num_parms, to_string, get_size); /* Step 0 - Sanity Checks. */ if((name == NULL) || (mid_str == NULL)) { DTNMP_DEBUG_ERR("adm_add_datadef","Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_add_datadef","->.", NULL); return; } if(gAdmData == NULL) { DTNMP_DEBUG_ERR("adm_add_datadef","Global data list not initialized.", NULL); DTNMP_DEBUG_EXIT("adm_add_datadef","->.", NULL); return; } /* Step 1 - Check name length. */ if(strlen(name) > ADM_MAX_NAME) { DTNMP_DEBUG_WARN("adm_add_datadef","Trunc. %s to %d bytes.", name, ADM_MAX_NAME) } /* Step 2 - Allocate a Data Definition. */ if((new_entry = (adm_datadef_t *) MTAKE(sizeof(adm_datadef_t))) == NULL) { DTNMP_DEBUG_ERR("adm_add_datadef","Can't allocate new entry of size %d.", sizeof(adm_datadef_t)); DTNMP_DEBUG_EXIT("adm_add_datadef","->.", NULL); return; } /* Step 3 - Copy the ADM information. */ strncpy((char *)new_entry->name, name, ADM_MAX_NAME); new_entry->mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used); new_entry->num_parms = num_parms; new_entry->collect = NULL; new_entry->to_string = (to_string == NULL) ? adm_print_uvast : to_string; new_entry->get_size = (get_size == NULL) ? adm_size_uvast : get_size; /* Step 4 - Add the new entry. */ lyst_insert_last(gAdmData, new_entry); DTNMP_DEBUG_EXIT("adm_add_datadef","->.", NULL); return; }
/****************************************************************************** * * \par Function Name: adm_print_unsigned_long_list * * \par Generates a single string representation of a list of unsigned longs. * * \retval NULL Failure * !NULL The string representation of the ADM entry value. * * \param[in] buffer The start of the ADM entry value. * \param[in] buffer_len Length of the given buffer. * \param[in] data_len Length of data item at head of the buffer. * \param[out] str_len Length of returned string from print function. * * \par Notes: * 1. The string representation is allocated on the heap and must be * freed when no longer necessary. * * Modification History: * MM/DD/YY AUTHOR DESCRIPTION * -------- ------------ --------------------------------------------- * 11/25/12 E. Birrane Initial implementation. *****************************************************************************/ char *adm_print_unsigned_long_list(uint8_t* buffer, uint64_t buffer_len, uint64_t data_len, uint32_t *str_len) { char *result = NULL; char *cursor = NULL; uint8_t *buf_ptr = NULL; uvast num = 0; unsigned long val = 0; int len = 0; DTNMP_DEBUG_ENTRY("adm_print_unsigned_long_list", "(%#llx, %ull, %ull, %#llx)", buffer, buffer_len, data_len, str_len); /* Step 0 - Sanity Checks. */ if((buffer == NULL) || (str_len == NULL)) { DTNMP_DEBUG_ERR("adm_print_unsigned_long_list", "Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_print_unsigned_long_list", "->NULL.", NULL); return NULL; } /* Step 1 - Figure out how many unsigned longs we need to print out. */ buf_ptr = buffer; len = decodeSdnv(&num, buf_ptr); buf_ptr += len; /* Step 2 - Size & allocate the string. */ *str_len = data_len + /* Data length */ 9 + /* Header info. */ (2 * len) + /* ", " per number */ 1; /* Trailer. */ if((result = (char *) MTAKE(*str_len)) == NULL) { DTNMP_DEBUG_ERR("adm_print_unsigned_long_list", "Can't alloc %d bytes.", *str_len); *str_len = 0; DTNMP_DEBUG_EXIT("adm_print_unsigned_long_list", "->NULL.", NULL); return NULL; } /* Step 3 - Accumulate string result. */ cursor = result; cursor += sprintf(cursor,"("UVAST_FIELDSPEC"): ",num); int i; for(i = 0; i < num; i++) { memcpy(&val, buf_ptr, sizeof(val)); buf_ptr += sizeof(val); cursor += sprintf(cursor, "%ld, ",val); } DTNMP_DEBUG_EXIT("adm_print_unsigned_long_list", "->%#llx.", result); return result; }
void adm_add_ctrl(char *name, uint8_t *mid_str, int num_parms) { uint8_t *tmp = NULL; uint32_t size = 0; uint32_t used = 0; adm_ctrl_t *new_entry = NULL; DTNMP_DEBUG_ENTRY("adm_add_ctrl","(%#llx, %#llx, %d)", name, mid_str, num_parms); /* Step 0 - Sanity Checks. */ if((name == NULL) || (mid_str == NULL)) { DTNMP_DEBUG_ERR("adm_add_ctrl","Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_add_ctrl","->.", NULL); return; } if(gAdmCtrls == NULL) { DTNMP_DEBUG_ERR("adm_add_ctrl","Global Controls list not initialized.", NULL); DTNMP_DEBUG_EXIT("adm_add_ctrl","->.", NULL); return; } /* Step 1 - Check name length. */ if(strlen(name) > ADM_MAX_NAME) { DTNMP_DEBUG_WARN("adm_add_ctrl","Trunc. %s to %d bytes.", name, ADM_MAX_NAME) } /* Step 2 - Allocate a Data Definition. */ if((new_entry = (adm_ctrl_t *) MTAKE(sizeof(adm_ctrl_t))) == NULL) { DTNMP_DEBUG_ERR("adm_add_ctrl","Can't allocate new entry of size %d.", sizeof(adm_datadef_t)); DTNMP_DEBUG_EXIT("adm_add_ctrl","->.", NULL); return; } /* Step 3 - Copy the ADM information. */ strncpy((char *)new_entry->name, name, ADM_MAX_NAME); new_entry->mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used); //new_entry->mid_len = size; new_entry->num_parms = num_parms; new_entry->run = NULL; /* Step 4 - Add the new entry. */ lyst_insert_last(gAdmCtrls, new_entry); DTNMP_DEBUG_EXIT("adm_add_ctrl","->.", NULL); return; }
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; }
char *adm_print_string_list(uint8_t* buffer, uint64_t buffer_len, uint64_t data_len, uint32_t *str_len) { char *result = NULL; char *cursor = NULL; uint8_t *buf_ptr = NULL; uvast num = 0; int len = 0; DTNMP_DEBUG_ENTRY("adm_print_string_list", "(%#llx, %ull, %ull, %#llx)", buffer, buffer_len, data_len, str_len); /* Step 0 - Sanity Checks. */ if((buffer == NULL) || (str_len == NULL)) { DTNMP_DEBUG_ERR("adm_print_string_list", "Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_print_string_list", "->NULL.", NULL); return NULL; } /* Step 1 - Figure out size of resulting string. */ buf_ptr = buffer; len = decodeSdnv(&num, buf_ptr); buf_ptr += len; *str_len = data_len + /* String length */ 9 + /* Header info. */ (2 * len) + /* ", " per string */ 1; /* Trailer. */ /* Step 2 - Allocate the result. */ if((result = (char *) MTAKE(*str_len)) == NULL) { DTNMP_DEBUG_ERR("adm_print_string_list","Can't alloc %d bytes", *str_len); *str_len = 0; DTNMP_DEBUG_EXIT("adm_print_string_list", "->NULL.", NULL); return NULL; } /* Step 3 - Accumulate the result. */ cursor = result; cursor += sprintf(cursor,"("UVAST_FIELDSPEC"): ",num); /* Add stirngs to result. */ int i; for(i = 0; i < num; i++) { cursor += sprintf(cursor, "%s, ",buf_ptr); buf_ptr += strlen((char*)buf_ptr) + 1; } DTNMP_DEBUG_EXIT("adm_print_string_list", "->%#llx.", result); return result; }
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); } } }
expr_result_t ltp_get_heap_bytes_used(Lyst params) { unsigned long bytes_reserved = 0; unsigned long bytes_used = 0; expr_result_t result; result.type = EXPR_TYPE_UINT32; ltpnm_resources(&bytes_reserved, &bytes_used); result.length = sizeof(unsigned long); result.value = (uint8_t*) MTAKE(result.length); memcpy(result.value, &bytes_used, sizeof(bytes_used)); return result; }
/****************************************************************************** * * \par Function Name: adm_print_uvast * * \par Generates a single string representation of a uvast. * * \retval NULL Failure * !NULL The string representation of the ADM entry value. * * \param[in] buffer The start of the ADM entry value. * \param[in] buffer_len Length of the given buffer. * \param[in] data_len Length of data item at head of the buffer. * \param[out] str_len Length of returned string from print function. * * \par Notes: * 1. The string representation is allocated on the heap and must be * freed when no longer necessary. * * Modification History: * MM/DD/YY AUTHOR DESCRIPTION * -------- ------------ --------------------------------------------- * 08/16/13 E. Birrane Initial implementation. *****************************************************************************/ char *adm_print_uvast(uint8_t* buffer, uint64_t buffer_len, uint64_t data_len, uint32_t *str_len) { char *result; uint64_t temp = 0; DTNMP_DEBUG_ENTRY("adm_print_uvast", "(%#llx, %ull, %ull, %#llx)", buffer, buffer_len, data_len, str_len); /* Step 0 - Sanity Checks. */ if((buffer == NULL) || (str_len == NULL)) { DTNMP_DEBUG_ERR("adm_print_uvast", "Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_print_uvast", "->NULL.", NULL); return NULL; } /* Step 1 - Make sure we have buffer space. */ if(data_len > buffer_len) { DTNMP_DEBUG_ERR("adm_print_uvast","Data Len %d > buf len %d.", data_len, buffer_len); *str_len = 0; DTNMP_DEBUG_EXIT("adm_print_uvast", "->NULL.", NULL); return NULL; } /* Step 2 - Size the string and allocate it. * \todo: A better estimate should go here. */ *str_len = 32; if((result = (char *) MTAKE(*str_len)) == NULL) { DTNMP_DEBUG_ERR("adm_print_uvast","Can't alloc %d bytes.", *str_len); *str_len = 0; DTNMP_DEBUG_EXIT("adm_print_uvast", "->NULL.", NULL); return NULL; } /* Step 3 - Copy data and return. */ memcpy(&temp, buffer, data_len); isprintf(result,*str_len,UVAST_FIELDSPEC, temp); DTNMP_DEBUG_EXIT("adm_print_uvast", "->%#llx.", result); return result; }
expr_result_t ltp_get_node_resources_all(Lyst params) { unsigned long bytes_reserved = 0; unsigned long bytes_used = 0; expr_result_t result; result.type = EXPR_TYPE_BLOB; ltpnm_resources(&bytes_reserved, &bytes_used); result.length = sizeof(unsigned long) * 2; result.value = (uint8_t*) MTAKE(result.length); memcpy(result.value, &bytes_reserved, sizeof(bytes_reserved)); memcpy(&(result.value[sizeof(bytes_reserved)]), &bytes_used, sizeof(bytes_used)); return result; }
/** * \brief Creates a report policy message from a buffer. * * \author Ed Birrane * * \note * - On failure (NULL return) we do NOT de-allocate the passed-in header. * * \return NULL - failure * !NULL - message. * * \param[in] cursor The buffer holding the message. * \param[in] size The remaining buffer size. * \param[out] bytes_used Bytes consumed in the deserialization. */ adm_rpt_policy_t *msg_deserialize_rpt_policy(uint8_t *cursor, uint32_t size, uint32_t *bytes_used) { adm_rpt_policy_t *result = NULL; uint32_t bytes = 0; DTNMP_DEBUG_ENTRY("msg_deserialize_rpt_policy","(0x%x, %d, 0x%x)", (unsigned long)cursor, size, (unsigned long) bytes_used); /* Step 0: Sanity Checks. */ if((cursor == NULL) || (bytes_used == 0)) { DTNMP_DEBUG_ERR("msg_deserialize_rpt_policy","Bad Args.",NULL); DTNMP_DEBUG_EXIT("msg_deserialize_rpt_policy","->NULL",NULL); return NULL; } /* Step 1: Allocate the new message structure. */ if((result = (adm_rpt_policy_t*)MTAKE(sizeof(adm_rpt_policy_t))) == NULL) { DTNMP_DEBUG_ERR("msg_deserialize_rpt_policy","Can't Alloc %d Bytes.", sizeof(adm_rpt_policy_t)); *bytes_used = 0; DTNMP_DEBUG_EXIT("msg_deserialize_rpt_policy","->NULL",NULL); return NULL; } else { memset(result,0,sizeof(adm_rpt_policy_t)); } /* Step 2: Deserialize the message. */ /* Grab the mask */ result->mask = *cursor; cursor++; size--; *bytes_used += 1; DTNMP_DEBUG_EXIT("msg_deserialize_rpt_policy","->0x%x", (unsigned long)result); return result; }
uint8_t *mid_serialize(mid_t *mid, uint32_t *size) { uint8_t *result = NULL; DTNMP_DEBUG_ENTRY("mid_serialize","(%#llx, %#llx)", (unsigned long) mid, (unsigned long) size); /* Step 0: Sanity Check. */ if((mid == NULL) || (size == NULL)) { DTNMP_DEBUG_ERR("mid_serialize","Bad args.", NULL); DTNMP_DEBUG_EXIT("mid_serialize","->NULL", NULL); return NULL; } /* Step 1: Make sure the MID is serialized. */ if((mid->raw == NULL) || (mid->raw_size == 0)) { if(mid_internal_serialize(mid) == 0) { DTNMP_DEBUG_ERR("mid_serialize","Can't serialize mid.", NULL); *size = 0; DTNMP_DEBUG_EXIT("mid_serialize","->NULL", NULL); return NULL; } } *size = mid->raw_size; /* Step 2: Allocate result. */ if((result = (uint8_t*) MTAKE(*size)) == NULL) { DTNMP_DEBUG_ERR("mid_serialize","Can't alloc %d bytes.", *size); *size = 0; DTNMP_DEBUG_EXIT("mid_serialize","->NULL", NULL); return NULL; } /* Step 3: Copy in the result. */ memcpy(result, mid->raw, mid->raw_size); DTNMP_DEBUG_EXIT("mid_serialize","->%#llx", (unsigned long)result); return result; }
/****************************************************************************** * * \par Function Name: adm_print_string * * \par Performs the somewhat straightforward function of building a string * representation of a string. This is a generic to-string function for * ADM entries whose values are strings. * * \retval NULL Failure * !NULL The string representation of the ADM entry value. * * \param[in] buffer The start of the ADM entry value. * \param[in] buffer_len Length of the given buffer. * \param[in] data_len Length of data item at head of the buffer. * \param[out] str_len Length of returned string from print function. * * \par Notes: * 1. The string representation is allocated on the heap and must be * freed when no longer necessary. * * Modification History: * MM/DD/YY AUTHOR DESCRIPTION * -------- ------------ --------------------------------------------- * 11/25/12 E. Birrane Initial implementation. *****************************************************************************/ char *adm_print_string(uint8_t* buffer, uint64_t buffer_len, uint64_t data_len, uint32_t *str_len) { char *result = NULL; uint32_t len = 0; DTNMP_DEBUG_ENTRY("adm_print_string","(%#llx, %ull, %ull, %#llx)", buffer, buffer_len, data_len, str_len); /* Step 0 - Sanity Checks. */ if((buffer == NULL) || (str_len == NULL)) { DTNMP_DEBUG_ERR("adm_print_string", "Bad Args.", NULL); DTNMP_DEBUG_EXIT("adm_print_string", "->NULL.", NULL); return NULL; } /* Step 1 - Data at head of buffer should be a string. Grab len & check. */ len = strlen((char*) buffer); if((len > buffer_len) || (len != data_len)) { DTNMP_DEBUG_ERR("adm_print_string", "Bad len %d. Expected %d.", len, data_len); DTNMP_DEBUG_EXIT("adm_print_string", "->NULL.", NULL); return NULL; } /* Step 2 - Allocate size for string rep. of the string value. */ *str_len = len + 1; if((result = (char *) MTAKE(*str_len)) == NULL) { DTNMP_DEBUG_ERR("adm_print_string", "Can't alloc %d bytes", *str_len); DTNMP_DEBUG_EXIT("adm_print_string", "->NULL.", NULL); return NULL; } /* Step 3 - Copy over. */ sprintf(result,"%s", (char*) buffer); DTNMP_DEBUG_EXIT("adm_print_string", "->%s.", result); return result; }
expr_result_t ltp_get_engines(Lyst params) { unsigned int ids[32]; uint8_t *cursor = NULL; int num = 0; unsigned long val = 0; Sdnv num_sdnv; expr_result_t result; result.type = EXPR_TYPE_BLOB; ltpnm_spanEngineIds_get(ids, &num); if(num > 32) { fprintf(stderr,"We do not support more than 32 engines. Aborting.\n"); exit(1); } encodeSdnv(&num_sdnv, num); result.length = num_sdnv.length + /* NUM as SDNV length */ (num * sizeof(unsigned long)); result.value = (uint8_t *) MTAKE(result.length); cursor = result.value; memcpy(cursor,num_sdnv.text, num_sdnv.length); cursor += num_sdnv.length; for(int i = 0; i < num; i++) { val = ids[i]; memcpy(cursor,&val, sizeof(val)); cursor += sizeof(val); } return result; }
static int udpMamsInit(MamsInterface *tsif) { unsigned short portNbr; unsigned int ipAddress; char hostName[MAXHOSTNAMELEN + 1]; struct sockaddr socketName; struct sockaddr_in *inetName; socklen_t nameLength; int fd; char endpointNameText[32]; int eptLen; long longfd; parseSocketSpec(tsif->endpointSpec, &portNbr, &ipAddress); //printf("parsed endpoint spec to port %d address %d.\n", portNbr, ipAddress); if (ipAddress == 0) { getNameOfHost(hostName, sizeof hostName); ipAddress = getInternetAddress(hostName); } else { if (getInternetHostName(ipAddress, hostName) == NULL) { putErrmsg("Unknown host in endpoint.", tsif->endpointSpec); return -1; } } portNbr = htons(portNbr); ipAddress = htonl(ipAddress); 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 *) &ipAddress, 4); fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) { putSysErrmsg("udpts can't open MAMS SAP", NULL); return -1; } nameLength = sizeof(struct sockaddr); if (reUseAddress(fd) || bind(fd, &socketName, nameLength) < 0 || getsockname(fd, &socketName, &nameLength) < 0) { putSysErrmsg("udpts can't initialize AMS SAP", NULL); return -1; } portNbr = inetName->sin_port; portNbr = ntohs(portNbr); memcpy((char *) &ipAddress, (char *) &(inetName->sin_addr.s_addr), 4); ipAddress = ntohl(ipAddress); isprintf(endpointNameText, sizeof endpointNameText, "%s:%hu", hostName, portNbr); //printf("resulting ept is '%s'.\n", endpointNameText); eptLen = strlen(endpointNameText) + 1; tsif->ept = MTAKE(eptLen); if (tsif->ept == NULL) { close(fd); putSysErrmsg(NoMemoryMemo, NULL); return -1; } istrcpy(tsif->ept, endpointNameText, eptLen); longfd = fd; tsif->sap = (void *) longfd; 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; }
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; }
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 int udpAmsInit(AmsInterface *tsif, char *epspec) { unsigned short portNbr; unsigned int ipAddress; char hostName[MAXHOSTNAMELEN + 1]; struct sockaddr socketName; struct sockaddr_in *inetName; socklen_t nameLength; int fd; char endpointNameText[32]; int eptLen; long longfd; if (strcmp(epspec, "@") == 0) /* Default. */ { epspec = NULL; /* Force default selection. */ } parseSocketSpec(epspec, &portNbr, &ipAddress); if (ipAddress == 0) { getNameOfHost(hostName, sizeof hostName); ipAddress = getInternetAddress(hostName); } else { if (getInternetHostName(ipAddress, hostName) == NULL) { putErrmsg("Unknown host in endpoint.", epspec); return -1; } } portNbr = htons(portNbr); ipAddress = htonl(ipAddress); 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 *) &ipAddress, 4); fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) { putSysErrmsg("udpts can't open AMS SAP", NULL); return -1; } nameLength = sizeof(struct sockaddr); if (reUseAddress(fd) || bind(fd, &socketName, nameLength) < 0 || getsockname(fd, &socketName, &nameLength) < 0) { putSysErrmsg("udpts can't initialize AMS SAP", NULL); return -1; } portNbr = inetName->sin_port; portNbr = ntohs(portNbr); memcpy((char *) &ipAddress, (char *) &(inetName->sin_addr.s_addr), 4); ipAddress = ntohl(ipAddress); tsif->diligence = AmsBestEffort; tsif->sequence = AmsArrivalOrder; isprintf(endpointNameText, sizeof endpointNameText, "%s:%hu", hostName, portNbr); eptLen = strlen(endpointNameText) + 1; tsif->ept = MTAKE(eptLen); if (tsif->ept == NULL) { close(fd); putSysErrmsg(NoMemoryMemo, NULL); return -1; } istrcpy(tsif->ept, endpointNameText, eptLen); longfd = fd; tsif->sap = (void *) longfd; 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; }