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;
}
Example #3
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);
}