int app_send_file(const char* term, const char* file_name) { LOG // open file FILE* file = fopen(file_name, "rb"); if (!file) { perror("fopen"); return -1; } // start link layer int fd = ll_open(term, TRANSMITTER); if (fd == -1) { perror("ll_open"); return -1; } int file_size = get_file_size(file); if (file_size == -1) { perror("get_file_size"); return -1; } // build control params control_param paramStartFileSize; paramStartFileSize.type = FIELD_PARAM_TYPE_FILE_SIZE; paramStartFileSize.file_size.size.w = file_size; control_param paramStartFileName; paramStartFileName.type = FIELD_PARAM_TYPE_FILE_NAME; paramStartFileName.file_name.name = (char*)file_name; control_param params[] = { paramStartFileSize, paramStartFileName }; if (app_send_control_packet(fd, CONTROL_FIELD_START, 2, params) != 0) { perror("app_send_control_packet"); return -1; } int i = 0; char* buffer = malloc(MAX_DATA_PACKET_SIZE); size_t read_bytes; size_t write_bytes = 0; while ((read_bytes = fread(buffer, sizeof(char), MAX_DATA_PACKET_SIZE, file)) != 0) { if (app_send_data_packet(fd, (i++) % 255, buffer, read_bytes) == -1) { perror("app_send_data_packet"); free(buffer); return -1; } write_bytes += read_bytes; buffer = memset(buffer, 0, MAX_DATA_PACKET_SIZE); printf("\rProgress: %3d%%", (int)(write_bytes / (float)file_size * 100)); fflush(stdout); } printf("\n"); free(buffer); if (fclose(file) != 0) { perror("fclose"); return -1; } if (app_send_control_packet(fd, CONTROL_FIELD_END, 0, NULL) != 0) { perror("app_send_control_packet"); return -1; } if (!ll_close(fd)) { perror("ll_close"); return -1; } return 0; }
int app_receive_file(const char* term, const char* file_name) { LOG // start link layer int fd = ll_open(term, RECEIVER); if (fd == -1) { perror("ll_open"); return -1; } int ctrlStart; control_param startParams[2]; if (app_receive_control_packet(fd, &ctrlStart, 2, startParams) != 0) { perror("app_receive_control_packet (start)"); return -1; } if (ctrlStart != CONTROL_FIELD_START) { ERRORF("Control field received (%d) is not CONTROL_FIELD_START", ctrlStart); return -1; } DEBUGF("File size to receive: %d", startParams[0].file_size.size.w); DEBUGF("File name to receive: %d", startParams[1].file_name.name); free(startParams[1].file_name.name); FILE* output_file = fopen(file_name, "wb"); if(output_file == NULL) { perror("ERROR: Opening output file"); return -1; } int total_size_read = 0; int seq_number = -1; while (total_size_read != startParams[0].file_size.size.w) { char* buffer; int length; int seq_number_before = seq_number; if (app_receive_data_packet(fd, &seq_number, &buffer, &length) != 0) { perror("app_receive_data_packet"); free(buffer); return -1; } if (seq_number != 0 && seq_number_before + 1 != seq_number) { ERRORF("Expected sequence number %d but got %d", seq_number_before + 1, seq_number); free(buffer); return -1; } total_size_read += length; fwrite(buffer, sizeof(char), length, output_file); free(buffer); } if (fclose(output_file) != 0) { perror("ERROR: Closing output file"); return -1; } int ctrlEnd; if (app_receive_control_packet(fd, &ctrlEnd, 0, NULL) != 0) { perror("app_receive_control_packet (end)"); return -1; } if (ctrlEnd != CONTROL_FIELD_END) { ERRORF("Control field received (%d) is not CONTROL_FIELD_END", ctrlEnd); return -1; } if (!ll_close(fd)) { perror("ll_close"); return -1; } return 0; }
struct task_act * task_select (int *secs_p) { struct connection * cn; struct connection * cn_tmp; struct connection **next_cn; struct task_act * tk; struct task_act **next_tk; struct oper_act * on; int timeout_tmp; char process_edbs = TRUE; char do_timeout; int suspended = FALSE; int xi = 0; struct task_act * ret_tk = NULLTASK; extern char startup_update; struct oper_act * newop = NULLOPER; time (&timenow); (*secs_p) = NOTOK; conns_used = 0; /* DLOG(log_dsap, LLOG_DEBUG, ("task_select connections:")); conn_list_log(connlist); */ for(cn=connlist; cn!=NULLCONN; cn=cn_tmp) { cn_tmp = cn->cn_next; /* Nasty but necessary in conn_extract() manages to get itself called somehow */ do_timeout = FALSE; #ifdef DEBUG conn_log(cn,LLOG_DEBUG); #endif next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { if(tk->tk_timed) { if(tk->tk_timeout <= timenow) { #ifdef DEBUG struct UTCtime ut; struct UTCtime ut2; DLOG(log_dsap, LLOG_TRACE, ("task has timelimit of %ld", tk->tk_timeout)); tm2ut(gmtime(&(tk->tk_timeout)), &ut); DLOG(log_dsap, LLOG_DEBUG, ("converted timelimit = %s", utct2str(&(ut)))); tm2ut(gmtime(&(timenow)), &ut2); DLOG(log_dsap, LLOG_DEBUG, ("time now = %s", utct2str(&(ut2)))); #endif (*next_tk) = tk->tk_next; timeout_task(tk); continue; } else { timeout_tmp = (int) tk->tk_timeout - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } next_tk = &(tk->tk_next); } if(cn->cn_state == CN_OPEN) { next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { next_tk = &(tk->tk_next); if(tk->tk_state == TK_ACTIVE) { if( (ret_tk == NULLTASK) || (tk->tk_prio > ret_tk->tk_prio) || ( (tk->tk_prio == ret_tk->tk_prio) && ( (!ret_tk->tk_timed) || ( (tk->tk_timed) && (tk->tk_timeout < ret_tk->tk_timeout) ) ) ) ) { ret_tk = tk; } } if(tk->tk_state == TK_SUSPEND) { /* * A task suspended to allow the network to be polled. * Set suspended to force polling. */ tk->tk_state = TK_ACTIVE; suspended = TRUE; } } if(cn->cn_tasklist == NULLTASK) { if(cn->cn_initiator) { if(cn->cn_operlist == NULLOPER) { if((cn->cn_last_used + conn_timeout) <= timenow) { do_timeout = TRUE; } else { timeout_tmp = (int) (cn->cn_last_used + conn_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } else { timeout_tmp = conn_timeout; /* safety catch */ if ((tk = cn->cn_operlist->on_task) != NULLTASK) { if (tk->tk_timed) { timeout_tmp = (int) tk->tk_timeout - timenow; if (timeout_tmp < 0) timeout_tmp = 0; } } if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } cn->cn_last_used = timenow; } } } else { cn->cn_last_used = timenow; process_edbs = FALSE; } } else { if((cn->cn_last_used + nsap_timeout) <= timenow) { if ((cn->cn_state == CN_CONNECTING1) || (cn->cn_state == CN_CONNECTING2)) conn_retry(cn,1); else if (cn->cn_state == CN_CLOSING) { if (conn_release_retry(cn) == NOTOK) { /* had its chance - abort */ conn_rel_abort (cn); do_ds_unbind(cn); conn_extract(cn); } } else if ( (cn->cn_state == CN_OPENING) || (cn->cn_state == CN_PRE_OPENING) ) { /* something started to associate - then gave up !!! */ conn_rel_abort (cn); conn_extract (cn); } (*secs_p) = nsap_timeout; } else { timeout_tmp = (int) (cn->cn_last_used + nsap_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } if(do_timeout) { LLOG(log_dsap, LLOG_TRACE, ("Timing out connection %d",cn->cn_ad)); if (conn_release(cn) == NOTOK) { (*secs_p) = nsap_timeout; conns_used++; } } else { conns_used++; } } /* * Open the connection with the highest priority operation * waiting on it... * * Get DSA Info operations are highest priority, followed by * BIND_COMPARE, and X500, and finally GetEDB operations. */ next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= MAX_CONNS) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type == ON_TYPE_GET_DSA_INFO) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI)) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type != ON_TYPE_GET_EDB) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500)) break; (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } } if(process_edbs && !quipu_shutdown) { /* * Nothing is happening that would be disturbed by writing back * a retrieved EDB so it is a good time to process them. */ if (!get_edb_ops && pending_ops) { get_edb_ops = pending_ops; pending_ops = NULLOPER; if(oper_chain(get_edb_ops) != OK) { LLOG(log_dsap, LLOG_TRACE, ("Could not chain a pending operation")); (*secs_p) = 0; /* service network and then try next one */ pending_ops = get_edb_ops -> on_next_task; get_edb_ops -> on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; } } else if (get_edb_ops) { if (get_edb_ops->on_state == ON_COMPLETE) { if (get_edb_ops->on_type == ON_TYPE_GET_EDB) process_edb(get_edb_ops,&newop); else { /* ON_TYPE_SHADOW */ process_shadow(get_edb_ops); ds_res_free (&get_edb_ops-> on_resp.di_result.dr_res.dcr_dsres); } if (newop) { newop->on_next_task = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); if (oper_send_invoke (newop) != OK) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_send getedb next failed")); oper_free (newop); get_edb_ops = NULLOPER; } get_edb_ops = newop; } else if (get_edb_ops) { pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); get_edb_ops = NULLOPER; } (*secs_p) = 0; /* Schedule next one ! */ } else if (get_edb_ops->on_state == ON_ABANDONED) { LLOG (log_dsap,LLOG_TRACE,("Get edb has been abandoned")); pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; (*secs_p) = 0; /* Schedule next one ! */ } } else if (startup_update) { /* see if cache timer has expired - if so resend edb ops... */ if ( (timenow - lastedb_update) >= slave_timeout ) slave_update(); } } if ((get_edb_ops == NULLOPER) && startup_update ) { /* make sure we are awake for the next EDB update */ if ((timeout_tmp = lastedb_update + slave_timeout - timenow) >= 0) if (((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) (*secs_p) = timeout_tmp; } if(suspended) { /* * A task suspended in order for the network to be checked. * Force this to happen by setting the selected task to NULL * and the polling time of the network to 0 secs. */ ret_tk = NULLTASK; (*secs_p) = 0; } for(cn=connwaitlist; cn!=NULLCONN; cn=cn->cn_next) xi++; /* If someting is waiting, see if we can shut a connection down */ /* Make arbitary choice for now */ for(cn=connlist; (xi!=0 || quipu_shutdown) && (cn!=NULLCONN); cn=cn_tmp) { cn_tmp = cn->cn_next; if ((cn->cn_state == CN_OPEN) && (cn->cn_tasklist == NULLTASK) && (cn->cn_initiator) && (cn->cn_operlist == NULLOPER)) { LLOG(log_dsap, LLOG_TRACE, ("Releasing connection %d early (%d waiting)",cn->cn_ad,xi)); if (conn_release(cn) == NOTOK) conns_used++; else xi--; (*secs_p) = 0; /* let connection be re-used */ } } #ifndef NO_STATS if ( (timenow - last_log_close) >= LOGOPENTIME ) { ll_close (log_stat); last_log_close = timenow; } else { if ( (ret_tk == NULLTASK) && (*secs_p >= LOGOPENTIME)) *secs_p = LOGOPENTIME; /* Wake to close log! */ } #endif if(process_edbs && quipu_shutdown) *secs_p = NOTOK; return(ret_tk); }