isdn4k-utils/eurofile/src/eft/eft.c

346 lines
8.6 KiB
C

/* $Id: eft.c,v 1.1 1999/06/30 17:18:11 he Exp $ */
/*
Copyright 1998 by Henner Eisen
This code is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <tdu_user.h>
#include "tdu.h"
#include <eft.h>
#include "eft_private.h"
#include "fileheader.h"
#include <malloc.h>
#include <netdb.h>
#include "extra_version_.h"
/* Table with extended reason codes for EUROFile */
static struct tdu_descr re_descr[] = {
{"identifier rejected", EFT_RE_ID_REJECTED,0},
{"disk full", EFT_RE_DISK_FULL,0},
{"file access impossible", EFT_RE_FILE_ACCESS_IMPOSSIBLE,0},
{"reserved", EFT_RE_RESERVED,0},
{"user interrupt of communication", EFT_RE_USER_INTERRUPT,0},
{"user abort", EFT_RE_USER_ABORT,0},
{"extended format not available", EFT_RE_NO_EXTENDED_FMT,0},
{"log access impossible", EFT_RE_NO_LOG_ACCESS,0},
{"compression format not supported", EFT_RE_CMPR_FMT_NOT_SUPPORTED,0},
{"incorrect recovery FCS", EFT_RE_WRONG_FCS,0},
{"coding error in compressed data", EFT_RE_CMPR_CODING_ERROR,0},
{NULL, 0,0}
};
/* ETS 300 383 (1995) Annex D.2 */
const char *eft_signature="EUROSFT92/1/UNIX/eftp4linux/" E4L_VERSION E4L_EXTRA_VERSION_REV E4L_EXTRA_VERSION_CHANGED;
const char * eft_str_reason(int reason)
{
return tdu_str_reason(reason);
}
const char * eft_str_other_reason(int reason)
{
static const char unknown[] = "Unknown_EftOtherReason_Code";
char * des = tdu_des(re_descr,reason);
return des ? des : unknown;
}
/*
* Set the address (used as local called/calling address parameter in
* T-Associate request and confirmation.
*
* returns 0 on success or something else when string is too long;
*/
int eft_set_address(struct eft * eft, char * address)
{
int ret=0;
if(address){
if(strlen(address)>TDU_PLEN_ADDR){
fprintf(stderr,"eftd: address \"%s\" too long (truncated at %d chars).\n", address, TDU_PLEN_ADDR);
ret = -1;
}
strncpy(eft->address,address,TDU_PLEN_ADDR);
eft->address[TDU_PLEN_ADDR]=0;
} else {
eft->address = NULL;
}
return ret;
}
char * eft_re_descr(int re)
{
return tdu_des(re_descr,re);
}
int eft_attach_socket(struct eft *eft, int s)
{
eft->fsm->socket = s;
return 0;
}
int eft_get_socket(struct eft *eft)
{
return eft->fsm->socket;
}
int eft_is_up(struct eft * eft)
{
return eft->fsm->up;
}
int eft_select( struct eft *eft, int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
tdu_printf(TDU_LOG_TRC,"eft_select()\n");
return tdu_select(eft->fsm, n, readfds, writefds, exceptfds,
timeout);
}
void eft_print_time( struct tdu_fsm * fsm )
{
struct transfer_regime *tr = & fsm->transfer;
int usec;
double sec;
usec = ( tr->tv_end.tv_usec - tr->tv_begin.tv_usec );
sec = ( tr->tv_end.tv_sec - tr->tv_begin.tv_sec )
+ usec / 1000000.0;
if( usec < 0 ) sec += 1.0;
printf("%d packets, %d bytes transferred in %f seconds (%f bytes/sec)\n",
tr->pkt_cnt, tr->byte_cnt,
sec, tr->byte_cnt/sec );
printf("(%d bytes file header, %d bytes data)\n", fsm->stream->hdr.len,
tr->byte_cnt - fsm->stream->hdr.len);
}
/*
* private, no function beside eft_make_instance should need to know about
* this
*/
struct eft_instance{
struct eft h; /* handle for eft machine */
struct tdu_stream eft_tdu_stream;
struct tdu_user eft_tdu_user;
struct tdu_fsm eft_tdu_fsm;
struct fileheader_par eft_fh;
#define MAX_ISDN_NO 20
unsigned char isdn_no[MAX_ISDN_NO+1] /* of peer*/;
unsigned char user_name[TDU_PLEN_IDENT+1] /* of peer*/;
char address[TDU_PLEN_ADDR+1]; /* T_ASSOCICATE parameter */
};
/*
* Set the default address of the eft instance
* (contributed by Matthias Stolte <ms@msdatec.de>; slightly modified)
*/
static void set_default_address(struct eft * eft)
{
char hostname[TDU_PLEN_ADDR+1];
struct hostent *phinfo;
if (0 == gethostname(hostname, sizeof(hostname))) {
phinfo = gethostbyname(hostname);
if (NULL == phinfo) {
herror(hostname);
}
else {
eft_set_address(eft, phinfo->h_name);
/* FIXME: user defineable log mask isn't read until now */
tdu_printf(TDU_LOG_LOG, "address set to \"%s\" initially\n", eft->address);
}
}
else
perror("gethostname");
}
struct eft * eft_make_instance()
{
struct eft_instance * p;
p=malloc(sizeof(*p));
if( ! p ) return NULL;
memset(p,0,sizeof(*p));
p->h.ts = & p-> eft_tdu_stream;
p->h.fsm = & p-> eft_tdu_fsm;
p->h.usr = & p-> eft_tdu_user;
p->h.fh = & p-> eft_fh;
p->eft_tdu_stream.fsm = p->h.fsm;
p->eft_tdu_fsm.stream = p->h.ts;
p->eft_tdu_user.fsm = p->h.fsm;
p->eft_tdu_fsm.user = p->h.usr;
p->h.usr->priv = & p->h;
p->h.isdn_no = p->isdn_no;
p->h.user_name = p->user_name;
p->h.tmp_fd = eft_make_tmp();
p->h.address = p->address;
set_default_address(&p->h);
return &p->h;
/* FIXME: what about/ where should go file header stuff */
}
int eft_release(struct eft * eft)
{
struct tdu_fsm * fsm = eft->ts->fsm;
tdu_printf(TDU_LOG_TRC, "eft_release_req()\n");
if( tdu_release_req(fsm) >= 0) return -1;
tdu_wait_for_release( fsm, 0 );
return 0;
}
int eft_msg(struct eft * eft, unsigned char * msg)
{
struct tdu_fsm * fsm = eft->ts->fsm;
return tdu_typed_data_req(fsm,msg);
}
struct tdu_user * eft_get_user(struct eft *eft)
{
return eft->fsm->user;
}
int eft_msg2stdout(struct tdu_user * ts, struct tdu_param* par)
{
par->par.udata->udata[par->par.udata->udata_len] = 0;
printf( "EFT-Message: %s\n", par->par.udata->udata);
tdu_printf(TDU_LOG_AP2, "MSG: message=\"%s\"\n", par->par.udata->udata);
return 0;
}
int eft_remote_has_navigation(struct eft * eft)
{
struct tdu_access_param * r_par = & eft->fsm->access.remote;
if ( r_par->udata_len < 3 ) return 0;
return r_par->udata[3] == 0x4f;
}
void eft_stream_init_fd(struct eft * eft, int fd, int close)
{
struct tdu_stream * ts = eft->ts;
tdu_stream_init_fd(ts,fd,close);
ts->hdr.data = eft->fh;
ts->hdr.read = tdu_fh_get_fd_hdr;
#if 1
ts->hdr.parse = tdu_fh_parse;
#endif
}
void eft_stream_set_stat(struct eft * eft, struct stat * s)
{
eft->fh->fh_s = *s;
eft->fh->fh_xdirrec = 0;
}
void eft_stream_set_names(struct eft * eft, unsigned char * t_name,
unsigned char * name, int type)
{
tdu_printf(TDU_LOG_TRC,"eft_stream_set_names(): class=%d\n",type);
strcpy(eft->fh->fh_t_name, t_name);
strcpy(eft->fh->fh_name, name);
eft->fh->fh_type = type;
}
#if 0
void eft_stream_set_length(struct eft * eft, int l)
{
eft->fh->fh_s.st_size = l;
}
#endif
/*
* associate a peer's phone number with the eft object
*/
void eft_add_peer_phone(struct eft *eft , unsigned char * str)
{
strncpy(eft->isdn_no,str,MAX_ISDN_NO);
eft->isdn_no[MAX_ISDN_NO]=0;
}
/*
* retrun a string pointer to the peer's phone number
*/
unsigned char * eft_peer_phone(struct eft *eft)
{
return eft->isdn_no;
}
void eft_set_flags(struct eft * eft, long flags)
{
eft -> flags = flags;
}
long eft_get_flags(struct eft * eft)
{
return eft -> flags;
}
void eft_set_xferlog(struct eft * eft, int fd)
{
eft -> xferlog = fd;
/* tdu_printf(TDU_LOG_TMP, "xferlog now %d\n",eft->xferlog); */
}
/*
* copy the called address (as returned in called address parameter of
* T-Associate response) with possible unprintable characters replaced
* to a destinatiion array called[]. It must be at least of size
* TDU_PLEN_ADDR+1.
*/
int eft_printable_called_addr(struct eft * eft, unsigned char *called)
{
tdu_mk_printable(called,eft->fsm->assoc.remote.called_addr,
eft->fsm->assoc.remote.called_len);
return eft->fsm->assoc.remote.called_len;
}
/*
* copy the association user data (as returned in called address parameter
* with T-Associate response) with possible unprintable character replaced
* to a destinatiion array udata[]. It must be at least of size
* TDU_PLEN_UDATA+1.
*
*/
int eft_printable_assoc_udata(struct eft * eft,
unsigned char *udata)
{
tdu_mk_printable(udata,eft->fsm->assoc.remote.udata,
eft->fsm->assoc.remote.udata_len);
return eft->fsm->assoc.remote.udata_len;
}