/*=r=*************************************************************************/ static void m__release_a_file_data_pdu (MACHINE *m, FD *fd) /* WHAT IT DOES: Outputs a Filedata PDU */ { TRANS_STATUS *mp = &(m->publik); /* useful shorthand */ /*------------------------------------------------------------*/ /*----------------*/ /* Output the PDU */ /*----------------*/ aaa__send_one_file_data_pdu (m, fd); /*----------------------------------------------------*/ /* Perform actions required after the PDU is released */ /*----------------------------------------------------*/ /* Update the list of data to be sent (bookkeeping) */ nak__data_sent (&(m->nak), fd->offset, fd->offset + fd->buffer_length); /* If the entire file has been sent, build and queue an EOF PDU */ if (nak__how_many_filedata_gaps (&(m->nak)) == 0) { m->eof = aaa__build_eof (mp->condition_code, mp->file_checksum_as_calculated, mp->md.file_size); m->is_outgoing_eof_buffered = YES; } }
/*=r=************************************************************************/ char *nak__list_as_string (NAK *nak_ptr) { #define LONGEST_STRING 256 #define LONGEST_SUBSTRING 32 boolean out_of_room = NO; NODE *p; static char string [LONGEST_STRING]; char substring [LONGEST_SUBSTRING]; /*------------------------------------------------------------*/ /* Include the scope of the Nak */ sprintf (string, "(%lu-%lu)", nak_ptr->start_of_scope, nak_ptr->end_of_scope); /* Include whether or not Metadata is missing */ if (nak_ptr->is_metadata_missing) APPEND (string, " Metadata"); /* Include as many File-data gaps as will fit in the string */ if (nak_ptr->head != NULL) for (p=nak_ptr->head; p!=NULL; p=p->next) { if (!out_of_room) { if (strlen(string) + LONGEST_SUBSTRING + 64 >= LONGEST_STRING) /* Careful. We are in danger of writing past the end of the * allotted memory for 'string' (i.e. we are out of room). * We'll have to skip some gaps. * Hopefully, the user understands that "..." indicates * that there are more gaps. */ { out_of_room = YES; APPEND (string, " ... "); } else /* The normal case; add this gap to the string */ { sprintf (substring, " %lu-%lu", p->begin, p->end); APPEND (string, substring); } } else /* We already ran out of room; ignore all but the last gap */ { if (p->next == NULL) /* This is the last gap */ { sprintf (substring, " %lu-%lu", p->begin, p->end); APPEND (string, substring); } } } /* Show how many gaps there are */ sprintf (substring, " (%lu total gaps)\n", nak__how_many_filedata_gaps (nak_ptr)); APPEND (string, substring); return (string); }
/*=r=************************************************************************/ void s1__state_table (MACHINE *m, int event, PDU_AS_STRUCT *pdu_ptr, REQUEST *req_ptr) /* NOTE: Why is there no mention of 'state' in this routine? * Although the state tables originally used two states for the * Class 1 Sender (as published in a CCSDS Green Book for CFDP), * the logic has since been rearranged so that only one state * is necessary. */ { static FD fd; TRANS_STATUS *mp = &(m->publik); /* useful shorthand */ /*------------------------------------------------------------*/ /* Possibly display some debug info */ if (cfdp_is_message_class_enabled (CFDP_MSG_STATE_ALL)) aaa__display_state_and_event ("S1", m->publik.state, event); /*-----------------------*/ /* Respond to each Event */ /*-----------------------*/ if (event == THROTTLE_OUTGOING_FILE_DIR_PDU) /* Release, at most, one outgoing File Directive PDU */ { if (mp->frozen || mp->suspended) /* We can't release any PDUs while frozen or suspended */ ; else if (m->is_outgoing_md_buffered) /* We're not frozen or suspended, so we can release any PDU. * A Metadata is ready. Do we have the "green light"? */ { if (pdu_output__ready (FILE_DIR_PDU, mp->trans, m->hdr.dest_id)) /* Light is green. Send it. */ m__release_a_metadata_pdu (m); } else if (m->is_outgoing_eof_buffered) /* We're not frozen or suspended, so we can release any PDU. * An EOF is ready. Do we have the "green light"? */ { if (pdu_output__ready (FILE_DIR_PDU, mp->trans, m->hdr.dest_id)) /* Light is green. Send it. */ m__release_an_eof_pdu (m); } } else if (event == THROTTLE_OUTGOING_FILE_DATA_PDU) /* Release, at most, one outgoing Filedata PDU. */ { if (mp->frozen || mp->suspended) /* We can't release Filedata PDUs while frozen or suspended */ ; else if (nak__how_many_filedata_gaps (&(m->nak)) > 0) /* There is File Data ready. Do we have the "green light?" */ { if (pdu_output__ready (FILE_DATA_PDU, mp->trans, m->hdr.dest_id)) /* Light is green. Send it. */ m__release_a_file_data_pdu (m, &fd); } } else if (event == RECEIVED_PUT_REQUEST) /* Received a Put Request */ { /* Generate a Metadata pdu */ aaa__build_metadata_from_put_req (*req_ptr, &m->hdr, &mp->md); /* Store some Header info for public viewing */ mp->trans = m->hdr.trans; mp->partner_id = req_ptr->info.put.dest_id; /* 'Indication' callback allows engine user to respond to events */ indication__ (IND_TRANSACTION, &(m->publik)); indication__ (IND_MACHINE_ALLOCATED, &(m->publik)); /* Queue the Metadata PDU for output */ m->is_outgoing_md_buffered = YES; } else if (event == RECEIVED_SUSPEND_REQUEST) /* A Suspend Request was received; suspend */ aaa__notice_of_suspension (m); else if (event == RECEIVED_RESUME_REQUEST) /* A Resume Request was received; resume */ { /* 'Indication' callback allows engine user to respond to events */ indication__ (IND_RESUMED, &(m->publik)); mp->suspended = NO; } else if (event == RECEIVED_CANCEL_REQUEST) /* A Cancel Request was received; cancel the transaction */ { mp->cancelled = YES; mp->condition_code = CANCEL_REQUEST_RECEIVED; m__ask_partner_to_cancel (m); } else if (event == RECEIVED_ABANDON_REQUEST) /* Abandon this transaction */ aaa__abandon_this_transaction (m); else if (event == RECEIVED_REPORT_REQUEST) /* A Report Request was received; issue a Report */ indication__ (IND_REPORT, &(m->publik)); else if (event == RECEIVED_FREEZE_REQUEST) /* A "Freeze" was received, so Freeze */ mp->frozen = YES; else if (event == RECEIVED_THAW_REQUEST) /* A "Thaw" was received, so Thaw */ mp->frozen = NO; else if (event == EXTERNAL_FILE_TRANSFER_COMPLETED) /* This event was added in May 2007 to support high-speed (external) * file transfer by the engine user. When this event fires, we know * that the engine user has completed sending the first round of * Filedata PDUs. Therefore, we can send the EOF PDU. */ { m->eof = aaa__build_eof (mp->condition_code, mp->file_checksum_as_calculated, mp->md.file_size); m->is_outgoing_eof_buffered = YES; /* Clear the flags related to external xfer */ m->is_external_xfer_open = NO; m->should_external_xfer_be_closed = NO; } else /* The above events are the only ones that should occur. If some * other event occurs, ignore it (but warn the user). */ w_msg__ ("cfdp_engine: ignored event '%s' for trans '%s' <S1>.\n", event__event_as_string(event), cfdp_trans_as_string (mp->trans)); }