?? efax.c
字號:
err = msg ("ES2file write:") ; tputcnow ( m, CAN, -1 ) ; msg ("Wdata reception CANcelled") ; } } if ( *nerr ) { if ( *nerr > MAXERRPRT ) msg ("R-+ ....." ) ; msg ("R- : reception errors" ) ; msg ("W- %d reception errors", *nerr ) ; } if ( nr != EOF ) msg ( "Wno RTC" ) ; else while ( tgetd ( m->f, TO_CHAR ) >= 0 ) ; msg ( "I- received %d lines, %d errors", line, *nerr ) ; return err ;}/* Send training check sequence of n zeroes. Returns 0 or 2 on error. */int puttrain ( MODEM *m, const char *s, int n ){ int i, err=0 ; ckcmd ( m, &err, s, TO_FT, CONNECT ) ; if ( ! err ) { ttymode ( m->f, SEND ) ; for ( i=0 ; i<n ; i++ ) { tputc ( 0, m->f, -1 ) ; if ( tobytes ( m->f ) >= MINWRITE ) tflush ( m->f, -1 ) ; } tputs ( m, DLE_ETX, -1 ) ; /* also does tflush() */ ttymode ( m->f, COMMAND ) ; ckcmd ( m, &err, 0, TO_DRAIN, OK ) ; msg ( "I- sent TCF (%d bytes)", n ) ; } return err ;}/* Checks for an error-free run of at least n bytes in the received training check sequence. Returns 0 if check passed, 1 if error-free run was too short, or 3 on other errors. */int gettrain ( MODEM *m, const char *s, int n ) { int err=0, c=0, i=0, maxrunl=0, runl=0 ; ckcmd ( m, &err, s, TO_FT, CONNECT ) ; if ( ! err ) for ( i=0 ; ( c = tgetd ( m->f, TO_CHAR ) ) >= 0 ; i++ ) if ( c ) { if ( runl > maxrunl ) maxrunl = runl ; runl = 0 ; } else { runl ++ ; } if ( runl > maxrunl ) maxrunl = runl ; ckcmd ( m, &err, 0, TO_RTCMD, NO ) ; if ( !err ) { err = maxrunl < n ; msg ( "I- received TCF (%s: run of %d correct in %d bytes)", err ? "failed" : "passed" , maxrunl, i ) ; } return err ;}/* Log a sent/received HDLC frame. Display of these messages is delayed to avoid possible timing problems. */void logfr ( const char *s , const char *nm , u_char *p , int n ){ int i=0 ; msg ( "I- %s %s", s, nm ) ; msg ( n > 10 ? "H- %s %d bytes:" : "H-+ %s %d bytes:" , s, n ) ; for ( i=0 ; i<n ; i++ ) { msg ( "H-+ %02x" , p[i] & 0xff ) ; if ( ( i&0xf ) == 0xf && i != n-1 ) msg ( "H-" ) ; } msg ( "H-") ;}/* Send HDLC control frame of type type. Extra bits can be OR'ed into the frame type (FCF) to indicate that this frame follows a previous one (no +FTH required) and/or that more frames will follow. Sets up flag, address, and fax control field bytes in `buf'. Sends these plus `len` additional bytes. Terminates with DLE-ETX and checks response. Returns 0 if OK, 2 or 3 on error. */#define MORE_FR 0x100 #define SUB_FR 0x200 int putframe ( int type, u_char *buf , int len, MODEM *m, int t ){ int err=0 ; buf [ 0 ] = 0xff ; buf [ 1 ] = type & MORE_FR ? 0xc0 : 0xc8 ; buf [ 2 ] = type & 0xff ; if ( ! ( type & SUB_FR ) ) ckcmd ( m, &err, "+FTH=3" , TO_FT, CONNECT ) ; if ( ! err ) { ttymode ( m->f, SEND ) ; sendbuf ( m, buf, len+3, -1 ) ; tputs ( m, DLE_ETX, -1 ) ; /* and tflush() */ ttymode ( m->f, COMMAND ) ; ckcmd ( m, &err, 0, TO_DRAIN, ( type & MORE_FR ) ? CONNECT : OK ) ; if ( ! err ) logfr ( "sent", frname( type & 0x7f ), buf, len+3 ) ; } return err ;}/* Read HDLC frame and store it in buffer buf of size n. Skips issuing +FRH command on pass==0. Returns length of frame if OK, EOF on timeout, -3 if any errors as per T.30 5.4.2 (too long, FCS error) */int getframe ( MODEM *m, int pass, u_char *buf, int n, int t ){ int err=0, c=0, i=0 ; if ( pass && ( c = cmd ( m, "+FRH=3", t ) ) != CONNECT ) err = ( c == EOF ) ? -EOF : msg ( "E3get frame command failed") ; if ( err == -EOF ) { tputc ( CAN, m->f, t ) ; cmd ( m, "", TO_ABRT ) ; } if ( ! err ) { for ( i=0 ; ( c = tgetd ( m->f, pass ? TO_CHAR : t ) ) >= 0 ; i++ ) if ( i < n ) buf[ i ] = c ; if ( c == EOF ) { err = ( msg ( "E3timed out reading frame data"), -EOF ) ; } else { if ( i >= n ) err = msg ( "E3frame too long (%d bytes)", i ) ; if ( ( c = cmd ( m, 0, TO_RTCMD ) ) != OK && c != CONNECT ) err = msg ( "E3wrong response after frame data" ) ; } } return err ? -err : ( i < n ? i : n ) ;}/* Reverse bit and byte order of ID strings as per T.30 5.3.6.2.4-6 */void revcpy ( u_char *from , u_char *to ){ int i, j ; for ( i=0, j=IDLEN-1 ; i<IDLEN ; i++, j-- ) to [ i ] = normalbits [ from [ j ] & 0xff ] ;}/* Handle procedure interrupt requests (just prints message for now). Returns 0. */int proc_int( void ){ return msg ("W0procedure interrupt request ignored" ) ;}/* Class 1 send. Each received frame elicits an appropriate reply. Optional or unrecognized frames are ignored. Terminates by sending DCN after receiving MCF after EOP or on error. Timeouts, bad frames or CRP repeat last command up to MAXRETRY times. On training check failures the speed (remote capability[BR]) is reduced. The lowest speed is retried MAXTRAIN times. Page transmission failures are retried NTXRETRY times. */enum replies{ NONE=0x100, TXDATA, PPM, SENDDIS } ;int c1send ( MODEM *m, IFILE *f, int pages, cap local, char *localid, char *header, pbmfont *font ) { int err=0, done=0, pass=0, started=0, page=0, frame=NONE, reply=DCN ; int frlen, rxdislen=0, disbit=0, ppm=EOP ; int cmdtry=0, pagetry=0, traintry=0 ; cap remote = { DEFCAP }, session = { DEFCAP } ; char remoteid [ IDLEN + 1 ] ; u_char buf [ MAXFRLEN ], *fif=buf+3 ; for ( pass=started ; ! done ; pass++ ) { if ( err ) { frame = NONE ; } else { frlen = getframe ( m, pass, buf, MAXFRLEN, started ? T3S : T1 ) ; if ( frlen < 3 ) { frame = CRP ; } else { frame = buf [ 2 ] & 0x7f ; logfr ( "received" , frname(frame), buf , frlen ) ; cmdtry = 0 ; } } switch ( frame ) { case CRP: if ( !started || cmdtry++ >= MAXRETRY ) err = msg ( "E3no response from remote" ) ; break ; case NSF: reply = NONE ; break ; case CSI: revcpy ( fif , (u_char*) remoteid ) ; msg ( "I- remote ID=\"%*.*s\"", IDLEN, IDLEN, remoteid ) ; reply = NONE ; break ; case DIS: started = 1 ; disbit = 0x80 ; rxdislen = dislen ( fif ) ; mkcap ( fif, remote, 1 ) ; reply = DCS ; break ; case CFR: reply = TXDATA ; break ; case FTT: if ( (remote[BR] = fallback[session[BR]]) > 0 || traintry++ < MAXTRAIN ) reply = DCS ; else err = msg ( "E1failed to train") ; break ; case PIP: proc_int() ; case RTP: case MCF: page++ ; pagetry=0 ; if ( ppm == MPS && frame == MCF ) reply = TXDATA ; else if ( ppm == EOM ) reply = DCS ; else if ( ppm == EOP ) reply = DCN ; else err = msg ( "E2can't happen(c1send.ppm)" ) ; break ; case PIN: proc_int() ; case RTN: if ( pagetry++ < NTXRETRY ) reply = DCS ; else err = msg( "E2too many page send retries" ) ; break ; case DCN: err = msg ( "E3receiver disconnect") ; break ; case NONE: break ; default: break ; } /* switch ( frame ) */ switch ( err ? DCN : reply ) { case DCS: /* "start of Phase B" */ revcpy ( (u_char*) localid , fif ) ; if ( !err ) err = putframe ( TSI | MORE_FR | disbit, buf, IDLEN, m, -1 ) ; mincap ( local, remote, session ) ; mkdis ( session, fif, rxdislen, 0 ) ; if ( !err ) err = putframe ( DCS | SUB_FR | disbit, buf, rxdislen, m, -1 ) ; ckcmd ( m, &err, "+FTS=8", TO_FT, OK ) ; if ( !err ) err = puttrain ( m, c1cmd[1][1][session[BR]], 1.65 * cps [ session[BR] ] ) ; reply = DCS ; break ; case TXDATA: err = rdpage ( f, ! ( page == 0 || pagetry > 0 ), &ppm, local ) ; ckcmd ( m, &err, c1cmd [1][0][session[BR]], TO_FT, CONNECT ) ; if ( !err ) err = send_data ( m, f, page, pages, local, session, header, font ) ; ckcmd ( m, &err, "+FTS=8", TO_FT, OK ) ; /* fall through */ case PPM: if ( !err ) err = putframe ( ppm | disbit, buf, 0, m, -1 ) ; reply = PPM ; break ; case DCN: putframe ( DCN | disbit, buf, 0, m, -1 ) ; done = 1 ; break ; case NONE: break ; default: err = msg ( "E3can't happen(reply)" ) ; break ; } /* switch ( reply ) */ } /* for ( ! done ) */ return err ;}/* Class 1 receive. Sends DIS until gets DCS/DIS or times out. Sends ppr after ppm and receives data after DCS or MPS. Note: TCF (training check data) is received 75 +/- 20 ms after DCS so there should be no lengthy processing between DCS and gettrain(). */int c1receive ( MODEM *m, OFILE *f, cap local, char *localid, int maxpgerr, int poll ) { int err=0, done=0, started=0, page=0, nerr=0, pass, frlen ; int disbit=0, good=1, nfrerr=0, frame ; u_char buf[MAXFRLEN], *fif=buf+3 ; cap session ; char remoteid [ IDLEN + 1 ] ; err = wrpage ( f, page ) ; for ( pass=0 ; ! err && ! done ; pass++ ) { if ( pass == 0 && ! poll ) { frame = SENDDIS ; } else { frlen = getframe ( m, pass, buf, MAXFRLEN, started ? T2 : poll ? T1 : T4 ) ; if ( frlen >= 3 ) { started = 1 ; nfrerr = 0 ; frame = buf [ 2 ] ; if ( frame != DTC ) frame &= 0x7f ; logfr ( "received" , frname(frame), buf, frlen ) ; } else if ( ! started && ! poll && pass < MAXDIS ) { frame = SENDDIS ; } else if ( ++nfrerr < 3 ) { frame = NONE ; } else { err = msg ( "E3timed out" ) ; frame = DCN ; } } switch ( frame ) { case DIS: disbit = 0x80 ; case CRP: case SENDDIS: revcpy ( (u_char*) localid, fif ) ; if ( !err ) err = putframe ( CSI | disbit | MORE_FR | ( poll || pass ? 0 : SUB_FR ), buf, IDLEN, m, -1 ) ; mkdis ( local, fif, DEFDISLEN, 1 ) ; if ( !err ) err = putframe ( DIS | disbit | SUB_FR, buf, DEFDISLEN, m, -1 ) ; break ; case TSI: ; case CSI: ; revcpy ( fif, (u_char*) remoteid ) ; msg ( "I- remote ID=\"%*.*s\"" , IDLEN, IDLEN, remoteid ) ; break ; case DCS: ; mkcap ( fif, session, 0 ) ; printcap ( "session", session ) ; if ( gettrain ( m, c1cmd [0][1][session[BR]], cps[session[BR]] ) == 0 ) { if ( !err ) err = putframe ( CFR | disbit, buf, 0, m, -1 ) ; if ( !err ) goto getdata ; } else { if ( !err ) err = putframe ( FTT | disbit, buf, 0, m, -1 ) ; } break ; case PRI_EOM: case PRI_MPS: case PRI_EOP: proc_int() ; /* fall through */ case EOM: case MPS: case EOP: err = wrpage ( f, ++page ) ; if ( ! err ) if ( good ) err = putframe ( MCF | disbit, buf, 0, m, -1 ) ; else err = putframe ( RTN | disbit, buf, 0, m, -1 ) ; if ( ! err && good && ( frame == MPS || frame == PRI_MPS ) ) goto getdata ; if ( ! err && good && ( frame == EOM || frame == PRI_EOM ) ) { ckcmd ( m, &err, "+FTS=8", TO_FT, OK ) ; } break ; getdata: ckcmd ( m, &err, c1cmd [0][0][session[BR]] , TO_FT, CONNECT ) ; if ( !err ) err = receive_data ( m, f, session, &nerr ) ; good = nerr < maxpgerr ; if ( good ) msg ( "ITreceived -> %s", f->cfname ) ; ckcmd ( m, &err, 0, TO_C2EOR, NO ) ; break ; case DTC: /* no poll server yet */ putframe ( DCN, buf, 0, m, -1 ) ; done=1 ; break ; case DCN: done = 1 ; break; case NONE:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -